mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Merge branch 'master-remote' into SoftFever
# Conflicts: # resources/profiles/Creality.json # resources/profiles/Voron.json # version.inc
This commit is contained in:
		
						commit
						6fb941cf4c
					
				
					 26 changed files with 224 additions and 70 deletions
				
			
		| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
{
 | 
			
		||||
    "name": "Bambulab",
 | 
			
		||||
    "url": "http://www.bambulab.com/Parameters/vendor/BBL.json",
 | 
			
		||||
    "version": "01.03.00.02",
 | 
			
		||||
    "version": "01.03.00.13",
 | 
			
		||||
    "force_update": "0",
 | 
			
		||||
    "description": "the initial version of BBL configurations",
 | 
			
		||||
    "machine_model_list": [
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,9 +111,10 @@
 | 
			
		|||
        "0.08"
 | 
			
		||||
    ],
 | 
			
		||||
    "printable_height": "250",
 | 
			
		||||
    "extruder_clearance_radius": "32",
 | 
			
		||||
    "extruder_clearance_radius": "57",
 | 
			
		||||
    "extruder_clearance_max_radius": "68",
 | 
			
		||||
    "extruder_clearance_height_to_rod": "36",
 | 
			
		||||
    "extruder_clearance_height_to_lid": "140",
 | 
			
		||||
    "extruder_clearance_height_to_lid": "90",
 | 
			
		||||
    "nozzle_volume": "118",
 | 
			
		||||
    "nozzle_diameter": [
 | 
			
		||||
        "0.4"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,6 +84,15 @@ public:
 | 
			
		|||
 | 
			
		||||
        std::sort(store_.begin(), store_.end(), sortfunc);
 | 
			
		||||
 | 
			
		||||
        // debug: write down intitial order
 | 
			
		||||
        for (auto it = store_.begin(); it != store_.end(); ++it) {
 | 
			
		||||
            std::stringstream ss;
 | 
			
		||||
            ss << "initial order: " << it->get().name << ", p=" << it->get().priority() << ", bed_temp=" << it->get().bed_temp << ", height=" << it->get().height
 | 
			
		||||
               << ", area=" << it->get().area();
 | 
			
		||||
            if (this->unfitindicator_)
 | 
			
		||||
                this->unfitindicator_(ss.str());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int item_id = 0;
 | 
			
		||||
        auto makeProgress = [this, &item_id](Placer &placer, size_t bin_idx) {
 | 
			
		||||
            packed_bins_[bin_idx] = placer.getItems();
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +111,7 @@ public:
 | 
			
		|||
            bool was_packed = false;
 | 
			
		||||
            int best_bed_id = -1;
 | 
			
		||||
            int bed_id_firstfit = -1;
 | 
			
		||||
            double score = LARGE_COST_TO_REJECT, best_score = LARGE_COST_TO_REJECT;
 | 
			
		||||
            double score = LARGE_COST_TO_REJECT+1, best_score = LARGE_COST_TO_REJECT+1;
 | 
			
		||||
            double score_all_plates = 0, score_all_plates_best = std::numeric_limits<double>::max();
 | 
			
		||||
            typename Placer::PackResult result, result_best, result_firstfit;
 | 
			
		||||
            size_t j = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -130,8 +139,8 @@ public:
 | 
			
		|||
                    // item is not fit because we have tried all possible plates to find a good enough fit
 | 
			
		||||
                    if (bed_id_firstfit == MAX_NUM_PLATES) {
 | 
			
		||||
                        it->get().binId(BIN_ID_UNFIT);
 | 
			
		||||
                        //if (this->unfitindicator_)
 | 
			
		||||
                        //    this->unfitindicator_(it->get().name + " bed_id_firstfit == MAX_NUM_PLATES" + ",best_score=" + std::to_string(best_score));
 | 
			
		||||
                        if (this->unfitindicator_)
 | 
			
		||||
                            this->unfitindicator_(it->get().name + " bed_id_firstfit == MAX_NUM_PLATES" + ",best_score=" + std::to_string(best_score));
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
| 
						 | 
				
			
			@ -152,10 +161,13 @@ public:
 | 
			
		|||
                }
 | 
			
		||||
 | 
			
		||||
                if(!was_packed){
 | 
			
		||||
                    //if (this->unfitindicator_)
 | 
			
		||||
                    //    this->unfitindicator_(it->get().name + " ,plate_id=" + std::to_string(j) + ",score=" + std::to_string(score)
 | 
			
		||||
                    //        + ", score_all_plates=" + std::to_string(score_all_plates)
 | 
			
		||||
                    //        + ", overfit=" + std::to_string(result.overfit()));
 | 
			
		||||
                    if (this->unfitindicator_ && !placers.empty())
 | 
			
		||||
                        this->unfitindicator_(it->get().name + ", height=" +std::to_string(it->get().height)
 | 
			
		||||
                            + " ,plate_id=" + std::to_string(j-1)
 | 
			
		||||
                            + ", score=" + std::to_string(score)
 | 
			
		||||
                            + ", best_bed_id=" + std::to_string(best_bed_id)
 | 
			
		||||
                            + ", score_all_plates=" + std::to_string(score_all_plates)
 | 
			
		||||
                            +", overfit=" + std::to_string(result.overfit()));
 | 
			
		||||
 | 
			
		||||
                    placers.emplace_back(bin);
 | 
			
		||||
                    placers.back().plateID(placers.size() - 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -533,8 +533,10 @@ void AppConfig::save()
 | 
			
		|||
    {
 | 
			
		||||
        // Returns "undefined" if the thread naming functionality is not supported by the operating system.
 | 
			
		||||
        std::optional<std::string> current_thread_name = get_current_thread_name();
 | 
			
		||||
        if (current_thread_name && *current_thread_name != "bambustu_main")
 | 
			
		||||
            throw CriticalException("Calling AppConfig::save() from a worker thread!");
 | 
			
		||||
        if (current_thread_name && *current_thread_name != "bambustu_main") {
 | 
			
		||||
            BOOST_LOG_TRIVIAL(error) << __FUNCTION__<<", current_thread_name is " << *current_thread_name;
 | 
			
		||||
            throw CriticalException("Calling AppConfig::save() from a worker thread, thread name: " + *current_thread_name);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The config is first written to a file with a PID suffix and then moved
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -404,8 +404,8 @@ protected:
 | 
			
		|||
                hasLidHeightConflict |= (p.height > clearance_height_to_lid);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            double lambda3 = LARGE_COST_TO_REJECT;
 | 
			
		||||
            double lambda4 = LARGE_COST_TO_REJECT;
 | 
			
		||||
            double lambda3 = LARGE_COST_TO_REJECT*1.1;
 | 
			
		||||
            double lambda4 = LARGE_COST_TO_REJECT*1.2;
 | 
			
		||||
            for (int i = 0; i < m_items.size(); i++) {
 | 
			
		||||
                Item& p = m_items[i];
 | 
			
		||||
                if (p.is_virt_object) continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -556,12 +556,11 @@ public:
 | 
			
		|||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
        //if (progressind) {
 | 
			
		||||
        //    m_pck.unfitIndicator([this, progressind](std::string name) {
 | 
			
		||||
        //        progressind(100, name+" not fit!");
 | 
			
		||||
        //        BOOST_LOG_TRIVIAL(debug) << "arrange not fit: " + name;
 | 
			
		||||
        //        });
 | 
			
		||||
        //}
 | 
			
		||||
        if (progressind) {
 | 
			
		||||
            m_pck.unfitIndicator([this, progressind](std::string name) {
 | 
			
		||||
                BOOST_LOG_TRIVIAL(debug) << "arrange not fit: " + name;
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (stopcond) m_pck.stopCondition(stopcond);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,6 +52,7 @@ struct ArrangePolygon {
 | 
			
		|||
    //BBS: add locked_plate to indicate whether it is in the locked plate
 | 
			
		||||
    int       locked_plate{ -1 };
 | 
			
		||||
    bool      is_virt_object{ false };
 | 
			
		||||
    bool      is_extrusion_cali_object{ false };
 | 
			
		||||
    bool      is_wipe_tower{false};
 | 
			
		||||
    //BBS: add row/col for sudoku-style layout
 | 
			
		||||
    int       row{0};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -469,7 +469,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
 | 
			
		|||
		LayerRegion* layerm = this->m_regions[surface_fill.region_id];
 | 
			
		||||
		params.config = &layerm->region().config();
 | 
			
		||||
		for (ExPolygon& expoly : surface_fill.expolygons) {
 | 
			
		||||
			f->no_overlap_expolygons = intersection_ex(layerm->fill_no_overlap_expolygons, ExPolygons() = { expoly });
 | 
			
		||||
			f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly});
 | 
			
		||||
			// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
 | 
			
		||||
			f->spacing = surface_fill.params.spacing;
 | 
			
		||||
			surface_fill.surface.expolygon = std::move(expoly);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4058,18 +4058,21 @@ void GCodeProcessor::update_slice_warnings()
 | 
			
		|||
 | 
			
		||||
    auto used_extruders = get_used_extruders();
 | 
			
		||||
    assert(!used_extruders.empty());
 | 
			
		||||
    GCodeProcessorResult::SliceWarning warning;
 | 
			
		||||
    warning.level = 1;
 | 
			
		||||
    if (m_highest_bed_temp != 0) {
 | 
			
		||||
        for (size_t i = 0; i < used_extruders.size(); i++) {
 | 
			
		||||
            int temperature = get_filament_vitrification_temperature(used_extruders[i]);
 | 
			
		||||
            if (temperature != 0 && m_highest_bed_temp > temperature) {
 | 
			
		||||
                GCodeProcessorResult::SliceWarning warning;
 | 
			
		||||
                warning.level = 1;
 | 
			
		||||
                warning.msg = BED_TEMP_TOO_HIGH_THAN_FILAMENT;
 | 
			
		||||
                m_result.warnings.emplace_back(std::move(warning));
 | 
			
		||||
            }
 | 
			
		||||
            if (temperature != 0 && m_highest_bed_temp > temperature)
 | 
			
		||||
                warning.params.push_back(std::to_string(used_extruders[i]));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!warning.params.empty()) {
 | 
			
		||||
        warning.msg   = BED_TEMP_TOO_HIGH_THAN_FILAMENT;
 | 
			
		||||
        m_result.warnings.push_back(warning);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_result.warnings.shrink_to_fit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,11 +127,11 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::
 | 
			
		|||
 | 
			
		||||
        const ConfigOptionInts* bed_opt = config.option<ConfigOptionInts>(get_bed_temp_key(curr_bed_type));
 | 
			
		||||
        if (bed_opt != nullptr)
 | 
			
		||||
            ap.bed_temp = bed_opt->get_at(ap.extrude_ids.back());
 | 
			
		||||
            ap.bed_temp = bed_opt->get_at(ap.extrude_ids.back()-1);
 | 
			
		||||
 | 
			
		||||
        const ConfigOptionInts* bed_opt_1st_layer = config.option<ConfigOptionInts>(get_bed_temp_1st_layer_key(curr_bed_type));
 | 
			
		||||
        if (bed_opt_1st_layer != nullptr)
 | 
			
		||||
            ap.first_bed_temp = bed_opt_1st_layer->get_at(ap.extrude_ids.back());
 | 
			
		||||
            ap.first_bed_temp = bed_opt_1st_layer->get_at(ap.extrude_ids.back()-1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (config.has("nozzle_temperature")) //get the print temperature
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -764,7 +764,7 @@ static std::vector<std::string> s_Preset_printer_options {
 | 
			
		|||
    "printer_technology",
 | 
			
		||||
    "printable_area", "bed_exclude_area", "gcode_flavor","z_lift_type",
 | 
			
		||||
    "single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode",
 | 
			
		||||
    "printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
 | 
			
		||||
    "printer_model", "printer_variant", "printable_height", "extruder_clearance_radius",  "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
 | 
			
		||||
    "default_print_profile", "inherits",
 | 
			
		||||
    "silent_mode",
 | 
			
		||||
    // BBS
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,6 +82,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
 | 
			
		|||
        "extruder_clearance_height_to_rod",
 | 
			
		||||
        "extruder_clearance_height_to_lid",
 | 
			
		||||
        "extruder_clearance_radius",
 | 
			
		||||
        "extruder_clearance_max_radius",
 | 
			
		||||
        "extruder_colour",
 | 
			
		||||
        "extruder_offset",
 | 
			
		||||
        "filament_flow_ratio",
 | 
			
		||||
| 
						 | 
				
			
			@ -398,6 +399,9 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
 | 
			
		|||
        const PrintInstance *print_instance;
 | 
			
		||||
        BoundingBox    bounding_box;
 | 
			
		||||
        Polygon        hull_polygon;
 | 
			
		||||
        int                  index;
 | 
			
		||||
        double         arrange_score;
 | 
			
		||||
        double               height;
 | 
			
		||||
    };
 | 
			
		||||
    std::vector<struct print_instance_info> print_instance_with_bounding_box;
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -475,6 +479,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
 | 
			
		|||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                struct print_instance_info print_info {&instance, convex_hull.bounding_box(), convex_hull};
 | 
			
		||||
                print_info.height = instance.print_object->height();
 | 
			
		||||
                print_instance_with_bounding_box.push_back(std::move(print_info));
 | 
			
		||||
                convex_hulls_other.emplace_back(std::move(convex_hull));
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -489,22 +494,104 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //sort the print instance
 | 
			
		||||
    // calc sort order
 | 
			
		||||
    double hc1              = scale_(print.config().extruder_clearance_height_to_lid); // height to lid
 | 
			
		||||
    double hc2              = scale_(print.config().extruder_clearance_height_to_rod); // height to rod
 | 
			
		||||
    double printable_height = scale_(print.config().printable_height);
 | 
			
		||||
 | 
			
		||||
    auto bed_points = get_bed_shape(print_config);
 | 
			
		||||
    float bed_width = bed_points[1].x() - bed_points[0].x();
 | 
			
		||||
    // 如果扩大以后的多边形的距离小于这个值,就需要严格保证从左到右的打印顺序,否则会撞工具头右侧
 | 
			
		||||
    float unsafe_dist = scale_(print_config.extruder_clearance_max_radius.value - print_config.extruder_clearance_radius.value);
 | 
			
		||||
    struct VecHash
 | 
			
		||||
    {
 | 
			
		||||
        size_t operator()(const Vec2i &n1) const
 | 
			
		||||
        {
 | 
			
		||||
            return std::hash<coord_t>()(int(n1(0) * 100 + 100)) + std::hash<coord_t>()(int(n1(1) * 100 + 100)) * 101;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    std::unordered_set<Vec2i, VecHash> left_right_pair; // pairs in this vector must strictly obey the left-right order
 | 
			
		||||
    for (size_t i = 0; i < print_instance_with_bounding_box.size();i++) { 
 | 
			
		||||
        auto &inst         = print_instance_with_bounding_box[i];
 | 
			
		||||
        inst.index         = i;
 | 
			
		||||
        Point pt           = inst.bounding_box.center();
 | 
			
		||||
        inst.arrange_score = pt.x() / 2 + pt.y(); // we prefer print row-by-row, so cost on x-direction is smaller
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t i = 0; i < print_instance_with_bounding_box.size(); i++) {
 | 
			
		||||
        auto &inst         = print_instance_with_bounding_box[i];        
 | 
			
		||||
        auto &l            = print_instance_with_bounding_box[i];
 | 
			
		||||
        for (size_t j = 0; j < print_instance_with_bounding_box.size(); j++) {
 | 
			
		||||
            if (j != i) { 
 | 
			
		||||
                auto &r        = print_instance_with_bounding_box[j];
 | 
			
		||||
                auto ly1       = l.bounding_box.min.y();
 | 
			
		||||
                auto ly2       = l.bounding_box.max.y();
 | 
			
		||||
                auto ry1       = r.bounding_box.min.y();
 | 
			
		||||
                auto ry2       = r.bounding_box.max.y();
 | 
			
		||||
                auto lx1       = l.bounding_box.min.x();
 | 
			
		||||
                auto rx1       = r.bounding_box.min.x();
 | 
			
		||||
                auto lx2       = l.bounding_box.max.x();
 | 
			
		||||
                auto rx2       = r.bounding_box.max.x();
 | 
			
		||||
                auto inter_min = std::max(ly1, ry1);
 | 
			
		||||
                auto inter_max = std::min(ly2, ry2);
 | 
			
		||||
                auto inter_y   = inter_max - inter_min;
 | 
			
		||||
                inter_min      = std::max(lx1, rx1);
 | 
			
		||||
                inter_max      = std::min(lx2, rx2);
 | 
			
		||||
                auto inter_x   = inter_max - inter_min;
 | 
			
		||||
 | 
			
		||||
                // 如果y方向的重合超过轮廓的膨胀量,说明两个物体在一行,应该先打左边的物体,即先比较二者的x坐标。
 | 
			
		||||
                if (inter_y > scale_(1)) {
 | 
			
		||||
                    if (std::max(rx1 - lx2, lx1 - rx2) < unsafe_dist) {
 | 
			
		||||
                        if (lx1 > rx1) {
 | 
			
		||||
                            left_right_pair.insert({j, i});
 | 
			
		||||
                            BOOST_LOG_TRIVIAL(debug) << "in-a-row, print_instance " << r.print_instance->model_instance->get_object()->name << "(" << r.arrange_score << ")"
 | 
			
		||||
                                                     << " -> " << l.print_instance->model_instance->get_object()->name << "(" << l.arrange_score << ")";
 | 
			
		||||
                        } else {
 | 
			
		||||
                            left_right_pair.insert({i, j});
 | 
			
		||||
                            BOOST_LOG_TRIVIAL(debug) << "in-a-row, print_instance " << l.print_instance->model_instance->get_object()->name << "(" << l.arrange_score << ")"
 | 
			
		||||
                                                     << " -> " << r.print_instance->model_instance->get_object()->name << "(" << r.arrange_score << ")";
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } 
 | 
			
		||||
                if (l.height > hc1 && r.height < hc1) {
 | 
			
		||||
                    // 当前物体超过了顶盖高度,必须后打
 | 
			
		||||
                    left_right_pair.insert({j, i});
 | 
			
		||||
                    BOOST_LOG_TRIVIAL(debug) << "height>hc1, print_instance " << r.print_instance->model_instance->get_object()->name << "(" << r.arrange_score << ")"
 | 
			
		||||
                                             << " -> " << l.print_instance->model_instance->get_object()->name << "(" << l.arrange_score << ")";
 | 
			
		||||
                }
 | 
			
		||||
                else if (l.height > hc2 && l.height > r.height && l.arrange_score<r.arrange_score) {
 | 
			
		||||
                    // 如果当前物体的高度超过滑杆,且比r高,就给它加一点代价,尽量让高的物体后打(只有物体高度超过滑杆时才有必要按高度来)
 | 
			
		||||
                    l.arrange_score = std::max(l.arrange_score, r.arrange_score + bed_width/2);
 | 
			
		||||
                    BOOST_LOG_TRIVIAL(debug) << "height>hc2, print_instance " << inst.print_instance->model_instance->get_object()->name
 | 
			
		||||
                                             << ", right=" << r.print_instance->model_instance->get_object()->name << ", l.score: " << l.arrange_score
 | 
			
		||||
                                             << ", r.score: " << r.arrange_score;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    BOOST_LOG_TRIVIAL(debug) << "bed width: " << bed_width << ", unsafe_dist:" << unsafe_dist;
 | 
			
		||||
    // 多做几次代价传播,因为前一次有些值没有更新。
 | 
			
		||||
    // TODO 更好的办法是建立一颗树,一步到位。不过我暂时没精力搞,先就这样吧
 | 
			
		||||
    for (int k=0;k<5;k++)
 | 
			
		||||
    for (auto p : left_right_pair) {
 | 
			
		||||
        auto &l = print_instance_with_bounding_box[p(0)];
 | 
			
		||||
        auto &r = print_instance_with_bounding_box[p(1)];
 | 
			
		||||
        if(r.arrange_score<l.arrange_score)
 | 
			
		||||
            r.arrange_score = l.arrange_score + bed_width/2;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    for (auto p : left_right_pair) {
 | 
			
		||||
        auto &l         = print_instance_with_bounding_box[p(0)];
 | 
			
		||||
        auto &r         = print_instance_with_bounding_box[p(1)];
 | 
			
		||||
        BOOST_LOG_TRIVIAL(debug) << "print_instance " << l.print_instance->model_instance->get_object()->name << "(" << l.arrange_score << ")"
 | 
			
		||||
                                 << " -> " << r.print_instance->model_instance->get_object()->name << "(" << r.arrange_score << ")";
 | 
			
		||||
    }
 | 
			
		||||
    // sort the print instance
 | 
			
		||||
    std::sort(print_instance_with_bounding_box.begin(), print_instance_with_bounding_box.end(),
 | 
			
		||||
        [](auto &l, auto &r) {
 | 
			
		||||
            auto ly1       = l.bounding_box.min.y();
 | 
			
		||||
            auto ly2       = l.bounding_box.max.y();
 | 
			
		||||
            auto ry1       = r.bounding_box.min.y();
 | 
			
		||||
            auto ry2       = r.bounding_box.max.y();
 | 
			
		||||
            auto inter_min = std::max(ly1, ry1);
 | 
			
		||||
            auto inter_max = std::min(ly2, ry2);
 | 
			
		||||
            auto lx        = l.bounding_box.min.x();
 | 
			
		||||
            auto rx        = r.bounding_box.min.x();
 | 
			
		||||
            if (inter_max - inter_min > 0)
 | 
			
		||||
                return (lx < rx) || ((lx == rx) && (ly1 < ry1));
 | 
			
		||||
            else
 | 
			
		||||
                return (ly1 < ry1);
 | 
			
		||||
        });
 | 
			
		||||
        [](print_instance_info& l, print_instance_info& r) {return l.arrange_score < r.arrange_score;});
 | 
			
		||||
 | 
			
		||||
    for (auto &inst : print_instance_with_bounding_box)
 | 
			
		||||
        BOOST_LOG_TRIVIAL(debug) << "after sorting print_instance " << inst.print_instance->model_instance->get_object()->name << ", score: " << inst.arrange_score
 | 
			
		||||
                                 << ", height:"<< inst.height;
 | 
			
		||||
 | 
			
		||||
    // sequential_print_vertical_clearance_valid
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -535,9 +622,6 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
 | 
			
		|||
                break;
 | 
			
		||||
        }*/
 | 
			
		||||
 | 
			
		||||
        double hc1 = scale_(print.config().extruder_clearance_height_to_lid);
 | 
			
		||||
        double hc2 = scale_(print.config().extruder_clearance_height_to_rod);
 | 
			
		||||
        double printable_height = scale_(print.config().printable_height);
 | 
			
		||||
 | 
			
		||||
        // if objects are not overlapped on y-axis, they will not collide even if they are taller than extruder_clearance_height_to_rod
 | 
			
		||||
        int print_instance_count = print_instance_with_bounding_box.size();
 | 
			
		||||
| 
						 | 
				
			
			@ -545,7 +629,8 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
 | 
			
		|||
        for (int k = 0; k < print_instance_count; k++)
 | 
			
		||||
        {
 | 
			
		||||
            auto inst = print_instance_with_bounding_box[k].print_instance;
 | 
			
		||||
            auto bbox = print_instance_with_bounding_box[k].bounding_box;
 | 
			
		||||
            // 只需要考虑喷嘴到滑杆的偏移量,这个比整个工具头的碰撞半径要小得多
 | 
			
		||||
            auto bbox = print_instance_with_bounding_box[k].bounding_box.inflated(-scale_(0.5 * print.config().extruder_clearance_radius.value));
 | 
			
		||||
            auto iy1 = bbox.min.y();
 | 
			
		||||
            auto iy2 = bbox.max.y();
 | 
			
		||||
            (const_cast<ModelInstance*>(inst->model_instance))->arrange_order = k+1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1025,7 +1025,7 @@ void PrintConfigDef::init_fff_params()
 | 
			
		|||
    def = this->add("extruder_clearance_height_to_rod", coFloat);
 | 
			
		||||
    def->label = L("Height to rod");
 | 
			
		||||
    def->tooltip = L("Distance of the nozzle tip to the lower rod. "
 | 
			
		||||
        "Used as input of auto-arranging to avoid collision when printing by object");
 | 
			
		||||
        "Used for collision avoidance in by-object printing.");
 | 
			
		||||
    def->sidetext = L("mm");
 | 
			
		||||
    def->min = 0;
 | 
			
		||||
    def->mode = comAdvanced;
 | 
			
		||||
| 
						 | 
				
			
			@ -1035,7 +1035,7 @@ void PrintConfigDef::init_fff_params()
 | 
			
		|||
    def = this->add("extruder_clearance_height_to_lid", coFloat);
 | 
			
		||||
    def->label = L("Height to lid");
 | 
			
		||||
    def->tooltip = L("Distance of the nozzle tip to the lid. "
 | 
			
		||||
        "Used as input of auto-arranging to avoid collision when printing by object");
 | 
			
		||||
        "Used for collision avoidance in by-object printing.");
 | 
			
		||||
    def->sidetext = L("mm");
 | 
			
		||||
    def->min = 0;
 | 
			
		||||
    def->mode = comAdvanced;
 | 
			
		||||
| 
						 | 
				
			
			@ -1043,12 +1043,20 @@ void PrintConfigDef::init_fff_params()
 | 
			
		|||
 | 
			
		||||
    def = this->add("extruder_clearance_radius", coFloat);
 | 
			
		||||
    def->label = L("Radius");
 | 
			
		||||
    def->tooltip = L("Clearance radius around extruder. Used as input of auto-arranging to avoid collision when printing by object");
 | 
			
		||||
    def->tooltip = L("Clearance radius around extruder. Used for collision avoidance in by-object printing.");
 | 
			
		||||
    def->sidetext = L("mm");
 | 
			
		||||
    def->min = 0;
 | 
			
		||||
    def->mode = comAdvanced;
 | 
			
		||||
    def->set_default_value(new ConfigOptionFloat(40));
 | 
			
		||||
 | 
			
		||||
    def           = this->add("extruder_clearance_max_radius", coFloat);
 | 
			
		||||
    def->label    = L("Max Radius");
 | 
			
		||||
    def->tooltip  = L("Max clearance radius around extruder. Used for collision avoidance in by-object printing.");
 | 
			
		||||
    def->sidetext = L("mm");
 | 
			
		||||
    def->min      = 0;
 | 
			
		||||
    def->mode     = comAdvanced;
 | 
			
		||||
    def->set_default_value(new ConfigOptionFloat(68));
 | 
			
		||||
 | 
			
		||||
    def = this->add("extruder_colour", coStrings);
 | 
			
		||||
    def->label = L("Extruder Color");
 | 
			
		||||
    def->tooltip = L("Only used as a visual help on UI");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -841,6 +841,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
 | 
			
		|||
    ((ConfigOptionFloat,              extruder_clearance_height_to_rod))//BBs
 | 
			
		||||
    ((ConfigOptionFloat,              extruder_clearance_height_to_lid))//BBS
 | 
			
		||||
    ((ConfigOptionFloat,              extruder_clearance_radius))
 | 
			
		||||
    ((ConfigOptionFloat,              extruder_clearance_max_radius))
 | 
			
		||||
    ((ConfigOptionStrings,            extruder_colour))
 | 
			
		||||
    ((ConfigOptionPoints,             extruder_offset))
 | 
			
		||||
    ((ConfigOptionBools,              reduce_fan_stop_start_freq))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,8 +31,8 @@ namespace GUI {
 | 
			
		|||
DownloadProgressDialog::DownloadProgressDialog(wxString title)
 | 
			
		||||
    : DPIDialog(static_cast<wxWindow *>(wxGetApp().mainframe), wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX)
 | 
			
		||||
{
 | 
			
		||||
    wxString download_failed_url = wxT("https://wiki.bambulab.com/e/en/software/bambu-studio/failed-to-get-network-plugin");
 | 
			
		||||
    wxString install_failed_url = wxT("https://wiki.bambulab.com/e/en/software/bambu-studio/failed-to-get-network-plugin");
 | 
			
		||||
    wxString download_failed_url = wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-get-network-plugin");
 | 
			
		||||
    wxString install_failed_url = wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-get-network-plugin");
 | 
			
		||||
 | 
			
		||||
    wxString download_failed_msg = _L("Failed to download the plug-in. Please check your firewall settings and vpn software, check and retry.");
 | 
			
		||||
    wxString install_failed_msg = _L("Failed to install the plug-in. Please check whether it is blocked or deleted by anti-virus software.");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -248,7 +248,8 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
 | 
			
		|||
                return owner.model_instance_id == id;
 | 
			
		||||
                });
 | 
			
		||||
            if (it != owners.end())
 | 
			
		||||
                it->print_order = std::string((_(L("Sequence"))).ToUTF8()) + "#: " + std::to_string(i + 1);
 | 
			
		||||
                //it->print_order = std::string((_(L("Sequence"))).ToUTF8()) + "#: " + std::to_string(i + 1);
 | 
			
		||||
                it->print_order = std::string((_(L("Sequence"))).ToUTF8()) + "#: " + std::to_string(sorted_instances[i]->arrange_order);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6032,10 +6033,20 @@ void GLCanvas3D::_render_overlays()
 | 
			
		|||
    bool sequential_print = opt != nullptr && (opt->value == PrintSequence::ByObject);
 | 
			
		||||
    std::vector<const ModelInstance*> sorted_instances;
 | 
			
		||||
    if (sequential_print) {
 | 
			
		||||
        for (ModelObject* model_object : m_model->objects)
 | 
			
		||||
        const Print* print = fff_print();
 | 
			
		||||
        if (print) {
 | 
			
		||||
            for (const PrintObject *print_object : print->objects())
 | 
			
		||||
            {
 | 
			
		||||
                for (const PrintInstance &instance : print_object->instances())
 | 
			
		||||
                {
 | 
			
		||||
                    sorted_instances.emplace_back(instance.model_instance);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        /*for (ModelObject* model_object : m_model->objects)
 | 
			
		||||
            for (ModelInstance* model_instance : model_object->instances) {
 | 
			
		||||
                sorted_instances.emplace_back(model_instance);
 | 
			
		||||
            }
 | 
			
		||||
            }*/
 | 
			
		||||
    }
 | 
			
		||||
    m_labels.render(sorted_instances);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1333,7 +1333,7 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
 | 
			
		|||
            menu->Destroy(item_id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const int filaments_cnt = filaments_count();
 | 
			
		||||
    int filaments_cnt = filaments_count();
 | 
			
		||||
    if (filaments_cnt <= 1)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1345,6 +1345,10 @@ void MenuFactory::append_menu_item_change_filament(wxMenu* menu)
 | 
			
		|||
    std::vector<wxBitmap*> icons = get_extruder_color_icons(true);
 | 
			
		||||
    if (icons.size() < filaments_cnt) {
 | 
			
		||||
        BOOST_LOG_TRIVIAL(warning) << boost::format("Warning: icons size %1%, filaments_cnt=%2%")%icons.size()%filaments_cnt;
 | 
			
		||||
        if (icons.size() <= 1)
 | 
			
		||||
            return;
 | 
			
		||||
        else
 | 
			
		||||
            filaments_cnt = icons.size();
 | 
			
		||||
    }
 | 
			
		||||
    wxMenu* extruder_selection_menu = new wxMenu();
 | 
			
		||||
    const wxString& name = sels.Count() == 1 ? names[0] : names[1];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -816,7 +816,6 @@ void AssembleView::reload_scene(bool refresh_immediately, bool force_full_scene_
 | 
			
		|||
            m_canvas->render(true);
 | 
			
		||||
        }
 | 
			
		||||
        m_canvas->reload_scene(refresh_immediately, force_full_scene_refresh);
 | 
			
		||||
        m_canvas->reload_scene(refresh_immediately, force_full_scene_refresh);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -611,6 +611,9 @@ void ModelObjectsInfo::on_update()
 | 
			
		|||
    if (!get_pool()->get_canvas()->get_model()->objects.empty()) {
 | 
			
		||||
        m_model_objects = get_pool()->get_canvas()->get_model()->objects;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        m_model_objects.clear();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ModelObjectsInfo::on_release()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -345,7 +345,7 @@ void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos)
 | 
			
		|||
void GLGizmosManager::update_assemble_view_data()
 | 
			
		||||
{
 | 
			
		||||
    if (m_assemble_view_data) {
 | 
			
		||||
        if (m_parent.get_canvas_type() != GLCanvas3D::CanvasAssembleView)
 | 
			
		||||
        if (!wxGetApp().plater()->get_assmeble_canvas3D()->get_wxglcanvas()->IsShown())
 | 
			
		||||
            m_assemble_view_data->update(AssembleViewDataID(0));
 | 
			
		||||
        else
 | 
			
		||||
            m_assemble_view_data->update(AssembleViewDataID((int)AssembleViewDataID::ModelObjectsInfo | (int)AssembleViewDataID::ModelObjectsClipper));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -503,6 +503,9 @@ void ArrangeJob::process()
 | 
			
		|||
    if (params.is_seq_print)
 | 
			
		||||
        params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius));
 | 
			
		||||
 | 
			
		||||
    if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer"))
 | 
			
		||||
        m_plater->get_partplate_list().preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
 | 
			
		||||
        
 | 
			
		||||
    double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0;
 | 
			
		||||
    double brim_max = 0;
 | 
			
		||||
    std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon ap) {  brim_max = std::max(brim_max, ap.brim_width); });
 | 
			
		||||
| 
						 | 
				
			
			@ -514,21 +517,26 @@ void ArrangeJob::process()
 | 
			
		|||
    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) {
 | 
			
		||||
        params.bed_shrink_x -= params.cleareance_radius/2;
 | 
			
		||||
        params.bed_shrink_y -= params.cleareance_radius/2;
 | 
			
		||||
        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(params.cleareance_radius/2), -scaled(params.cleareance_radius/2));
 | 
			
		||||
                region.poly.translate(-scaled(shift_dist), -scaled(shift_dist));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // do not inflate brim_width. Objects are allowed to have overlapped brim.
 | 
			
		||||
    std::for_each(m_selected.begin(), m_selected.end(), [&](auto& ap) {ap.inflation = params.min_obj_distance / 2; });
 | 
			
		||||
    std::for_each(m_unselected.begin(), m_unselected.end(), [&](auto& ap) {ap.inflation = ap.is_virt_object ? scaled(params.brim_skirt_distance) : params.min_obj_distance / 2; });
 | 
			
		||||
    // 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.
 | 
			
		||||
    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 ? scaled(params.cleareance_radius / 2) : scaled(params.brim_skirt_distance + params.cleareance_radius / 2));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer"))
 | 
			
		||||
        m_plater->get_partplate_list().preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
 | 
			
		||||
 | 
			
		||||
    m_plater->get_partplate_list().preprocess_exclude_areas(params.excluded_regions, 1);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -567,6 +575,7 @@ void ArrangeJob::process()
 | 
			
		|||
            << ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp;
 | 
			
		||||
        BOOST_LOG_TRIVIAL(debug) << "items unselected before arrange: ";
 | 
			
		||||
        for (auto item : m_unselected)
 | 
			
		||||
            if (!item.is_virt_object)
 | 
			
		||||
            BOOST_LOG_TRIVIAL(debug) << item.name << ", extruder: " << item.extrude_ids.back() << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3461,6 +3461,7 @@ bool PartPlateList::preprocess_nonprefered_areas(arrangement::ArrangePolygons& r
 | 
			
		|||
			ret.translation = Vec2crd(0, 0);
 | 
			
		||||
			ret.rotation = 0.0f;
 | 
			
		||||
			ret.is_virt_object = true;
 | 
			
		||||
            ret.is_extrusion_cali_object = true;
 | 
			
		||||
			ret.bed_idx = j;
 | 
			
		||||
			ret.height = 1;
 | 
			
		||||
			ret.name = "NonpreferedRegion" + std::to_string(index);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2020,7 +2020,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
 | 
			
		|||
    //BBS: add bed_exclude_area
 | 
			
		||||
    , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
 | 
			
		||||
        "printable_area", "bed_exclude_area", "print_sequence",
 | 
			
		||||
        "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_distance",
 | 
			
		||||
        "extruder_clearance_radius", "extruder_clearance_max_radius",
 | 
			
		||||
        "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_distance",
 | 
			
		||||
        "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material",
 | 
			
		||||
        "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume",
 | 
			
		||||
        "extruder_colour", "filament_colour", "material_colour", "printable_height", "printer_model", "printer_technology",
 | 
			
		||||
| 
						 | 
				
			
			@ -7224,7 +7225,7 @@ void Plater::add_model(bool imperial_units/* = false*/)
 | 
			
		|||
    if (!load_files(paths, strategy, ask_multi).empty()) {
 | 
			
		||||
 | 
			
		||||
        if (get_project_name() == _L("Untitled") && paths.size() > 0) {
 | 
			
		||||
            p->set_project_filename(wxString(paths[0].string()));
 | 
			
		||||
            p->set_project_filename(wxString::FromUTF8(paths[0].string()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        wxGetApp().mainframe->update_title();
 | 
			
		||||
| 
						 | 
				
			
			@ -9319,6 +9320,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
 | 
			
		|||
{
 | 
			
		||||
    bool update_scheduled = false;
 | 
			
		||||
    bool bed_shape_changed = false;
 | 
			
		||||
    bool print_sequence_changed = false;
 | 
			
		||||
    t_config_option_keys diff_keys = p->config->diff(config);
 | 
			
		||||
    for (auto opt_key : diff_keys) {
 | 
			
		||||
        if (opt_key == "filament_colour") {
 | 
			
		||||
| 
						 | 
				
			
			@ -9369,6 +9371,7 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
 | 
			
		|||
        }
 | 
			
		||||
        else if (opt_key == "print_sequence") {
 | 
			
		||||
            update_scheduled = true;
 | 
			
		||||
            print_sequence_changed = true;
 | 
			
		||||
        }
 | 
			
		||||
        else if (opt_key == "printer_model") {
 | 
			
		||||
            p->reset_gcode_toolpaths();
 | 
			
		||||
| 
						 | 
				
			
			@ -9393,6 +9396,9 @@ void Plater::on_config_change(const DynamicPrintConfig &config)
 | 
			
		|||
        if (seq_print->value == PrintSequence::ByObject) {
 | 
			
		||||
            std::string info_text = L("Print By Object: \nSuggest to use auto-arrange to avoid collisions when printing.");
 | 
			
		||||
            notify_manager->bbl_show_seqprintinfo_notification(info_text);
 | 
			
		||||
            //always show label when switch to sequence print
 | 
			
		||||
            if (print_sequence_changed)
 | 
			
		||||
                this->show_view3D_labels(true);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            notify_manager->bbl_close_seqprintinfo_notification();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,6 +89,7 @@ void ReleaseNoteDialog::update_release_note(wxString release_note, std::string v
 | 
			
		|||
    sizer_text_release_note->Add(m_staticText_release_note, 0, wxALL, 5);
 | 
			
		||||
    m_vebview_release_note->SetSizer(sizer_text_release_note);
 | 
			
		||||
    m_vebview_release_note->Layout();
 | 
			
		||||
    m_vebview_release_note->Fit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UpdateVersionDialog::alter_choice(wxCommandEvent& event)
 | 
			
		||||
| 
						 | 
				
			
			@ -333,6 +334,7 @@ void UpdateVersionDialog::update_version_info(wxString release_note, wxString ve
 | 
			
		|||
        sizer_text_release_note->Add(m_staticText_release_note, 0, wxALL, 5);
 | 
			
		||||
        m_scrollwindows_release_note->SetSizer(sizer_text_release_note);
 | 
			
		||||
        m_scrollwindows_release_note->Layout();
 | 
			
		||||
        m_scrollwindows_release_note->Fit();
 | 
			
		||||
    }  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -643,7 +643,7 @@ void SelectMachinePopup::update_other_devices()
 | 
			
		|||
    m_placeholder_panel = new wxWindow(m_scrolledWindow, wxID_ANY, wxDefaultPosition, wxSize(-1,FromDIP(26)));
 | 
			
		||||
    wxBoxSizer* placeholder_sizer = new wxBoxSizer(wxVERTICAL);
 | 
			
		||||
 | 
			
		||||
    auto m_hyperlink = new wxHyperlinkCtrl(m_placeholder_panel, wxID_ANY, _L("Can't find my devices?"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
 | 
			
		||||
    m_hyperlink = new wxHyperlinkCtrl(m_placeholder_panel, wxID_ANY, _L("Can't find my devices?"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
 | 
			
		||||
    placeholder_sizer->Add(m_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -860,6 +860,12 @@ void SelectMachinePopup::OnLeftUp(wxMouseEvent &event)
 | 
			
		|||
                wxPostEvent(p->mPanel, event);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //hyper link
 | 
			
		||||
        auto h_rect = m_hyperlink->ClientToScreen(wxPoint(0, 0));
 | 
			
		||||
        if (mouse_pos.x > h_rect.x && mouse_pos.y > h_rect.y && mouse_pos.x < (h_rect.x + m_hyperlink->GetSize().x) && mouse_pos.y < (h_rect.y + m_hyperlink->GetSize().y)) {
 | 
			
		||||
          wxLaunchDefaultBrowser(wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"));
 | 
			
		||||
        } 
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -198,6 +198,7 @@ private:
 | 
			
		|||
    int                               m_my_devices_count{0};
 | 
			
		||||
    int                               m_other_devices_count{0};
 | 
			
		||||
    wxWindow*                         m_placeholder_panel{nullptr};
 | 
			
		||||
    wxHyperlinkCtrl*                  m_hyperlink{nullptr};
 | 
			
		||||
    wxBoxSizer *                      m_sizer_body{nullptr};
 | 
			
		||||
    wxBoxSizer *                      m_sizer_my_devices{nullptr};
 | 
			
		||||
    wxBoxSizer *                      m_sizer_other_devices{nullptr};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,5 +10,5 @@ endif()
 | 
			
		|||
if(NOT DEFINED BBL_INTERNAL_TESTING)
 | 
			
		||||
set(BBL_INTERNAL_TESTING "1")
 | 
			
		||||
endif()
 | 
			
		||||
set(SLIC3R_VERSION "01.03.00.12")
 | 
			
		||||
set(SLIC3R_VERSION "01.03.00.22")
 | 
			
		||||
set(SoftFever_VERSION "1.3.2")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue