mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-13 17:58:03 -06:00
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:
parent
a26c573b1b
commit
f745c5fea2
21 changed files with 172 additions and 183 deletions
|
@ -553,11 +553,6 @@ bool GCode::gcode_label_objects = false;
|
|||
std::string WipeTowerIntegration::tool_change(GCode& gcodegen, int extruder_id, bool finish_layer)
|
||||
{
|
||||
std::string gcode;
|
||||
assert(m_layer_idx >= 0);
|
||||
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (m_layer_idx < (int)m_tool_changes.size()) {
|
||||
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
|
||||
// Calculate where the wipe tower layer will be printed. -1 means that print z will not change,
|
||||
// resulting in a wipe tower with sparse layers.
|
||||
|
@ -570,6 +565,18 @@ bool GCode::gcode_label_objects = false;
|
|||
wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height;
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && m_is_first_print) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][0], m_tool_changes[m_layer_idx][0].new_tool, wipe_tower_z);
|
||||
m_tool_change_idx++;
|
||||
m_is_first_print = false;
|
||||
}
|
||||
|
||||
assert(m_layer_idx >= 0);
|
||||
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (m_layer_idx < (int)m_tool_changes.size()) {
|
||||
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
|
||||
if (!ignore_sparse) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z);
|
||||
m_last_wipe_tower_print_z = wipe_tower_z;
|
||||
|
@ -2781,6 +2788,9 @@ GCode::LayerResult GCode::process_layer(
|
|||
}
|
||||
} // for objects
|
||||
|
||||
if (m_wipe_tower)
|
||||
m_wipe_tower->set_is_first_print(true);
|
||||
|
||||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
std::vector<std::unique_ptr<EdgeGrid::Grid>> lower_layer_edge_grids(layers.size());
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
|
|
|
@ -82,7 +82,9 @@ public:
|
|||
m_layer_idx(-1),
|
||||
m_tool_change_idx(0),
|
||||
m_plate_origin(plate_origin),
|
||||
m_single_extruder_multi_material(print_config.single_extruder_multi_material)
|
||||
m_single_extruder_multi_material(print_config.single_extruder_multi_material),
|
||||
m_enable_timelapse_print(print_config.timelapse_no_toolhead.value),
|
||||
m_is_first_print(true)
|
||||
{}
|
||||
|
||||
std::string prime(GCode &gcodegen);
|
||||
|
@ -91,6 +93,11 @@ public:
|
|||
std::string finalize(GCode &gcodegen);
|
||||
std::vector<float> used_filament_length() const;
|
||||
|
||||
bool is_first_print() const { return m_is_first_print;}
|
||||
void set_is_first_print(bool is) { m_is_first_print = is; }
|
||||
|
||||
bool enable_timelapse_print() const { return m_enable_timelapse_print; }
|
||||
|
||||
private:
|
||||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||
std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const;
|
||||
|
@ -117,6 +124,8 @@ private:
|
|||
// BBS
|
||||
Vec3d m_plate_origin;
|
||||
bool m_single_extruder_multi_material;
|
||||
bool m_enable_timelapse_print;
|
||||
bool m_is_first_print;
|
||||
};
|
||||
|
||||
class ColorPrintColors
|
||||
|
|
|
@ -544,7 +544,8 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi
|
|||
m_travel_speed(config.travel_speed),
|
||||
m_current_tool(initial_tool),
|
||||
//wipe_volumes(flush_matrix)
|
||||
m_wipe_volume(prime_volume)
|
||||
m_wipe_volume(prime_volume),
|
||||
m_enable_timelapse_print(config.timelapse_no_toolhead.value)
|
||||
{
|
||||
// Read absolute value of first layer speed, if given as percentage,
|
||||
// it is taken over following default. Speeds from config are not
|
||||
|
@ -1305,6 +1306,9 @@ void WipeTower::plan_tower()
|
|||
}
|
||||
|
||||
{
|
||||
if (m_enable_timelapse_print && max_depth < EPSILON)
|
||||
max_depth = min_wipe_tower_depth;
|
||||
|
||||
if (max_depth + EPSILON < min_wipe_tower_depth)
|
||||
m_extra_spacing = min_wipe_tower_depth / max_depth;
|
||||
else
|
||||
|
@ -1343,9 +1347,13 @@ void WipeTower::plan_tower()
|
|||
for (auto& layer : m_plan)
|
||||
layer.depth = 0.f;
|
||||
|
||||
float max_depth_for_all = 0;
|
||||
for (int layer_index = int(m_plan.size()) - 1; layer_index >= 0; --layer_index)
|
||||
{
|
||||
float this_layer_depth = std::max(m_plan[layer_index].depth, m_plan[layer_index].toolchanges_depth());
|
||||
if (m_enable_timelapse_print && this_layer_depth < EPSILON)
|
||||
this_layer_depth = min_wipe_tower_depth;
|
||||
|
||||
m_plan[layer_index].depth = this_layer_depth;
|
||||
|
||||
if (this_layer_depth > m_wipe_tower_depth - m_perimeter_width)
|
||||
|
@ -1356,6 +1364,15 @@ void WipeTower::plan_tower()
|
|||
if (m_plan[i].depth - this_layer_depth < 2*m_perimeter_width )
|
||||
m_plan[i].depth = this_layer_depth;
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && layer_index == 0)
|
||||
max_depth_for_all = m_plan[0].depth;
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print) {
|
||||
for (int i = int(m_plan.size()) - 1; i >= 0; i--) {
|
||||
m_plan[i].depth = max_depth_for_all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1474,17 +1491,25 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
|
|||
// BBS: consider both soluable and support properties
|
||||
int idx = first_toolchange_to_nonsoluble_nonsupport (layer.tool_changes);
|
||||
ToolChangeResult finish_layer_tcr;
|
||||
ToolChangeResult timelapse_wall;
|
||||
|
||||
if (idx == -1) {
|
||||
// if there is no toolchange switching to non-soluble, finish layer
|
||||
// will be called at the very beginning. That's the last possibility
|
||||
// where a nonsoluble tool can be.
|
||||
finish_layer_tcr = finish_layer();
|
||||
if (m_enable_timelapse_print) {
|
||||
timelapse_wall = only_generate_out_wall();
|
||||
}
|
||||
finish_layer_tcr = finish_layer(m_enable_timelapse_print ? false : true);
|
||||
}
|
||||
|
||||
for (int i=0; i<int(layer.tool_changes.size()); ++i) {
|
||||
if (i == 0 && m_enable_timelapse_print) {
|
||||
timelapse_wall = only_generate_out_wall();
|
||||
}
|
||||
|
||||
if (i == idx) {
|
||||
layer_result.emplace_back(tool_change(layer.tool_changes[i].new_tool, true));
|
||||
layer_result.emplace_back(tool_change(layer.tool_changes[i].new_tool, m_enable_timelapse_print ? false : true));
|
||||
// finish_layer will be called after this toolchange
|
||||
finish_layer_tcr = finish_layer(false);
|
||||
}
|
||||
|
@ -1504,8 +1529,57 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
|
|||
layer_result[idx] = merge_tcr(layer_result[idx], finish_layer_tcr);
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print) {
|
||||
layer_result.insert(layer_result.begin(), std::move(timelapse_wall));
|
||||
}
|
||||
|
||||
result.emplace_back(std::move(layer_result));
|
||||
}
|
||||
}
|
||||
|
||||
WipeTower::ToolChangeResult WipeTower::only_generate_out_wall()
|
||||
{
|
||||
size_t old_tool = m_current_tool;
|
||||
|
||||
m_extrusion_flow = 0.038f; // hard code
|
||||
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
|
||||
writer.set_extrusion_flow(m_extrusion_flow)
|
||||
.set_z(m_z_pos)
|
||||
.set_initial_tool(m_current_tool)
|
||||
.set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f));
|
||||
|
||||
// Slow down on the 1st layer.
|
||||
bool first_layer = is_first_layer();
|
||||
// BBS: speed up perimeter speed to 90mm/s for non-first layer
|
||||
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : 5400.f;
|
||||
float fill_box_y = m_layer_info->toolchanges_depth() + m_perimeter_width;
|
||||
box_coordinates fill_box(Vec2f(m_perimeter_width, fill_box_y), m_wipe_tower_width - 2 * m_perimeter_width, m_layer_info->depth - fill_box_y);
|
||||
|
||||
writer.set_initial_position((m_left_to_right ? fill_box.ru : fill_box.lu), // so there is never a diagonal travel
|
||||
m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
|
||||
|
||||
bool toolchanges_on_layer = m_layer_info->toolchanges_depth() > WT_EPSILON;
|
||||
|
||||
// we are in one of the corners, travel to ld along the perimeter:
|
||||
if (writer.x() > fill_box.ld.x() + EPSILON) writer.travel(fill_box.ld.x(), writer.y());
|
||||
if (writer.y() > fill_box.ld.y() + EPSILON) writer.travel(writer.x(), fill_box.ld.y());
|
||||
|
||||
// outer perimeter (always):
|
||||
// BBS
|
||||
box_coordinates wt_box(Vec2f(0.f, (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)), m_wipe_tower_width, m_layer_info->depth + m_perimeter_width);
|
||||
wt_box = align_perimeter(wt_box);
|
||||
writer.rectangle(wt_box, feedrate);
|
||||
|
||||
// Now prepare future wipe. box contains rectangle that was extruded last (ccw).
|
||||
Vec2f target = (writer.pos() == wt_box.ld ? wt_box.rd : (writer.pos() == wt_box.rd ? wt_box.ru : (writer.pos() == wt_box.ru ? wt_box.lu : wt_box.ld)));
|
||||
writer.add_wipe_point(writer.pos()).add_wipe_point(target);
|
||||
|
||||
// Ask our writer about how much material was consumed.
|
||||
// Skip this in case the layer is sparse and config option to not print sparse layers is enabled.
|
||||
if (!m_no_sparse_layers || toolchanges_on_layer)
|
||||
if (m_current_tool < m_used_filament_length.size()) m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length();
|
||||
|
||||
return construct_tcr(writer, false, old_tool, true, 0.f);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -152,6 +152,8 @@ public:
|
|||
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
|
||||
void generate(std::vector<std::vector<ToolChangeResult>> &result);
|
||||
|
||||
WipeTower::ToolChangeResult only_generate_out_wall();
|
||||
|
||||
float get_depth() const { return m_wipe_tower_depth; }
|
||||
float get_brim_width() const { return m_wipe_tower_brim_width_real; }
|
||||
|
||||
|
@ -263,7 +265,7 @@ private:
|
|||
return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point
|
||||
}
|
||||
|
||||
|
||||
bool m_enable_timelapse_print = false;
|
||||
bool m_semm = true; // Are we using a single extruder multimaterial printer?
|
||||
Vec2f m_wipe_tower_pos; // Left front corner of the wipe tower in mm.
|
||||
float m_wipe_tower_width; // Width of the wipe tower.
|
||||
|
|
|
@ -237,8 +237,7 @@ enum class ModelVolumeType : int {
|
|||
NEGATIVE_VOLUME,
|
||||
PARAMETER_MODIFIER,
|
||||
SUPPORT_BLOCKER,
|
||||
SUPPORT_ENFORCER,
|
||||
TIMELAPSE_WIPE_TOWER
|
||||
SUPPORT_ENFORCER
|
||||
};
|
||||
|
||||
enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower, CutToParts };
|
||||
|
@ -271,7 +270,6 @@ public:
|
|||
LayerHeightProfile layer_height_profile;
|
||||
// Whether or not this object is printable
|
||||
bool printable;
|
||||
bool is_timelapse_wipe_tower = false;
|
||||
|
||||
// This vector holds position of selected support points for SLA. The data are
|
||||
// saved in mesh coordinates to allow using them for several instances.
|
||||
|
|
|
@ -1575,6 +1575,9 @@ void Print::finalize_first_layer_convex_hull()
|
|||
// Wipe tower support.
|
||||
bool Print::has_wipe_tower() const
|
||||
{
|
||||
if (enable_timelapse_print())
|
||||
return true;
|
||||
|
||||
return
|
||||
! m_config.spiral_mode.value &&
|
||||
m_config.enable_prime_tower.value &&
|
||||
|
@ -1589,18 +1592,25 @@ const WipeTowerData& Print::wipe_tower_data(size_t filaments_cnt) const
|
|||
double width = m_config.prime_tower_width;
|
||||
double layer_height = 0.2; // hard code layer height
|
||||
double wipe_volume = m_config.prime_volume;
|
||||
const_cast<Print*>(this)->m_wipe_tower_data.depth = wipe_volume * (filaments_cnt - 1) / (layer_height * width);
|
||||
if (filaments_cnt == 1 && enable_timelapse_print()) {
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.depth = wipe_volume / (layer_height * width);
|
||||
} else {
|
||||
const_cast<Print *>(this)->m_wipe_tower_data.depth = wipe_volume * (filaments_cnt - 1) / (layer_height * width);
|
||||
}
|
||||
const_cast<Print*>(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width;
|
||||
}
|
||||
|
||||
return m_wipe_tower_data;
|
||||
}
|
||||
|
||||
bool Print::enable_timelapse_print() const
|
||||
{
|
||||
return m_config.timelapse_no_toolhead.value;
|
||||
}
|
||||
|
||||
void Print::_make_wipe_tower()
|
||||
{
|
||||
m_wipe_tower_data.clear();
|
||||
if (! this->has_wipe_tower())
|
||||
return;
|
||||
|
||||
// Get wiping matrix to get number of extruders and convert vector<double> to vector<float>:
|
||||
std::vector<float> flush_matrix(cast<float>(m_config.flush_volumes_matrix.values));
|
||||
|
@ -1616,7 +1626,18 @@ void Print::_make_wipe_tower()
|
|||
// BBS: priming logic is removed, so don't consider it in tool ordering
|
||||
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, false);
|
||||
|
||||
if (! m_wipe_tower_data.tool_ordering.has_wipe_tower())
|
||||
// if enable_timelapse_print(), update all layer_tools parameters(has_wipe_tower, wipe_tower_partitions)
|
||||
if (enable_timelapse_print()) {
|
||||
std::vector<LayerTools>& layer_tools_array = m_wipe_tower_data.tool_ordering.layer_tools();
|
||||
for (LayerTools& layer_tools : layer_tools_array) {
|
||||
layer_tools.has_wipe_tower = true;
|
||||
if (layer_tools.wipe_tower_partitions == 0) {
|
||||
layer_tools.wipe_tower_partitions = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_wipe_tower_data.tool_ordering.has_wipe_tower())
|
||||
// Don't generate any wipe tower.
|
||||
return;
|
||||
|
||||
|
@ -1705,6 +1726,11 @@ void Print::_make_wipe_tower()
|
|||
}
|
||||
}
|
||||
layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this);
|
||||
|
||||
// if enable timelapse, slice all layer
|
||||
if (enable_timelapse_print())
|
||||
continue;
|
||||
|
||||
if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0)
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -684,6 +684,8 @@ public:
|
|||
const WipeTowerData& wipe_tower_data(size_t filaments_cnt = 0) const;
|
||||
const ToolOrdering& tool_ordering() const { return m_tool_ordering; }
|
||||
|
||||
bool enable_timelapse_print() const;
|
||||
|
||||
std::string output_filename(const std::string &filename_base = std::string()) const override;
|
||||
|
||||
size_t num_print_regions() const throw() { return m_print_regions.size(); }
|
||||
|
|
|
@ -666,8 +666,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
//BBS
|
||||
|| opt_key == "adaptive_layer_height"
|
||||
|| opt_key == "raft_layers"
|
||||
|| opt_key == "raft_contact_distance"
|
||||
|| opt_key == "timelapse_no_toolhead") {
|
||||
|| opt_key == "raft_contact_distance") {
|
||||
steps.emplace_back(posSlice);
|
||||
} else if (
|
||||
opt_key == "elefant_foot_compensation"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
||||
// 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->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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue