ENH: Optimize and design the time-lapse wiper tower

Multiplex existing wipe tower and revert old time-lapse wipe tower code

Change-Id: Ia1cba9808647ea900f691b2c5d5887077be12d89
(cherry picked from commit 61f41df572d11b7cc738c34f2624fd123cd9a6df)
This commit is contained in:
zhimin.zeng 2022-08-15 14:41:28 +08:00 committed by Lane.Wei
parent a26c573b1b
commit f745c5fea2
21 changed files with 172 additions and 183 deletions

View file

@ -375,7 +375,6 @@ public:
bool is_modifier : 1;
// Wheter or not this volume has been generated from the wipe tower
bool is_wipe_tower : 1;
bool is_timelapse_wipe_tower : 1;
// Wheter or not this volume has been generated from an extrusion path
bool is_extrusion_path : 1;
// Wheter or not to always render this volume using its own alpha

View file

@ -3000,7 +3000,8 @@ void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_p
const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2);
const PrintConfig& config = print.config();
if (extruders_count > 1 && config.enable_prime_tower && (config.print_sequence == PrintSequence::ByLayer)) {
if (print.enable_timelapse_print()
|| (extruders_count > 1 && config.enable_prime_tower && (config.print_sequence == PrintSequence::ByLayer))) {
const float depth = print.wipe_tower_data(extruders_count).depth;
const float brim_width = print.wipe_tower_data(extruders_count).brim_width;

View file

@ -1925,7 +1925,11 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
bool wt = dynamic_cast<const ConfigOptionBool*>(m_config->option("enable_prime_tower"))->value;
auto co = dynamic_cast<const ConfigOptionEnum<PrintSequence>*>(m_config->option<ConfigOptionEnum<PrintSequence>>("print_sequence"));
if (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject) {
const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
const ConfigOption * option = dconfig.option("timelapse_no_toolhead");
bool timelapse_enabled = option ? option->getBool() : false;
if (timelapse_enabled || (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject)) {
for (int plate_id = 0; plate_id < n_plates; plate_id++) {
DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config;
float x = dynamic_cast<const ConfigOptionFloats*>(proj_cfg.option("wipe_tower_x"))->get_at(plate_id);
@ -3827,32 +3831,6 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type)
}
}
#if 1
// BBS: update Timelapse Wipe Tower according to max height
for (unsigned int obj_idx = 0; obj_idx < (unsigned int) m_model->objects.size(); ++obj_idx) {
ModelObject *model_object = m_model->objects[obj_idx];
if (model_object->is_timelapse_wipe_tower) {
for (GLVolume *volume : m_volumes.volumes) {
if (volume->composite_id.object_id == obj_idx) {
int instance_idx = volume->instance_idx();
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
double max_height = curr_plate->estimate_timelapse_wipe_tower_height();
float z_factor = max_height / model_object->raw_mesh_bounding_box().size()[2];
volume->set_instance_scaling_factor(Vec3d(1.0, 1.0, z_factor));
model_object->instances[instance_idx]->set_scaling_factor(Vec3d(1.0, 1.0, z_factor));
volume->is_timelapse_wipe_tower = true;
break;
}
}
ensure_on_bed(obj_idx, false);
model_object->invalidate_bounding_box();
break;
}
}
#endif
//BBS: notify instance updates to part plater list
m_selection.notify_instance_update(-1, -1);

View file

@ -459,15 +459,6 @@ wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType ty
[type, item](wxCommandEvent&) { obj_list()->load_generic_subobject(item, type); }, "", menu);
}
// BBS: only add timelapse tower item for plate
if (type == ModelVolumeType::INVALID) {
auto item = L("Timelapse Wipe Tower");
type = ModelVolumeType::TIMELAPSE_WIPE_TOWER;
append_menu_item(sub_menu, wxID_ANY, _(item), "",
[type, item](wxCommandEvent &) { obj_list()->load_generic_subobject(item, type); }, "", menu,
[]() { return plater()->can_add_timelapse_wt(); }, m_parent);
}
return sub_menu;
}

View file

@ -1869,7 +1869,7 @@ static TriangleMesh create_mesh(const std::string& type_name, const BoundingBoxf
const double side = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.1);
indexed_triangle_set mesh;
if (type_name == "Cube" || type_name == "Timelapse Wipe Tower")
if (type_name == "Cube")
// Sitting on the print bed, left front front corner at (0, 0).
mesh = its_make_cube(side, side, side);
else if (type_name == "Cylinder")
@ -1897,10 +1897,6 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
load_shape_object(type_name);
return;
}
else if (type == ModelVolumeType::TIMELAPSE_WIPE_TOWER) {
load_shape_object(type_name, true);
return;
}
const int obj_idx = get_selected_obj_idx();
if (obj_idx < 0)
@ -2004,7 +2000,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode
}
}
void ObjectList::load_shape_object(const std::string &type_name, bool is_timelapse_wt)
void ObjectList::load_shape_object(const std::string &type_name)
{
const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
//assert(selection.get_object_idx() == -1); // Add nothing is something is selected on 3DScene
@ -2021,11 +2017,11 @@ void ObjectList::load_shape_object(const std::string &type_name, bool is_timelap
BoundingBoxf3 bb;
TriangleMesh mesh = create_mesh(type_name, bb);
// BBS: remove "Shape" prefix
load_mesh_object(mesh, _(type_name), true, is_timelapse_wt);
load_mesh_object(mesh, _(type_name));
wxGetApp().mainframe->update_title();
}
void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center, bool is_timelapse_wt)
void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center)
{
// Add mesh to model as a new object
Model& model = wxGetApp().plater()->model();
@ -2049,27 +2045,11 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name
new_object->invalidate_bounding_box();
new_object->translate(-bb.center());
if (is_timelapse_wt) {
new_object->is_timelapse_wipe_tower = true;
auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate();
int highest_extruder = 0;
double max_height = curr_plate->estimate_timelapse_wipe_tower_height(&highest_extruder);
new_object->scale(1, 1, max_height / new_object->bounding_box().size()[2]);
// BBS: find an empty cell to put the copied object
auto start_point = wxGetApp().plater()->build_volume().bounding_volume2d().center();
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)});
// move to garbage bin of curr plate
auto offset = curr_plate->get_origin() + Vec3d(80.0, 230.0, -new_object->origin_translation.z());
new_object->instances[0]->set_offset(offset);
new_object->config.set_key_value("sparse_infill_density", new ConfigOptionPercent(0));
new_object->config.set_key_value("top_shell_layers", new ConfigOptionInt(0));
new_object->config.set("extruder", highest_extruder);
} else {
// BBS: find an empty cell to put the copied object
auto start_point = wxGetApp().plater()->build_volume().bounding_volume2d().center();
auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)});
new_object->instances[0]->set_offset(center ? to_3d(Vec2d(empty_cell(0), empty_cell(1)), -new_object->origin_translation.z()) : bb.center());
}
new_object->instances[0]->set_offset(center ? to_3d(Vec2d(empty_cell(0), empty_cell(1)), -new_object->origin_translation.z()) : bb.center());
new_object->ensure_on_bed();
@ -2765,11 +2745,6 @@ bool ObjectList::can_merge_to_multipart_object() const
for (wxDataViewItem item : sels) {
if (!(m_objects_model->GetItemType(item) & (itObject | itInstance)))
return false;
// BBS: do not support to merge timelapse wipe tower with other objects
ObjectDataViewModelNode* node = static_cast<ObjectDataViewModelNode*>(item.GetID());
if (node != nullptr && node->IsTimelapseWipeTower())
return false;
}
return true;

View file

@ -279,8 +279,8 @@ public:
//void load_part(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery = false);
void load_modifier(const wxArrayString& input_files, ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery = false);
void load_generic_subobject(const std::string& type_name, const ModelVolumeType type);
void load_shape_object(const std::string &type_name, bool is_timelapse_wt = false);
void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true, bool is_timelapse_wt = false);
void load_shape_object(const std::string &type_name);
void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true);
void del_object(const int obj_idx, bool refresh_immediately = true);
void del_subobject_item(wxDataViewItem& item);
void del_settings_from_config(const wxDataViewItem& parent_item);

View file

@ -333,18 +333,6 @@ void ObjectDataViewModelNode::SetPlateIdx(const int& idx)
m_plate_idx = idx;
}
// BBS
bool ObjectDataViewModelNode::IsTimelapseWipeTower() const
{
if (m_model_object == nullptr)
return false;
if (!(m_type & itObject) && !(m_type & itInstance))
return false;
return m_model_object->is_timelapse_wipe_tower;
}
void ObjectDataViewModelNode::UpdateExtruderAndColorIcon(wxString extruder /*= ""*/)
{
if (m_type == itVolume && m_volume_type != ModelVolumeType::MODEL_PART && m_volume_type != ModelVolumeType::PARAMETER_MODIFIER)

View file

@ -227,7 +227,6 @@ public:
bool HasSupportPainting() const { return m_support_enable; }
bool IsActionEnabled() const { return m_action_enable; }
void UpdateExtruderAndColorIcon(wxString extruder = "");
bool IsTimelapseWipeTower() const;
// use this function only for childrens
void AssignAllVal(ObjectDataViewModelNode& from_node)

View file

@ -1103,8 +1103,12 @@ Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volu
}
wipe_tower_size(2) = max_height;
const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
const ConfigOption* option = dconfig.option("timelapse_no_toolhead");
bool timelapse_enabled = option ? option->getBool() : false;
double depth = wipe_volume * (plate_extruders.size() - 1) / (layer_height * w);
if (depth > EPSILON) {
if (timelapse_enabled || depth > EPSILON) {
float min_wipe_tower_depth = 0.f;
auto iter = WipeTower::min_depth_per_height.begin();
while (iter != WipeTower::min_depth_per_height.end()) {
@ -1142,26 +1146,6 @@ Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volu
return wipe_tower_size;
}
double PartPlate::estimate_timelapse_wipe_tower_height(int *highest_extruder_id) const
{
double max_height = 0;
int highest_extruder = 0;
// auto m_model = wxGetApp().plater()->get_obj
for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) {
if (!contain_instance_totally(obj_idx, 0)) continue;
if (m_model->objects[obj_idx]->is_timelapse_wipe_tower) continue;
BoundingBoxf3 bbox = m_model->objects[obj_idx]->bounding_box();
if (bbox.size().z() > max_height) {
max_height = bbox.size().z();
highest_extruder = m_model->objects[obj_idx]->config.opt_int("extruder");
}
}
if (highest_extruder_id) *highest_extruder_id = highest_extruder;
return max_height;
}
bool PartPlate::operator<(PartPlate& plate) const
{
int index = plate.get_index();
@ -1636,33 +1620,6 @@ void PartPlate::move_instances_to(PartPlate& left_plate, PartPlate& right_plate,
return;
}
//can add timelapse object
bool PartPlate::can_add_timelapse_object()
{
bool result = true;
if (obj_to_instance_set.size() == 0)
return false;
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
{
int obj_id = it->first;
if (obj_id >= m_model->objects.size())
continue;
ModelObject* object = m_model->objects[obj_id];
if (object->is_timelapse_wipe_tower)
{
result = false;
break;
}
}
return result;
}
void PartPlate::generate_logo_polygon(ExPolygon &logo_polygon)
{
if (m_shape.size() == 4)

View file

@ -238,7 +238,6 @@ public:
Vec3d get_origin() { return m_origin; }
Vec3d estimate_wipe_tower_size(const double w, const double wipe_volume) const;
double estimate_timelapse_wipe_tower_height(int* highest_extruder_id=NULL) const;
std::vector<int> get_extruders() const;
/* instance related operations*/
@ -278,9 +277,6 @@ public:
//move instances to left or right PartPlate
void move_instances_to(PartPlate& left_plate, PartPlate& right_plate, BoundingBoxf3* bounding_box = nullptr);
//can add timelapse object
bool can_add_timelapse_object();
/*rendering related functions*/
const Pointfs& get_shape() const { return m_shape; }
bool set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Vec2d position, float height_to_lid, float height_to_rod);

View file

@ -1785,7 +1785,6 @@ struct Plater::priv
// Sets m_bed.m_polygon to limit the object placement.
//BBS: add bed exclude area
void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false);
bool can_add_timelapse_wt() const;
bool can_delete() const;
bool can_delete_all() const;
@ -5930,16 +5929,6 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_ar
}
}
bool Plater::priv::can_add_timelapse_wt() const {
const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
const ConfigOption* option = dconfig.option("timelapse_no_toolhead");
bool timelapse_enabled = option?option->getBool():false;
PartPlate* curr_plate = q->get_partplate_list().get_curr_plate();
return timelapse_enabled && curr_plate->can_add_timelapse_object();
}
bool Plater::priv::can_delete() const
{
return !get_selection().is_empty() && !get_selection().is_wipe_tower();
@ -9836,7 +9825,6 @@ void Plater::show_status_message(std::string s)
BOOST_LOG_TRIVIAL(trace) << "show_status_message:" << s;
}
bool Plater::can_add_timelapse_wt() const { return p->can_add_timelapse_wt(); } // BBS
bool Plater::can_delete() const { return p->can_delete(); }
bool Plater::can_delete_all() const { return p->can_delete_all(); }
bool Plater::can_add_model() const { return !is_background_process_slicing(); }

View file

@ -417,7 +417,6 @@ public:
//BBS:
void fill_color(int extruder_id);
bool can_add_timelapse_wt() const;
bool can_delete() const;
bool can_delete_all() const;

View file

@ -1374,11 +1374,9 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
if (opt_key == "enable_prime_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" )
update_wiping_button_visibility();
//popup message dialog when first selected
if (opt_key == "timelapse_no_toolhead" && boost::any_cast<bool>(value))
show_timelapse_warning_dialog();
// reload scene to update timelapse wipe tower
if (opt_key == "timelapse_no_toolhead")
wxGetApp().plater()->update();
// BBS
#if 0