Merge some BS1.7 changes:
bring back fill_bed feature, original implemention from PrusaSlicer. BS added exclusion logic.
This commit is contained in:
parent
b8db25ac0e
commit
3acd89e877
20 changed files with 242 additions and 180 deletions
|
@ -86,18 +86,21 @@ template<class PConf>
|
||||||
void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
||||||
|
|
||||||
if (params.is_seq_print) {
|
if (params.is_seq_print) {
|
||||||
// Align the arranged pile into the center of the bin
|
|
||||||
pcfg.alignment = PConf::Alignment::CENTER;
|
|
||||||
// Start placing the items from the center of the print bed
|
// Start placing the items from the center of the print bed
|
||||||
pcfg.starting_point = PConf::Alignment::BOTTOM_LEFT;
|
pcfg.starting_point = PConf::Alignment::BOTTOM_LEFT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Align the arranged pile into the center of the bin
|
|
||||||
pcfg.alignment = PConf::Alignment::CENTER;
|
|
||||||
// Start placing the items from the center of the print bed
|
// Start placing the items from the center of the print bed
|
||||||
pcfg.starting_point = PConf::Alignment::TOP_RIGHT;
|
pcfg.starting_point = PConf::Alignment::TOP_RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.do_final_align) {
|
||||||
|
// Align the arranged pile into the center of the bin
|
||||||
|
pcfg.alignment = PConf::Alignment::CENTER;
|
||||||
|
}else
|
||||||
|
pcfg.alignment = PConf::Alignment::DONT_ALIGN;
|
||||||
|
|
||||||
|
|
||||||
// Try 4 angles (45 degree step) and find the one with min cost
|
// Try 4 angles (45 degree step) and find the one with min cost
|
||||||
if (params.allow_rotations)
|
if (params.allow_rotations)
|
||||||
pcfg.rotations = {0., PI / 4., PI/2, 3. * PI / 4. };
|
pcfg.rotations = {0., PI / 4., PI/2, 3. * PI / 4. };
|
||||||
|
@ -452,27 +455,25 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<int> extruder_ids;
|
std::set<int> extruder_ids;
|
||||||
int non_virt_cnt = 0;
|
|
||||||
std::set<int> first_object_extruder_ids;
|
|
||||||
for (int i = 0; i < m_items.size(); i++) {
|
for (int i = 0; i < m_items.size(); i++) {
|
||||||
Item& p = m_items[i];
|
Item& p = m_items[i];
|
||||||
if (p.is_virt_object) continue;
|
if (p.is_virt_object) continue;
|
||||||
extruder_ids.insert(p.extrude_ids.begin(),p.extrude_ids.end());
|
extruder_ids.insert(p.extrude_ids.begin(),p.extrude_ids.end());
|
||||||
non_virt_cnt++;
|
|
||||||
if (non_virt_cnt == 1) { first_object_extruder_ids.insert(p.extrude_ids.begin(), p.extrude_ids.end()); }
|
|
||||||
}
|
}
|
||||||
extruder_ids.insert(item.extrude_ids.begin(),item.extrude_ids.end());
|
|
||||||
|
|
||||||
// add a large cost if not multi materials on same plate is not allowed
|
// add a large cost if not multi materials on same plate is not allowed
|
||||||
if (!params.allow_multi_materials_on_same_plate) {
|
if (!params.allow_multi_materials_on_same_plate) {
|
||||||
bool first_object = non_virt_cnt == 0;
|
// it's the first object, which can be multi-color
|
||||||
bool same_color_with_first_object = std::all_of(item.extrude_ids.begin(), item.extrude_ids.end(),
|
bool first_object = extruder_ids.empty();
|
||||||
[&](int color) { return first_object_extruder_ids.find(color) != first_object_extruder_ids.end(); });
|
// the two objects (previously packed items and the current item) are considered having same color if either one's colors are a subset of the other
|
||||||
// non_virt_cnt==0 means it's the first object, which can be multi-color
|
std::set<int> item_extruder_ids(item.extrude_ids.begin(), item.extrude_ids.end());
|
||||||
if (!(first_object || same_color_with_first_object)) score += LARGE_COST_TO_REJECT * 1.3;
|
bool same_color_with_previous_items = std::includes(item_extruder_ids.begin(), item_extruder_ids.end(), extruder_ids.begin(), extruder_ids.end())
|
||||||
|
|| std::includes(extruder_ids.begin(), extruder_ids.end(), item_extruder_ids.begin(), item_extruder_ids.end());
|
||||||
|
if (!(first_object || same_color_with_previous_items)) score += LARGE_COST_TO_REJECT * 1.3;
|
||||||
}
|
}
|
||||||
// for layered printing, we want extruder change as few as possible
|
// for layered printing, we want extruder change as few as possible
|
||||||
// this has very weak effect, CAN NOT use a large weight
|
// this has very weak effect, CAN NOT use a large weight
|
||||||
|
extruder_ids.insert(item.extrude_ids.begin(), item.extrude_ids.end());
|
||||||
if (!params.is_seq_print) {
|
if (!params.is_seq_print) {
|
||||||
score += 1 * std::max(0, ((int) extruder_ids.size() - 1));
|
score += 1 * std::max(0, ((int) extruder_ids.size() - 1));
|
||||||
}
|
}
|
||||||
|
@ -544,12 +545,6 @@ public:
|
||||||
if (items.empty()) return;
|
if (items.empty()) return;
|
||||||
|
|
||||||
auto binbb = sl::boundingBox(m_bin);
|
auto binbb = sl::boundingBox(m_bin);
|
||||||
// BBS: excluded region (virtual object but not wipe tower) should not affect final alignment
|
|
||||||
//bool all_is_excluded_region = std::all_of(items.begin(), items.end(), [](Item &itm) { return itm.is_virt_object && !itm.is_wipe_tower; });
|
|
||||||
//if (!all_is_excluded_region)
|
|
||||||
// cfg.alignment = PConfig::Alignment::DONT_ALIGN;
|
|
||||||
//else
|
|
||||||
// cfg.alignment = PConfig::Alignment::CENTER;
|
|
||||||
|
|
||||||
auto starting_point = cfg.starting_point == PConfig::Alignment::BOTTOM_LEFT ? binbb.minCorner() : binbb.center();
|
auto starting_point = cfg.starting_point == PConfig::Alignment::BOTTOM_LEFT ? binbb.minCorner() : binbb.center();
|
||||||
// if we have wipe tower, items should be arranged around wipe tower
|
// if we have wipe tower, items should be arranged around wipe tower
|
||||||
|
@ -561,15 +556,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.object_function = [this, binbb, starting_point](const Item &item, const ItemGroup &packed_items) {
|
cfg.object_function = [this, binbb, starting_point](const Item &item, const ItemGroup &packed_items) {
|
||||||
// 在我们的摆盘中,没有天然的固定对象。固定对象只有:屏蔽区域、挤出补偿区域、料塔。
|
return fixed_overfit(objfunc(item, starting_point), binbb);
|
||||||
// 对于屏蔽区域,摆入的对象仍然是可以向右上滑动的;
|
|
||||||
// 对挤出料塔,摆入的对象不能滑动(必须围绕料塔)
|
|
||||||
bool pack_around_wipe_tower = std::any_of(packed_items.begin(), packed_items.end(), [](Item& itm) { return itm.is_wipe_tower; });
|
|
||||||
//if(pack_around_wipe_tower)
|
|
||||||
return fixed_overfit(objfunc(item, starting_point), binbb);
|
|
||||||
//else {
|
|
||||||
// return fixed_overfit_topright_sliding(objfunc(item, starting_point), binbb, m_excluded_and_extruCali_regions);
|
|
||||||
//}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct ArrangePolygon {
|
||||||
//BBS: add row/col for sudoku-style layout
|
//BBS: add row/col for sudoku-style layout
|
||||||
int row{0};
|
int row{0};
|
||||||
int col{0};
|
int col{0};
|
||||||
std::vector<int> extrude_ids{1}; ///extruder_id for least extruder switch
|
std::vector<int> extrude_ids{}; /// extruder_id for least extruder switch
|
||||||
int bed_temp{0}; ///bed temperature for different material judge
|
int bed_temp{0}; ///bed temperature for different material judge
|
||||||
int print_temp{0}; ///print temperature for different material judge
|
int print_temp{0}; ///print temperature for different material judge
|
||||||
int first_bed_temp{ 0 }; ///first layer bed temperature for different material judge
|
int first_bed_temp{ 0 }; ///first layer bed temperature for different material judge
|
||||||
|
@ -114,6 +114,8 @@ struct ArrangeParams {
|
||||||
|
|
||||||
bool allow_rotations = false;
|
bool allow_rotations = false;
|
||||||
|
|
||||||
|
bool do_final_align = true;
|
||||||
|
|
||||||
//BBS: add specific arrange params
|
//BBS: add specific arrange params
|
||||||
bool allow_multi_materials_on_same_plate = true;
|
bool allow_multi_materials_on_same_plate = true;
|
||||||
bool avoid_extrusion_cali_region = true;
|
bool avoid_extrusion_cali_region = true;
|
||||||
|
|
|
@ -807,7 +807,7 @@ void PerimeterGenerator::split_top_surfaces(const ExPolygons &orig_polygons, ExP
|
||||||
offset_top_surface = 0;
|
offset_top_surface = 0;
|
||||||
// don't takes into account too thin areas
|
// don't takes into account too thin areas
|
||||||
// skip if the exposed area is smaller than 2x perimeter width
|
// skip if the exposed area is smaller than 2x perimeter width
|
||||||
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 2 + 10), 2.0 * (double(perimeter_width)));
|
double min_width_top_surface = std::max(double(ext_perimeter_spacing / 2 + 10), 2.5 * (double(perimeter_width)));
|
||||||
|
|
||||||
Polygons grown_upper_slices = offset(*this->upper_slices, min_width_top_surface);
|
Polygons grown_upper_slices = offset(*this->upper_slices, min_width_top_surface);
|
||||||
|
|
||||||
|
|
|
@ -685,9 +685,9 @@ bool Preset::is_custom_defined()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Preset::is_bbl_vendor_preset(PresetBundle *preset_bundle)
|
bool Preset::has_lidar(PresetBundle *preset_bundle)
|
||||||
{
|
{
|
||||||
bool is_bbl_vendor_preset = false;
|
bool has_lidar = false;
|
||||||
if (preset_bundle) {
|
if (preset_bundle) {
|
||||||
auto config = &preset_bundle->printers.get_edited_preset().config;
|
auto config = &preset_bundle->printers.get_edited_preset().config;
|
||||||
std::string vendor_name;
|
std::string vendor_name;
|
||||||
|
@ -700,9 +700,9 @@ bool Preset::is_bbl_vendor_preset(PresetBundle *preset_bundle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!vendor_name.empty())
|
if (!vendor_name.empty())
|
||||||
is_bbl_vendor_preset = vendor_name.compare("BBL") == 0 ? true : false;
|
has_lidar = vendor_name.compare("BBL") == 0 ? true : false;
|
||||||
}
|
}
|
||||||
return is_bbl_vendor_preset;
|
return has_lidar;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::string> s_Preset_print_options {
|
static std::vector<std::string> s_Preset_print_options {
|
||||||
|
|
|
@ -302,7 +302,7 @@ public:
|
||||||
std::string get_current_printer_type(PresetBundle *preset_bundle); // get current preset type
|
std::string get_current_printer_type(PresetBundle *preset_bundle); // get current preset type
|
||||||
bool is_custom_defined();
|
bool is_custom_defined();
|
||||||
|
|
||||||
bool is_bbl_vendor_preset(PresetBundle *preset_bundle);
|
bool has_lidar(PresetBundle *preset_bundle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,7 @@ void BackgroundSlicingProcess::process_fff()
|
||||||
{
|
{
|
||||||
assert(m_print == m_fff_print);
|
assert(m_print == m_fff_print);
|
||||||
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
||||||
m_fff_print->is_BBL_printer() = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
|
m_fff_print->is_BBL_printer() = preset_bundle.printers.get_edited_preset().has_lidar(&preset_bundle);
|
||||||
//BBS: add the logic to process from an existed gcode file
|
//BBS: add the logic to process from an existed gcode file
|
||||||
if (m_print->finished()) {
|
if (m_print->finished()) {
|
||||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%: skip slicing, to process previous gcode file")%__LINE__;
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%: skip slicing, to process previous gcode file")%__LINE__;
|
||||||
|
|
|
@ -5399,11 +5399,13 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
|
||||||
|
|
||||||
// only show this option if the printer has micro Lidar and can do first layer scan
|
// only show this option if the printer has micro Lidar and can do first layer scan
|
||||||
DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
DynamicPrintConfig ¤t_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
|
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
|
||||||
auto op = current_config.option("scan_first_layer");
|
auto op = current_config.option("scan_first_layer");
|
||||||
if (op && op->getBool()) {
|
if (has_lidar && op && op->getBool()) {
|
||||||
if (imgui->bbl_checkbox(_L("Avoid extrusion calibration region"), settings.avoid_extrusion_cali_region)) {
|
if (imgui->bbl_checkbox(_L("Avoid extrusion calibration region"), settings.avoid_extrusion_cali_region)) {
|
||||||
settings_out.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
|
settings_out.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
|
||||||
appcfg->set("arrange", avoid_extrusion_key.c_str(), settings_out.avoid_extrusion_cali_region);
|
appcfg->set("arrange", avoid_extrusion_key.c_str(), settings_out.avoid_extrusion_cali_region ? "1" : "0");
|
||||||
settings_changed = true;
|
settings_changed = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -656,6 +656,13 @@ wxMenuItem* MenuFactory::append_menu_item_instance_to_object(wxMenu* menu)
|
||||||
return menu_item;
|
return menu_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MenuFactory::append_menu_item_fill_bed(wxMenu *menu)
|
||||||
|
{
|
||||||
|
append_menu_item(
|
||||||
|
menu, wxID_ANY, _L("Fill bed with copies"), _L("Fill the remaining area of bed with copies of the selected object"),
|
||||||
|
[](wxCommandEvent &) { plater()->fill_bed_with_instances(); }, "", nullptr, []() { return plater()->can_increase_instances(); }, m_parent);
|
||||||
|
}
|
||||||
|
|
||||||
wxMenuItem* MenuFactory::append_menu_item_printable(wxMenu* menu)
|
wxMenuItem* MenuFactory::append_menu_item_printable(wxMenu* menu)
|
||||||
{
|
{
|
||||||
// BBS: to be checked
|
// BBS: to be checked
|
||||||
|
@ -1040,8 +1047,9 @@ void MenuFactory::create_object_menu()
|
||||||
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
|
// "Add (volumes)" popupmenu will be added later in append_menu_items_add_volume()
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuFactory::create_bbl_object_menu()
|
void MenuFactory::create_extra_object_menu()
|
||||||
{
|
{
|
||||||
|
append_menu_item_fill_bed(&m_object_menu);
|
||||||
// Object Clone
|
// Object Clone
|
||||||
append_menu_item_clone(&m_object_menu);
|
append_menu_item_clone(&m_object_menu);
|
||||||
// Object Repair
|
// Object Repair
|
||||||
|
@ -1262,7 +1270,7 @@ void MenuFactory::init(wxWindow* parent)
|
||||||
create_sla_object_menu();
|
create_sla_object_menu();
|
||||||
//create_part_menu();
|
//create_part_menu();
|
||||||
|
|
||||||
create_bbl_object_menu();
|
create_extra_object_menu();
|
||||||
create_bbl_part_menu();
|
create_bbl_part_menu();
|
||||||
create_bbl_assemble_object_menu();
|
create_bbl_assemble_object_menu();
|
||||||
create_bbl_assemble_part_menu();
|
create_bbl_assemble_part_menu();
|
||||||
|
|
|
@ -108,7 +108,7 @@ private:
|
||||||
//BBS: add part plate related logic
|
//BBS: add part plate related logic
|
||||||
void create_plate_menu();
|
void create_plate_menu();
|
||||||
//BBS: add bbl object menu
|
//BBS: add bbl object menu
|
||||||
void create_bbl_object_menu();
|
void create_extra_object_menu();
|
||||||
void create_bbl_part_menu();
|
void create_bbl_part_menu();
|
||||||
void create_bbl_assemble_object_menu();
|
void create_bbl_assemble_object_menu();
|
||||||
void create_bbl_assemble_part_menu();
|
void create_bbl_assemble_part_menu();
|
||||||
|
@ -150,6 +150,7 @@ private:
|
||||||
void append_menu_item_change_filament(wxMenu* menu);
|
void append_menu_item_change_filament(wxMenu* menu);
|
||||||
void append_menu_item_set_printable(wxMenu* menu);
|
void append_menu_item_set_printable(wxMenu* menu);
|
||||||
void append_menu_item_locked(wxMenu* menu);
|
void append_menu_item_locked(wxMenu* menu);
|
||||||
|
void append_menu_item_fill_bed(wxMenu *menu);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3547,7 +3547,7 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed, bool notify_partplate)
|
void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed, bool notify_partplate, bool do_info_update)
|
||||||
{
|
{
|
||||||
auto model_object = (*m_objects)[obj_idx];
|
auto model_object = (*m_objects)[obj_idx];
|
||||||
//BBS start add obj_idx for debug
|
//BBS start add obj_idx for debug
|
||||||
|
@ -3564,6 +3564,9 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed,
|
||||||
const auto item = m_objects_model->AddObject(model_object, warning_bitmap, model_object->is_cut());
|
const auto item = m_objects_model->AddObject(model_object, warning_bitmap, model_object->is_cut());
|
||||||
Expand(m_objects_model->GetParent(item));
|
Expand(m_objects_model->GetParent(item));
|
||||||
|
|
||||||
|
if (!do_info_update)
|
||||||
|
return;
|
||||||
|
|
||||||
update_info_items(obj_idx, nullptr, call_selection_changed);
|
update_info_items(obj_idx, nullptr, call_selection_changed);
|
||||||
|
|
||||||
add_volumes_to_object_in_list(obj_idx);
|
add_volumes_to_object_in_list(obj_idx);
|
||||||
|
|
|
@ -325,7 +325,7 @@ public:
|
||||||
void part_selection_changed();
|
void part_selection_changed();
|
||||||
|
|
||||||
// Add object to the list
|
// Add object to the list
|
||||||
void add_object_to_list(size_t obj_idx, bool call_selection_changed = true, bool notify_partplate = true);
|
void add_object_to_list(size_t obj_idx, bool call_selection_changed = true, bool notify_partplate = true, bool do_info_update = true);
|
||||||
// Add object's volumes to the list
|
// Add object's volumes to the list
|
||||||
// Return selected items, if add_to_selection is defined
|
// Return selected items, if add_to_selection is defined
|
||||||
wxDataViewItemArray add_volumes_to_object_in_list(size_t obj_idx, std::function<bool(const ModelVolume *)> add_to_selection = nullptr);
|
wxDataViewItemArray add_volumes_to_object_in_list(size_t obj_idx, std::function<bool(const ModelVolume *)> add_to_selection = nullptr);
|
||||||
|
|
|
@ -353,7 +353,7 @@ void ArrangeJob::prepare_partplate() {
|
||||||
ModelObject* mo = model.objects[oidx];
|
ModelObject* mo = model.objects[oidx];
|
||||||
for (size_t inst_idx = 0; inst_idx < mo->instances.size(); ++inst_idx)
|
for (size_t inst_idx = 0; inst_idx < mo->instances.size(); ++inst_idx)
|
||||||
{
|
{
|
||||||
bool in_plate = plate->contain_instance(oidx, inst_idx);
|
bool in_plate = plate->contain_instance(oidx, inst_idx) || plate->intersect_instance(oidx, inst_idx);
|
||||||
ArrangePolygon&& ap = prepare_arrange_polygon(mo->instances[inst_idx]);
|
ArrangePolygon&& ap = prepare_arrange_polygon(mo->instances[inst_idx]);
|
||||||
|
|
||||||
ArrangePolygons& cont = mo->instances[inst_idx]->printable ?
|
ArrangePolygons& cont = mo->instances[inst_idx]->printable ?
|
||||||
|
@ -392,20 +392,7 @@ void ArrangeJob::prepare()
|
||||||
NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging..."));
|
NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging..."));
|
||||||
m_plater->get_notification_manager()->bbl_close_plateinfo_notification();
|
m_plater->get_notification_manager()->bbl_close_plateinfo_notification();
|
||||||
|
|
||||||
{
|
params = init_arrange_params(m_plater);
|
||||||
const GLCanvas3D::ArrangeSettings &settings = static_cast<const GLCanvas3D *>(m_plater->canvas3D())->get_arrange_settings();
|
|
||||||
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
|
||||||
|
|
||||||
params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value;
|
|
||||||
params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value;
|
|
||||||
params.cleareance_radius = print.config().extruder_clearance_radius.value;
|
|
||||||
params.printable_height = print.config().printable_height.value;
|
|
||||||
params.allow_rotations = settings.enable_rotation;
|
|
||||||
params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;
|
|
||||||
params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
|
|
||||||
params.is_seq_print = settings.is_seq_print;
|
|
||||||
params.min_obj_distance = scaled(settings.distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
//BBS update extruder params and speed table before arranging
|
//BBS update extruder params and speed table before arranging
|
||||||
Plater::setExtruderParams(Model::extruderParamsMap);
|
Plater::setExtruderParams(Model::extruderParamsMap);
|
||||||
|
@ -510,85 +497,27 @@ void ArrangeJob::process()
|
||||||
auto & partplate_list = m_plater->get_partplate_list();
|
auto & partplate_list = m_plater->get_partplate_list();
|
||||||
auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||||
|
|
||||||
if (params.is_seq_print)
|
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
|
||||||
params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
|
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
|
||||||
if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer"))
|
if (has_lidar && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
|
||||||
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
|
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
|
||||||
|
|
||||||
double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0;
|
update_arrange_params(params, *m_plater, m_selected);
|
||||||
double brim_max = 0;
|
update_selected_items_inflation(m_selected, *m_plater, params);
|
||||||
std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon ap) { brim_max = std::max(brim_max, ap.brim_width); });
|
update_unselected_items_inflation(m_unselected, *m_plater, params);
|
||||||
|
|
||||||
// Note: skirt_distance is now defined between outermost brim and skirt, not the object and skirt.
|
Points bedpts = get_shrink_bedpts(*m_plater,params);
|
||||||
// So we can't do max but do adding instead.
|
|
||||||
params.brim_skirt_distance = skirt_distance + brim_max;
|
|
||||||
params.bed_shrink_x = settings.bed_shrink_x + params.brim_skirt_distance;
|
|
||||||
params.bed_shrink_y = settings.bed_shrink_y + params.brim_skirt_distance;
|
|
||||||
// for sequential print, we need to inflate the bed because cleareance_radius is so large
|
|
||||||
if (params.is_seq_print) {
|
|
||||||
float shift_dist = params.cleareance_radius / 2 - 5;
|
|
||||||
params.bed_shrink_x -= shift_dist;
|
|
||||||
params.bed_shrink_y -= shift_dist;
|
|
||||||
// dont forget to move the excluded region
|
|
||||||
for (auto& region : m_unselected) {
|
|
||||||
if (region.is_virt_object)
|
|
||||||
region.poly.translate(-scaled(shift_dist), -scaled(shift_dist));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (print.full_print_config().opt_bool("enable_support")) {
|
|
||||||
params.bed_shrink_x = std::max(5.f, params.bed_shrink_x);
|
|
||||||
params.bed_shrink_y = std::max(5.f, params.bed_shrink_y);
|
|
||||||
params.min_obj_distance = std::max(scaled(10.0), params.min_obj_distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not inflate brim_width. Objects are allowed to have overlapped brim.
|
|
||||||
Points bedpts = get_bed_shape(*m_plater->config());
|
|
||||||
BoundingBox bedbb = Polygon(bedpts).bounding_box();
|
|
||||||
std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon &ap) {
|
|
||||||
ap.inflation = params.min_obj_distance / 2;
|
|
||||||
BoundingBox apbb = ap.poly.contour.bounding_box();
|
|
||||||
auto diffx = bedbb.size().x() - apbb.size().x() - 5;
|
|
||||||
auto diffy = bedbb.size().y() - apbb.size().y() - 5;
|
|
||||||
if (diffx > 0 && diffy > 0) {
|
|
||||||
auto min_diff = std::min(diffx, diffy);
|
|
||||||
ap.inflation = std::min(min_diff / 2, ap.inflation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// For occulusion regions, inflation should be larger to prevent genrating brim on them.
|
|
||||||
// However, extrusion cali regions are exceptional, since we can allow brim overlaps them.
|
|
||||||
// 屏蔽区域只需要膨胀brim宽度,防止brim长过去;挤出标定区域不需要膨胀,brim可以长过去。
|
|
||||||
// 以前我们认为还需要膨胀clearance_radius/2,这其实是不需要的,因为这些区域并不会真的摆放物体,
|
|
||||||
// 其他物体的膨胀轮廓是可以跟它们重叠的。
|
|
||||||
double scaled_exclusion_gap = scale_(1);
|
double scaled_exclusion_gap = scale_(1);
|
||||||
std::for_each(m_unselected.begin(), m_unselected.end(), [&](auto &ap) {
|
|
||||||
ap.inflation = !ap.is_virt_object ?
|
|
||||||
params.min_obj_distance / 2 :
|
|
||||||
(ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap);
|
partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap);
|
||||||
|
|
||||||
// shrink bed by moving to center by dist
|
|
||||||
auto shrinkFun = [](Points& bedpts, double dist, int direction) {
|
|
||||||
#define SGN(x) ((x)>=0?1:-1)
|
|
||||||
Point center = Polygon(bedpts).bounding_box().center();
|
|
||||||
for (auto& pt : bedpts)
|
|
||||||
pt[direction] += dist * SGN(center[direction] - pt[direction]);
|
|
||||||
};
|
|
||||||
shrinkFun(bedpts, scaled(params.bed_shrink_x), 0);
|
|
||||||
shrinkFun(bedpts, scaled(params.bed_shrink_y), 1);
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "arrange bed_shrink_x=" << params.bed_shrink_x
|
BOOST_LOG_TRIVIAL(debug) << "arrange bed_shrink_x=" << params.bed_shrink_x
|
||||||
<< ", brim_max= "<<brim_max<<", "
|
|
||||||
<< "; bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
|
<< "; bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
|
||||||
|
|
||||||
params.stopcondition = [this]() { return was_canceled(); };
|
params.stopcondition = [this]() { return was_canceled(); };
|
||||||
|
|
||||||
params.progressind = [this](unsigned num_finished, std::string str="") {
|
params.progressind = [this](unsigned num_finished, std::string str = "") {
|
||||||
update_status(num_finished, _L("Arranging") + " " + str);
|
update_status(num_finished, _L("Arranging") + " "+ wxString::FromUTF8(str));
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -765,8 +694,8 @@ void ArrangeJob::finalize() {
|
||||||
std::optional<arrangement::ArrangePolygon>
|
std::optional<arrangement::ArrangePolygon>
|
||||||
get_wipe_tower_arrangepoly(const Plater &plater)
|
get_wipe_tower_arrangepoly(const Plater &plater)
|
||||||
{
|
{
|
||||||
// BBS FIXME: use actual plate_idx
|
int id = plater.canvas3D()->fff_print()->get_plate_index();
|
||||||
if (auto wti = get_wipe_tower(plater, 0))
|
if (auto wti = get_wipe_tower(plater, id))
|
||||||
return get_wipetower_arrange_poly(&wti);
|
return get_wipetower_arrange_poly(&wti);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -775,12 +704,12 @@ get_wipe_tower_arrangepoly(const Plater &plater)
|
||||||
//BBS: add sudoku-style stride
|
//BBS: add sudoku-style stride
|
||||||
double bed_stride_x(const Plater* plater) {
|
double bed_stride_x(const Plater* plater) {
|
||||||
double bedwidth = plater->build_volume().bounding_box().size().x();
|
double bedwidth = plater->build_volume().bounding_box().size().x();
|
||||||
return scaled<double>((1. + LOGICAL_BED_GAP) * bedwidth);
|
return (1. + LOGICAL_BED_GAP) * bedwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
double bed_stride_y(const Plater* plater) {
|
double bed_stride_y(const Plater* plater) {
|
||||||
double beddepth = plater->build_volume().bounding_box().size().y();
|
double beddepth = plater->build_volume().bounding_box().size().y();
|
||||||
return scaled<double>((1. + LOGICAL_BED_GAP) * beddepth);
|
return (1. + LOGICAL_BED_GAP) * beddepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -800,4 +729,107 @@ arrangement::ArrangeParams get_arrange_params(Plater *p)
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call before get selected and unselected
|
||||||
|
arrangement::ArrangeParams init_arrange_params(Plater *p)
|
||||||
|
{
|
||||||
|
arrangement::ArrangeParams params;
|
||||||
|
const GLCanvas3D::ArrangeSettings &settings = static_cast<const GLCanvas3D *>(p->canvas3D())->get_arrange_settings();
|
||||||
|
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||||
|
|
||||||
|
params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value;
|
||||||
|
params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value;
|
||||||
|
params.cleareance_radius = print.config().extruder_clearance_radius.value;
|
||||||
|
params.printable_height = print.config().printable_height.value;
|
||||||
|
params.allow_rotations = settings.enable_rotation;
|
||||||
|
params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;
|
||||||
|
params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
|
||||||
|
params.is_seq_print = settings.is_seq_print;
|
||||||
|
params.min_obj_distance = scaled(settings.distance);
|
||||||
|
params.bed_shrink_x = settings.bed_shrink_x;
|
||||||
|
params.bed_shrink_y = settings.bed_shrink_y;
|
||||||
|
|
||||||
|
int state = p->get_prepare_state();
|
||||||
|
if (state == Job::JobPrepareState::PREPARE_STATE_MENU) {
|
||||||
|
PartPlateList &plate_list = p->get_partplate_list();
|
||||||
|
PartPlate * plate = plate_list.get_curr_plate();
|
||||||
|
params.is_seq_print = plate->get_real_print_seq() == PrintSequence::ByObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.is_seq_print)
|
||||||
|
params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
//after get selected.call this to update bed_shrink
|
||||||
|
void update_arrange_params(arrangement::ArrangeParams ¶ms, const Plater &p, const arrangement::ArrangePolygons &selected)
|
||||||
|
{
|
||||||
|
const GLCanvas3D::ArrangeSettings &settings = static_cast<const GLCanvas3D *>(p.canvas3D())->get_arrange_settings();
|
||||||
|
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||||
|
double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0;
|
||||||
|
double brim_max = 0;
|
||||||
|
std::for_each(selected.begin(), selected.end(), [&](const ArrangePolygon &ap) { brim_max = std::max(brim_max, ap.brim_width); });
|
||||||
|
// Note: skirt_distance is now defined between outermost brim and skirt, not the object and skirt.
|
||||||
|
// So we can't do max but do adding instead.
|
||||||
|
params.brim_skirt_distance = skirt_distance + brim_max;
|
||||||
|
params.bed_shrink_x = settings.bed_shrink_x + params.brim_skirt_distance;
|
||||||
|
params.bed_shrink_y = settings.bed_shrink_y + params.brim_skirt_distance;
|
||||||
|
// for sequential print, we need to inflate the bed because cleareance_radius is so large
|
||||||
|
if (params.is_seq_print) {
|
||||||
|
float shift_dist = params.cleareance_radius / 2 - 5;
|
||||||
|
params.bed_shrink_x -= shift_dist;
|
||||||
|
params.bed_shrink_y -= shift_dist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//it will bed accurate after call update_params
|
||||||
|
Points get_shrink_bedpts(const Plater &plater, const arrangement::ArrangeParams ¶ms)
|
||||||
|
{
|
||||||
|
Points bedpts = get_bed_shape(*plater.config());
|
||||||
|
// shrink bed by moving to center by dist
|
||||||
|
auto shrinkFun = [](Points &bedpts, double dist, int direction) {
|
||||||
|
#define SGN(x) ((x) >= 0 ? 1 : -1)
|
||||||
|
Point center = Polygon(bedpts).bounding_box().center();
|
||||||
|
for (auto &pt : bedpts) pt[direction] += dist * SGN(center[direction] - pt[direction]);
|
||||||
|
};
|
||||||
|
shrinkFun(bedpts, scaled(params.bed_shrink_x), 0);
|
||||||
|
shrinkFun(bedpts, scaled(params.bed_shrink_y), 1);
|
||||||
|
return bedpts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_selected_items_inflation(arrangement::ArrangePolygons &selected, const Plater &p, const arrangement::ArrangeParams ¶ms) {
|
||||||
|
// do not inflate brim_width. Objects are allowed to have overlapped brim.
|
||||||
|
Points bedpts = get_shrink_bedpts(p, params);
|
||||||
|
BoundingBox bedbb = Polygon(bedpts).bounding_box();
|
||||||
|
std::for_each(selected.begin(), selected.end(), [&](ArrangePolygon &ap) {
|
||||||
|
ap.inflation = std::max(scaled(ap.brim_width), params.min_obj_distance / 2);
|
||||||
|
BoundingBox apbb = ap.poly.contour.bounding_box();
|
||||||
|
auto diffx = bedbb.size().x() - apbb.size().x() - 5;
|
||||||
|
auto diffy = bedbb.size().y() - apbb.size().y() - 5;
|
||||||
|
if (diffx > 0 && diffy > 0) {
|
||||||
|
auto min_diff = std::min(diffx, diffy);
|
||||||
|
ap.inflation = std::min(min_diff / 2, ap.inflation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_unselected_items_inflation(arrangement::ArrangePolygons &unselected, const Plater &p, const arrangement::ArrangeParams ¶ms)
|
||||||
|
{
|
||||||
|
if (params.is_seq_print) {
|
||||||
|
float shift_dist = params.cleareance_radius / 2 - 5;
|
||||||
|
// dont forget to move the excluded region
|
||||||
|
for (auto ®ion : unselected) {
|
||||||
|
if (region.is_virt_object) region.poly.translate(-scaled(shift_dist), -scaled(shift_dist));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// For occulusion regions, inflation should be larger to prevent genrating brim on them.
|
||||||
|
// However, extrusion cali regions are exceptional, since we can allow brim overlaps them.
|
||||||
|
// 屏蔽区域只需要膨胀brim宽度,防止brim长过去;挤出标定区域不需要膨胀,brim可以长过去。
|
||||||
|
// 以前我们认为还需要膨胀clearance_radius/2,这其实是不需要的,因为这些区域并不会真的摆放物体,
|
||||||
|
// 其他物体的膨胀轮廓是可以跟它们重叠的。
|
||||||
|
double scaled_exclusion_gap = scale_(1);
|
||||||
|
std::for_each(unselected.begin(), unselected.end(),
|
||||||
|
[&](auto &ap) { ap.inflation = !ap.is_virt_object ? std::max(scaled(ap.brim_width), params.min_obj_distance / 2)
|
||||||
|
: (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); });
|
||||||
|
}
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
|
|
@ -78,6 +78,16 @@ double bed_stride_y(const Plater* plater);
|
||||||
|
|
||||||
arrangement::ArrangeParams get_arrange_params(Plater *p);
|
arrangement::ArrangeParams get_arrange_params(Plater *p);
|
||||||
|
|
||||||
|
arrangement::ArrangeParams init_arrange_params(Plater *p);
|
||||||
|
|
||||||
|
Points get_shrink_bedpts(const Plater& plater,const arrangement::ArrangeParams& params);
|
||||||
|
|
||||||
|
void update_arrange_params(arrangement::ArrangeParams ¶ms, const Plater &p, const arrangement::ArrangePolygons &selected);
|
||||||
|
|
||||||
|
void update_selected_items_inflation(arrangement::ArrangePolygons &selected, const Plater &p, const arrangement::ArrangeParams ¶ms);
|
||||||
|
|
||||||
|
void update_unselected_items_inflation(arrangement::ArrangePolygons &unselected, const Plater &p, const arrangement::ArrangeParams ¶ms);
|
||||||
|
|
||||||
}} // namespace Slic3r::GUI
|
}} // namespace Slic3r::GUI
|
||||||
|
|
||||||
#endif // ARRANGEJOB_HPP
|
#endif // ARRANGEJOB_HPP
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
|
#include "libnest2d/common.hpp"
|
||||||
|
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
|
@ -22,6 +23,8 @@ void FillBedJob::prepare()
|
||||||
m_unselected.clear();
|
m_unselected.clear();
|
||||||
m_bedpts.clear();
|
m_bedpts.clear();
|
||||||
|
|
||||||
|
params = init_arrange_params(m_plater);
|
||||||
|
|
||||||
m_object_idx = m_plater->get_selected_object_idx();
|
m_object_idx = m_plater->get_selected_object_idx();
|
||||||
if (m_object_idx == -1)
|
if (m_object_idx == -1)
|
||||||
return;
|
return;
|
||||||
|
@ -42,6 +45,7 @@ void FillBedJob::prepare()
|
||||||
ModelObject *model_object = m_plater->model().objects[m_object_idx];
|
ModelObject *model_object = m_plater->model().objects[m_object_idx];
|
||||||
if (model_object->instances.empty()) return;
|
if (model_object->instances.empty()) return;
|
||||||
|
|
||||||
|
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
|
||||||
m_selected.reserve(model_object->instances.size());
|
m_selected.reserve(model_object->instances.size());
|
||||||
for (size_t oidx = 0; oidx < model.objects.size(); ++oidx)
|
for (size_t oidx = 0; oidx < model.objects.size(); ++oidx)
|
||||||
{
|
{
|
||||||
|
@ -50,7 +54,7 @@ void FillBedJob::prepare()
|
||||||
{
|
{
|
||||||
bool selected = (oidx == m_object_idx);
|
bool selected = (oidx == m_object_idx);
|
||||||
|
|
||||||
ArrangePolygon ap = get_arrange_poly(mo->instances[inst_idx]);
|
ArrangePolygon ap = get_instance_arrange_poly(mo->instances[inst_idx], global_config);
|
||||||
BoundingBox ap_bb = ap.transformed_poly().contour.bounding_box();
|
BoundingBox ap_bb = ap.transformed_poly().contour.bounding_box();
|
||||||
ap.height = 1;
|
ap.height = 1;
|
||||||
ap.name = mo->name;
|
ap.name = mo->name;
|
||||||
|
@ -117,6 +121,8 @@ void FillBedJob::prepare()
|
||||||
if (m_selected.empty()) return;
|
if (m_selected.empty()) return;
|
||||||
|
|
||||||
//add the virtual object into unselect list if has
|
//add the virtual object into unselect list if has
|
||||||
|
double scaled_exclusion_gap = scale_(1);
|
||||||
|
plate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap);
|
||||||
plate_list.preprocess_exclude_areas(m_unselected);
|
plate_list.preprocess_exclude_areas(m_unselected);
|
||||||
|
|
||||||
m_bedpts = get_bed_shape(*m_plater->config());
|
m_bedpts = get_bed_shape(*m_plater->config());
|
||||||
|
@ -134,14 +140,15 @@ void FillBedJob::prepare()
|
||||||
ap.bed_idx = arrangement::UNARRANGED;
|
ap.bed_idx = arrangement::UNARRANGED;
|
||||||
|
|
||||||
m_unselected.emplace_back(ap);
|
m_unselected.emplace_back(ap);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (auto wt = get_wipe_tower_arrangepoly(*m_plater))
|
if (auto wt = get_wipe_tower_arrangepoly(*m_plater))
|
||||||
m_unselected.emplace_back(std::move(*wt));*/
|
m_unselected.emplace_back(std::move(*wt));
|
||||||
|
|
||||||
double sc = scaled<double>(1.) * scaled(1.);
|
double sc = scaled<double>(1.) * scaled(1.);
|
||||||
|
|
||||||
ExPolygon poly = m_selected.front().poly;
|
const GLCanvas3D::ArrangeSettings& settings = static_cast<const GLCanvas3D*>(m_plater->canvas3D())->get_arrange_settings();
|
||||||
|
auto polys = offset_ex(m_selected.front().poly, scaled(settings.distance) / 2);
|
||||||
|
ExPolygon poly = polys.empty() ? m_selected.front().poly : polys.front();
|
||||||
double poly_area = poly.area() / sc;
|
double poly_area = poly.area() / sc;
|
||||||
double unsel_area = std::accumulate(m_unselected.begin(),
|
double unsel_area = std::accumulate(m_unselected.begin(),
|
||||||
m_unselected.end(), 0.,
|
m_unselected.end(), 0.,
|
||||||
|
@ -161,7 +168,7 @@ void FillBedJob::prepare()
|
||||||
// if the selection is not a single instance, choose the first as template
|
// if the selection is not a single instance, choose the first as template
|
||||||
//sel_id = std::max(sel_id, 0);
|
//sel_id = std::max(sel_id, 0);
|
||||||
ModelInstance *mi = model_object->instances[sel_id];
|
ModelInstance *mi = model_object->instances[sel_id];
|
||||||
ArrangePolygon template_ap = get_arrange_poly(mi);
|
ArrangePolygon template_ap = get_instance_arrange_poly(mi, global_config);
|
||||||
|
|
||||||
for (int i = 0; i < needed_items; ++i) {
|
for (int i = 0; i < needed_items; ++i) {
|
||||||
ArrangePolygon ap = template_ap;
|
ArrangePolygon ap = template_ap;
|
||||||
|
@ -171,8 +178,10 @@ void FillBedJob::prepare()
|
||||||
ap.itemid = -1;
|
ap.itemid = -1;
|
||||||
ap.setter = [this, mi](const ArrangePolygon &p) {
|
ap.setter = [this, mi](const ArrangePolygon &p) {
|
||||||
ModelObject *mo = m_plater->model().objects[m_object_idx];
|
ModelObject *mo = m_plater->model().objects[m_object_idx];
|
||||||
ModelInstance *inst = mo->add_instance(*mi);
|
ModelObject* newObj = m_plater->model().add_object(*mo);
|
||||||
inst->apply_arrange_result(p.translation.cast<double>(), p.rotation);
|
newObj->name = mo->name +" "+ std::to_string(p.itemid);
|
||||||
|
for (ModelInstance *newInst : newObj->instances) { newInst->apply_arrange_result(p.translation.cast<double>(), p.rotation); }
|
||||||
|
//m_plater->sidebar().obj_list()->paste_objects_into_list({m_plater->model().objects.size()-1});
|
||||||
};
|
};
|
||||||
m_selected.emplace_back(ap);
|
m_selected.emplace_back(ap);
|
||||||
}
|
}
|
||||||
|
@ -196,9 +205,19 @@ void FillBedJob::process()
|
||||||
const GLCanvas3D::ArrangeSettings &settings =
|
const GLCanvas3D::ArrangeSettings &settings =
|
||||||
static_cast<const GLCanvas3D*>(m_plater->canvas3D())->get_arrange_settings();
|
static_cast<const GLCanvas3D*>(m_plater->canvas3D())->get_arrange_settings();
|
||||||
|
|
||||||
arrangement::ArrangeParams params;
|
update_arrange_params(params, *m_plater, m_selected);
|
||||||
params.allow_rotations = settings.enable_rotation;
|
m_bedpts = get_shrink_bedpts(*m_plater, params);
|
||||||
params.min_obj_distance = scaled(settings.distance);
|
|
||||||
|
auto &partplate_list = m_plater->get_partplate_list();
|
||||||
|
auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||||
|
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
|
||||||
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
|
const bool has_lidar = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
|
||||||
|
if (has_lidar && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
|
||||||
|
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
|
||||||
|
|
||||||
|
update_selected_items_inflation(m_selected, *m_plater, params);
|
||||||
|
update_unselected_items_inflation(m_unselected, *m_plater, params);
|
||||||
|
|
||||||
bool do_stop = false;
|
bool do_stop = false;
|
||||||
params.stopcondition = [this, &do_stop]() {
|
params.stopcondition = [this, &do_stop]() {
|
||||||
|
@ -206,20 +225,22 @@ void FillBedJob::process()
|
||||||
};
|
};
|
||||||
|
|
||||||
params.progressind = [this](unsigned st,std::string str="") {
|
params.progressind = [this](unsigned st,std::string str="") {
|
||||||
// if (st > 0)
|
if (st > 0)
|
||||||
// update_status(int(m_status_range - st), _L("Filling bed " + str));
|
update_status(st, _L("Filling bed " + str));
|
||||||
};
|
};
|
||||||
|
|
||||||
params.on_packed = [&do_stop] (const ArrangePolygon &ap) {
|
params.on_packed = [&do_stop] (const ArrangePolygon &ap) {
|
||||||
do_stop = ap.bed_idx > 0 && ap.priority == 0;
|
do_stop = ap.bed_idx > 0 && ap.priority == 0;
|
||||||
};
|
};
|
||||||
|
// final align用的是凸包,在有fixed item的情况下可能找到的参考点位置是错的,这里就不做了。见STUDIO-3265
|
||||||
|
params.do_final_align = !has_lidar;
|
||||||
|
|
||||||
arrangement::arrange(m_selected, m_unselected, m_bedpts, params);
|
arrangement::arrange(m_selected, m_unselected, m_bedpts, params);
|
||||||
|
|
||||||
// finalize just here.
|
// finalize just here.
|
||||||
// update_status(m_status_range, was_canceled() ?
|
update_status(m_status_range, was_canceled() ?
|
||||||
// _(L("Bed filling canceled.")) :
|
_(L("Bed filling canceled.")) :
|
||||||
// _(L("Bed filling done.")));
|
_(L("Bed filling done.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FillBedJob::finalize()
|
void FillBedJob::finalize()
|
||||||
|
@ -243,11 +264,14 @@ void FillBedJob::finalize()
|
||||||
return s + int(ap.priority == 0 && ap.bed_idx == 0);
|
return s + int(ap.priority == 0 && ap.bed_idx == 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
int oldSize = m_plater->model().objects.size();
|
||||||
|
|
||||||
if (added_cnt > 0) {
|
if (added_cnt > 0) {
|
||||||
//BBS: adjust the selected instances
|
//BBS: adjust the selected instances
|
||||||
for (ArrangePolygon& ap : m_selected) {
|
for (ArrangePolygon& ap : m_selected) {
|
||||||
if (ap.bed_idx != 0) {
|
if (ap.bed_idx != 0) {
|
||||||
if (ap.itemid == -1)
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":skipped: bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y));
|
||||||
|
/*if (ap.itemid == -1)*/
|
||||||
continue;
|
continue;
|
||||||
ap.bed_idx = plate_list.get_plate_count();
|
ap.bed_idx = plate_list.get_plate_count();
|
||||||
}
|
}
|
||||||
|
@ -263,33 +287,24 @@ void FillBedJob::finalize()
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":selected: bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y));
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":selected: bed_id %1%, trans {%2%,%3%}") % ap.bed_idx % unscale<double>(ap.translation(X)) % unscale<double>(ap.translation(Y));
|
||||||
}
|
}
|
||||||
for (size_t inst_idx = 0; inst_idx < model_object->instances.size(); ++inst_idx)
|
|
||||||
{
|
int newSize = m_plater->model().objects.size();
|
||||||
plate_list.notify_instance_update(m_object_idx, inst_idx);
|
auto obj_list = m_plater->sidebar().obj_list();
|
||||||
|
for (size_t i = oldSize; i < newSize; i++) {
|
||||||
|
obj_list->add_object_to_list(i, true, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": paste_objects_into_list";
|
||||||
|
|
||||||
/*for (ArrangePolygon& ap : m_selected) {
|
/*for (ArrangePolygon& ap : m_selected) {
|
||||||
if (ap.bed_idx != arrangement::UNARRANGED && (ap.priority != 0 || ap.bed_idx == 0))
|
if (ap.bed_idx != arrangement::UNARRANGED && (ap.priority != 0 || ap.bed_idx == 0))
|
||||||
ap.apply();
|
ap.apply();
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
model_object->ensure_on_bed();
|
//model_object->ensure_on_bed();
|
||||||
|
//BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ": model_object->ensure_on_bed()";
|
||||||
|
|
||||||
m_plater->update();
|
m_plater->update();
|
||||||
|
|
||||||
//BBS: add partplate related logic
|
|
||||||
int added_cnt = std::accumulate(m_selected.begin(), m_selected.end(), 0,
|
|
||||||
[cur_plate](int s, auto& ap) {
|
|
||||||
return s + int(ap.priority == 0 && ap.bed_idx == cur_plate);
|
|
||||||
//return s + int(ap.priority == 0 && ap.bed_idx == 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME: somebody explain why this is needed for increase_object_instances
|
|
||||||
if (inst_cnt == 1) added_cnt++;
|
|
||||||
|
|
||||||
if (added_cnt > 0)
|
|
||||||
m_plater->sidebar()
|
|
||||||
.obj_list()->increase_object_instances(m_object_idx, size_t(added_cnt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Job::finalize();
|
Job::finalize();
|
||||||
|
|
|
@ -21,6 +21,8 @@ class FillBedJob : public PlaterJob
|
||||||
|
|
||||||
Points m_bedpts;
|
Points m_bedpts;
|
||||||
|
|
||||||
|
arrangement::ArrangeParams params;
|
||||||
|
|
||||||
int m_status_range = 0;
|
int m_status_range = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -549,7 +549,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
||||||
m_print_btn->Enable(m_print_enable);
|
m_print_btn->Enable(m_print_enable);
|
||||||
if (m_print_enable) {
|
if (m_print_enable) {
|
||||||
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
||||||
if (preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle))
|
if (preset_bundle.printers.get_edited_preset().has_lidar(&preset_bundle))
|
||||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_PLATE));
|
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PRINT_PLATE));
|
||||||
else
|
else
|
||||||
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_GCODE));
|
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_GCODE));
|
||||||
|
@ -907,7 +907,7 @@ void MainFrame::init_tabpanel() {
|
||||||
int old_sel = e.GetOldSelection();
|
int old_sel = e.GetOldSelection();
|
||||||
int new_sel = e.GetSelection();
|
int new_sel = e.GetSelection();
|
||||||
if (wxGetApp().preset_bundle &&
|
if (wxGetApp().preset_bundle &&
|
||||||
wxGetApp().preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(wxGetApp().preset_bundle) &&
|
wxGetApp().preset_bundle->printers.get_edited_preset().has_lidar(wxGetApp().preset_bundle) &&
|
||||||
new_sel == tpMonitor) {
|
new_sel == tpMonitor) {
|
||||||
if (!wxGetApp().getAgent()) {
|
if (!wxGetApp().getAgent()) {
|
||||||
e.Veto();
|
e.Veto();
|
||||||
|
@ -1505,7 +1505,7 @@ wxBoxSizer* MainFrame::create_side_tools()
|
||||||
SidePopup* p = new SidePopup(this);
|
SidePopup* p = new SidePopup(this);
|
||||||
|
|
||||||
if (wxGetApp().preset_bundle
|
if (wxGetApp().preset_bundle
|
||||||
&& !wxGetApp().preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(wxGetApp().preset_bundle)) {
|
&& !wxGetApp().preset_bundle->printers.get_edited_preset().has_lidar(wxGetApp().preset_bundle)) {
|
||||||
// ThirdParty Buttons
|
// ThirdParty Buttons
|
||||||
SideButton* export_gcode_btn = new SideButton(p, _L("Export G-code file"), "");
|
SideButton* export_gcode_btn = new SideButton(p, _L("Export G-code file"), "");
|
||||||
export_gcode_btn->SetCornerRadius(0);
|
export_gcode_btn->SetCornerRadius(0);
|
||||||
|
@ -3410,7 +3410,7 @@ void MainFrame::load_printer_url(wxString url)
|
||||||
void MainFrame::load_printer_url()
|
void MainFrame::load_printer_url()
|
||||||
{
|
{
|
||||||
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
||||||
if (preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle))
|
if (preset_bundle.printers.get_edited_preset().has_lidar(&preset_bundle))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto cfg = preset_bundle.printers.get_edited_preset().config;
|
auto cfg = preset_bundle.printers.get_edited_preset().config;
|
||||||
|
|
|
@ -23,7 +23,7 @@ PlateSettingsDialog::PlateSettingsDialog(wxWindow* parent, wxWindowID id, const
|
||||||
top_sizer->SetFlexibleDirection(wxBOTH);
|
top_sizer->SetFlexibleDirection(wxBOTH);
|
||||||
top_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
top_sizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
|
||||||
|
|
||||||
bool is_bbl = wxGetApp().preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(wxGetApp().preset_bundle);
|
bool is_bbl = wxGetApp().preset_bundle->printers.get_edited_preset().has_lidar(wxGetApp().preset_bundle);
|
||||||
if (is_bbl) {
|
if (is_bbl) {
|
||||||
m_bed_type_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0,
|
m_bed_type_choice = new ComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(FromDIP(240), -1), 0,
|
||||||
NULL, wxCB_READONLY);
|
NULL, wxCB_READONLY);
|
||||||
|
|
|
@ -1024,7 +1024,7 @@ void Sidebar::update_all_preset_comboboxes()
|
||||||
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
||||||
const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology();
|
const auto print_tech = preset_bundle.printers.get_edited_preset().printer_technology();
|
||||||
|
|
||||||
bool is_bbl_preset = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
|
bool is_bbl_preset = preset_bundle.printers.get_edited_preset().has_lidar(&preset_bundle);
|
||||||
|
|
||||||
auto p_mainframe = wxGetApp().mainframe;
|
auto p_mainframe = wxGetApp().mainframe;
|
||||||
|
|
||||||
|
@ -8183,7 +8183,7 @@ void Plater::_calib_pa_pattern(const Calib_Params& params)
|
||||||
|
|
||||||
const DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config();
|
const DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config();
|
||||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||||
const bool is_bbl_machine = preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(preset_bundle);
|
const bool is_bbl_machine = preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle);
|
||||||
const Vec3d plate_origin = get_partplate_list().get_current_plate_origin();
|
const Vec3d plate_origin = get_partplate_list().get_current_plate_origin();
|
||||||
CalibPressureAdvancePattern pa_pattern(
|
CalibPressureAdvancePattern pa_pattern(
|
||||||
params,
|
params,
|
||||||
|
@ -10403,7 +10403,7 @@ void Plater::reslice()
|
||||||
|
|
||||||
model().calib_pa_pattern->generate_custom_gcodes(
|
model().calib_pa_pattern->generate_custom_gcodes(
|
||||||
wxGetApp().preset_bundle->full_config(),
|
wxGetApp().preset_bundle->full_config(),
|
||||||
preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(preset_bundle),
|
preset_bundle->printers.get_edited_preset().has_lidar(preset_bundle),
|
||||||
model(),
|
model(),
|
||||||
get_partplate_list().get_current_plate_origin()
|
get_partplate_list().get_current_plate_origin()
|
||||||
);
|
);
|
||||||
|
|
|
@ -1039,7 +1039,7 @@ void PlaterPresetComboBox::update()
|
||||||
//if (i + 1 == m_collection->num_default_presets())
|
//if (i + 1 == m_collection->num_default_presets())
|
||||||
// set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
// set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
||||||
}
|
}
|
||||||
if (m_type == Preset::TYPE_FILAMENT && m_preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(m_preset_bundle))
|
if (m_type == Preset::TYPE_FILAMENT && m_preset_bundle->printers.get_edited_preset().has_lidar(m_preset_bundle))
|
||||||
add_ams_filaments(into_u8(selected_user_preset), true);
|
add_ams_filaments(into_u8(selected_user_preset), true);
|
||||||
|
|
||||||
//BBS: add project embedded preset logic
|
//BBS: add project embedded preset logic
|
||||||
|
@ -1267,7 +1267,7 @@ void TabPresetComboBox::update()
|
||||||
// set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
// set_label_marker(Append(separator(L("System presets")), wxNullBitmap));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_type == Preset::TYPE_FILAMENT && m_preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(m_preset_bundle))
|
if (m_type == Preset::TYPE_FILAMENT && m_preset_bundle->printers.get_edited_preset().has_lidar(m_preset_bundle))
|
||||||
add_ams_filaments(into_u8(selected));
|
add_ams_filaments(into_u8(selected));
|
||||||
|
|
||||||
//BBS: add project embedded preset logic
|
//BBS: add project embedded preset logic
|
||||||
|
|
|
@ -1644,9 +1644,9 @@ void Tab::on_presets_changed()
|
||||||
// Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets
|
// Instead of PostEvent (EVT_TAB_PRESETS_CHANGED) just call update_presets
|
||||||
wxGetApp().plater()->sidebar().update_presets(m_type);
|
wxGetApp().plater()->sidebar().update_presets(m_type);
|
||||||
|
|
||||||
bool is_bbl_vendor_preset = wxGetApp().preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(wxGetApp().preset_bundle);
|
bool has_lidar = wxGetApp().preset_bundle->printers.get_edited_preset().has_lidar(wxGetApp().preset_bundle);
|
||||||
auto& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
auto& printer_cfg = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||||
if (is_bbl_vendor_preset)
|
if (has_lidar)
|
||||||
wxGetApp().plater()->get_partplate_list().set_render_option(
|
wxGetApp().plater()->get_partplate_list().set_render_option(
|
||||||
!printer_cfg.option<ConfigOptionBool>("bbl_calib_mark_logo")->value, true);
|
!printer_cfg.option<ConfigOptionBool>("bbl_calib_mark_logo")->value, true);
|
||||||
else
|
else
|
||||||
|
@ -2873,7 +2873,7 @@ void TabFilament::toggle_options()
|
||||||
bool is_BBL_printer = false;
|
bool is_BBL_printer = false;
|
||||||
if (m_preset_bundle) {
|
if (m_preset_bundle) {
|
||||||
is_BBL_printer =
|
is_BBL_printer =
|
||||||
m_preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(
|
m_preset_bundle->printers.get_edited_preset().has_lidar(
|
||||||
m_preset_bundle);
|
m_preset_bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3669,7 +3669,7 @@ void TabPrinter::toggle_options()
|
||||||
//BBS: whether the preset is Bambu Lab printer
|
//BBS: whether the preset is Bambu Lab printer
|
||||||
bool is_BBL_printer = false;
|
bool is_BBL_printer = false;
|
||||||
if (m_preset_bundle) {
|
if (m_preset_bundle) {
|
||||||
is_BBL_printer = m_preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(m_preset_bundle);
|
is_BBL_printer = m_preset_bundle->printers.get_edited_preset().has_lidar(m_preset_bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool have_multiple_extruders = true;
|
bool have_multiple_extruders = true;
|
||||||
|
|
Loading…
Reference in a new issue