diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 9e52c5a56..b590af3ee 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -637,7 +637,7 @@ GeometryBuffer Bed3D::update_bed_triangles() const (*model_offset_ptr)(2) = -0.41 + GROUND_Z; std::vector origin_bed_shape; - for (size_t i = 0; i < m_bed_shape.size(); i++) { + for (size_t i = 0; i < m_bed_shape.size(); i++) { origin_bed_shape.push_back(m_bed_shape[i] - m_bed_shape[0]); } std::vector new_bed_shape; // offset to correct origin diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index af3f22591..cd2dc301c 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -133,7 +133,8 @@ public: // Bounding box around the print bed, axes and model, for rendering. const BoundingBoxf3& extended_bounding_box() const { return m_extended_bounding_box; } - + const std::string & get_model_filename() { return m_model_filename; } + const GLModel & get_model() { return m_model; } // Check against an expanded 2d bounding box. //FIXME shall one check against the real build volume? bool contains(const Point& point) const; diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp index 68a4f0d3c..5c5402fe9 100644 --- a/src/slic3r/GUI/BedShapeDialog.cpp +++ b/src/slic3r/GUI/BedShapeDialog.cpp @@ -295,7 +295,7 @@ wxPanel *BedShapePanel::init_texture_panel() load_btn->SetBackgroundColor(btn_bg_white); load_btn->SetBorderColor(btn_bd_white); load_btn->SetBackgroundColour(*wxWHITE); - load_btn->Enable(m_can_edit); + load_btn->Enable(true); wxSizer * load_sizer = new wxBoxSizer(wxHORIZONTAL); load_sizer->Add(load_btn, 1, wxEXPAND); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 5be069538..9d9ff6437 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -70,8 +70,6 @@ std::array PlateTextureForeground = {0x0, 0xae, 0x42, 0xff}; namespace Slic3r { namespace GUI { -class Bed3D; - std::array PartPlate::SELECT_COLOR = { 0.2666f, 0.2784f, 0.2784f, 1.0f }; //{ 0.4196f, 0.4235f, 0.4235f, 1.0f }; std::array PartPlate::UNSELECT_COLOR = { 0.82f, 0.82f, 0.82f, 1.0f }; std::array PartPlate::UNSELECT_DARK_COLOR = { 0.384f, 0.384f, 0.412f, 1.0f }; @@ -644,81 +642,78 @@ void PartPlate::render_logo_texture(GLTexture &logo_texture, const GeometryBuffe void PartPlate::render_logo(bool bottom, bool render_cali) const { - if (!m_partplate_list->render_bedtype_logo) { - // render third-party printer texture logo - if (m_partplate_list->m_logo_texture_filename.empty()) { - m_partplate_list->m_logo_texture.reset(); + // render printer custom texture logo + if (m_partplate_list->m_logo_texture_filename.empty()) { + m_partplate_list->m_logo_texture.reset(); + } else { + if (m_partplate_list->m_logo_texture.get_id() == 0 || m_partplate_list->m_logo_texture.get_source() != m_partplate_list->m_logo_texture_filename) { + m_partplate_list->m_logo_texture.reset(); + + if (boost::algorithm::iends_with(m_partplate_list->m_logo_texture_filename, ".svg")) { + /*// use higher resolution images if graphic card and opengl version allow + GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size(); + if (temp_texture->get_id() == 0 || temp_texture->get_source() != m_texture_filename) { + // generate a temporary lower resolution texture to show while no main texture levels have been compressed + if (!temp_texture->load_from_svg_file(m_texture_filename, false, false, false, max_tex_size / 8)) { + render_default(bottom, false); + return; + } + canvas.request_extra_frame(); + }*/ + + // starts generating the main texture, compression will run asynchronously + GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size(); + GLint logo_tex_size = (max_tex_size < 2048) ? max_tex_size : 2048; + if (!m_partplate_list->m_logo_texture.load_from_svg_file(m_partplate_list->m_logo_texture_filename, true, false, false, logo_tex_size)) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % m_partplate_list->m_logo_texture_filename; + return; + } + } else if (boost::algorithm::iends_with(m_partplate_list->m_logo_texture_filename, ".png")) { + // generate a temporary lower resolution texture to show while no main texture levels have been compressed + /* if (temp_texture->get_id() == 0 || temp_texture->get_source() != m_logo_texture_filename) { + if (!temp_texture->load_from_file(m_logo_texture_filename, false, GLTexture::None, false)) { + render_default(bottom, false); + return; + } + canvas.request_extra_frame(); + }*/ + + // starts generating the main texture, compression will run asynchronously + if (!m_partplate_list->m_logo_texture.load_from_file(m_partplate_list->m_logo_texture_filename, true, GLTexture::MultiThreaded, true)) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % m_partplate_list->m_logo_texture_filename; + return; + } + } else { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ + << boost::format(": can not load logo texture from %1%, unsupported format") % m_partplate_list->m_logo_texture_filename; + return; + } + } else if (m_partplate_list->m_logo_texture.unsent_compressed_data_available()) { + // sends to gpu the already available compressed levels of the main texture + m_partplate_list->m_logo_texture.send_compressed_data_to_gpu(); + + // the temporary texture is not needed anymore, reset it + // if (temp_texture->get_id() != 0) + // temp_texture->reset(); + + // canvas.request_extra_frame(); + } + + if (m_vbo_id == 0) { + unsigned int *vbo_id_ptr = const_cast(&m_vbo_id); + glsafe(::glGenBuffers(1, vbo_id_ptr)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, *vbo_id_ptr)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr) m_logo_triangles.get_vertices_data_size(), (const GLvoid *) m_logo_triangles.get_vertices_data(), + GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + } + if (m_vbo_id != 0 && m_logo_triangles.get_vertices_count() > 0) { + render_logo_texture(m_partplate_list->m_logo_texture, m_logo_triangles, bottom, m_vbo_id); + } + if (!m_partplate_list->render_bedtype_logo) { return; } - - //GLTexture* temp_texture = const_cast(&m_temp_texture); - - if (m_partplate_list->m_logo_texture.get_id() == 0 || m_partplate_list->m_logo_texture.get_source() != m_partplate_list->m_logo_texture_filename) { - m_partplate_list->m_logo_texture.reset(); - - if (boost::algorithm::iends_with(m_partplate_list->m_logo_texture_filename, ".svg")) { - /*// use higher resolution images if graphic card and opengl version allow - GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size(); - if (temp_texture->get_id() == 0 || temp_texture->get_source() != m_texture_filename) { - // generate a temporary lower resolution texture to show while no main texture levels have been compressed - if (!temp_texture->load_from_svg_file(m_texture_filename, false, false, false, max_tex_size / 8)) { - render_default(bottom, false); - return; - } - canvas.request_extra_frame(); - }*/ - - // starts generating the main texture, compression will run asynchronously - GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size(); - GLint logo_tex_size = (max_tex_size < 2048) ? max_tex_size : 2048; - if (!m_partplate_list->m_logo_texture.load_from_svg_file(m_partplate_list->m_logo_texture_filename, true, false, false, logo_tex_size)) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % m_partplate_list->m_logo_texture_filename; - return; - } - } - else if (boost::algorithm::iends_with(m_partplate_list->m_logo_texture_filename, ".png")) { - // generate a temporary lower resolution texture to show while no main texture levels have been compressed - /* if (temp_texture->get_id() == 0 || temp_texture->get_source() != m_logo_texture_filename) { - if (!temp_texture->load_from_file(m_logo_texture_filename, false, GLTexture::None, false)) { - render_default(bottom, false); - return; - } - canvas.request_extra_frame(); - }*/ - - // starts generating the main texture, compression will run asynchronously - if (!m_partplate_list->m_logo_texture.load_from_file(m_partplate_list->m_logo_texture_filename, true, GLTexture::MultiThreaded, true)) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % m_partplate_list->m_logo_texture_filename; - return; - } - } - else { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": can not load logo texture from %1%, unsupported format") % m_partplate_list->m_logo_texture_filename; - return; - } - } - else if (m_partplate_list->m_logo_texture.unsent_compressed_data_available()) { - // sends to gpu the already available compressed levels of the main texture - m_partplate_list->m_logo_texture.send_compressed_data_to_gpu(); - - // the temporary texture is not needed anymore, reset it - //if (temp_texture->get_id() != 0) - // temp_texture->reset(); - - //canvas.request_extra_frame(); - } - - if (m_vbo_id == 0) { - unsigned int* vbo_id_ptr = const_cast(&m_vbo_id); - glsafe(::glGenBuffers(1, vbo_id_ptr)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, *vbo_id_ptr)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)m_logo_triangles.get_vertices_data_size(), (const GLvoid*)m_logo_triangles.get_vertices_data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - } - if (m_vbo_id != 0 && m_logo_triangles.get_vertices_count() > 0) - render_logo_texture(m_partplate_list->m_logo_texture, m_logo_triangles, bottom, m_vbo_id); - return; - } + } m_partplate_list->load_bedtype_textures(); m_partplate_list->load_cali_textures(); @@ -2506,10 +2501,10 @@ void PartPlate::generate_logo_polygon(ExPolygon &logo_polygon) { const Vec2d& p = m_shape[i]; if ((i == 0) || (i == 1)) { - logo_polygon.contour.append({ scale_(p(0)), scale_(p(1) - 12.f) }); + logo_polygon.contour.append({ scale_(p(0)), scale_(p(1) - 10.f) }); } else { - logo_polygon.contour.append({ scale_(p(0)), scale_(p(1)) }); + logo_polygon.contour.append({scale_(p(0)), scale_(p(1) + 10.f)}); } } } @@ -2520,6 +2515,40 @@ void PartPlate::generate_logo_polygon(ExPolygon &logo_polygon) } } +void PartPlate::generate_logo_polygon(ExPolygon &logo_polygon, const BoundingBoxf3 &box) { + if (box.defined) { + { + Vec2d p(box.min.x(), box.min.y()); + logo_polygon.contour.append({scale_(p(0)), scale_(p(1))}); + } + { + Vec2d p(box.max.x(), box.min.y()); + logo_polygon.contour.append({scale_(p(0)), scale_(p(1))}); + } + { + Vec2d p(box.max.x(), box.max.y()); + logo_polygon.contour.append({scale_(p(0)), scale_(p(1))}); + } + { + Vec2d p(box.min.x(), box.max.y()); + logo_polygon.contour.append({scale_(p(0)), scale_(p(1))}); + } + } +} + +void PartPlate::set_logo_box_by_bed(const BoundingBoxf3& box) +{ + if (box.defined) { + ExPolygon logo_poly; + generate_logo_polygon(logo_poly, box); + if (!m_logo_triangles.set_from_triangles(triangulate_expolygon_2f(logo_poly, NORMALS_UP), GROUND_Z + 0.02f)) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":error :Unable to create logo triangles in set_logo_box_by_bed\n"; + return; + } + m_partplate_list->m_logo_texture.reset(); + } +} + void PartPlate::generate_print_polygon(ExPolygon &print_polygon) { auto compute_points = [&print_polygon](Vec2d& center, double radius, double start_angle, double stop_angle, int count) @@ -2690,6 +2719,9 @@ bool PartPlate::set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Ve else { ; } + if (m_partplate_list->m_bed3d && !m_partplate_list->m_bed3d->get_model_filename().empty()) { + set_logo_box_by_bed(m_partplate_list->m_bed3d->get_model().get_bounding_box()); + } ExPolygon poly; /*for (const Vec2d& p : m_shape) { @@ -3629,6 +3661,10 @@ void PartPlateList::reinit() return; } +void PartPlateList::set_bed3d(Bed3D *_bed3d) { + m_bed3d = _bed3d; +} + /*basic plate operations*/ //create an empty plate, and return its index //these model instances which are not in any plates should not be affected also diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 4e9799fee..9479c7d2d 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -70,7 +70,7 @@ class Plater; class GLCanvas3D; struct Camera; class PartPlateList; - +class Bed3D; using GCodeResult = GCodeProcessorResult; class PartPlate : public ObjectBase @@ -174,6 +174,7 @@ private: void generate_print_polygon(ExPolygon &print_polygon); void generate_exclude_polygon(ExPolygon &exclude_polygon); void generate_logo_polygon(ExPolygon &logo_polygon); + void generate_logo_polygon(ExPolygon &logo_polygon,const BoundingBoxf3& box); void calc_bounding_boxes() const; void calc_triangles(const ExPolygon& poly); void calc_exclude_triangles(const ExPolygon& poly); @@ -240,6 +241,7 @@ public: void reset_bed_type(); DynamicPrintConfig* config() { return &m_config; } + void set_logo_box_by_bed(const BoundingBoxf3& box); // set print sequence per plate //bool print_seq_same_global = true; void set_print_seq(PrintSequence print_seq = PrintSequence::ByDefault); @@ -534,6 +536,7 @@ class PartPlateList : public ObjectBase { Plater* m_plater; //Plater reference, not own it Model* m_model; //Model reference, not own it + Bed3D * m_bed3d{nullptr}; PrinterTechnology printer_technology; std::vector m_plate_list; @@ -667,7 +670,7 @@ public: //reset partplate to init states void reinit(); - + void set_bed3d(Bed3D* _bed3d); //get the plate stride double plate_stride_x(); double plate_stride_y(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 09f266120..279860f82 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2797,6 +2797,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_DEL_FILAMENT, &priv::on_delete_filament, this); this->q->Bind(EVT_ADD_CUSTOM_FILAMENT, &priv::on_add_custom_filament, this); view3D = new View3D(q, bed, &model, config, &background_process); + partplate_list.set_bed3d(&bed); //BBS: use partplater's gcode preview = new Preview(q, bed, &model, config, &background_process, partplate_list.get_current_slice_result(), [this]() { schedule_background_process(); }); @@ -12495,8 +12496,22 @@ void Plater::set_bed_shape() const auto bundle = wxGetApp().preset_bundle; if (bundle != nullptr) { const Preset* curr = &bundle->printers.get_selected_preset(); - if (curr->is_system) + if (curr->is_system) { texture_filename = PresetUtils::system_printer_bed_texture(*curr); + bool is_configed_by_BBL = PresetUtils::system_printer_bed_model(*curr).size() > 0; + if (is_configed_by_BBL && wxGetApp().app_config->has_section("user_bbl_svg_list")) { + auto cur_preset_name = bundle->printers.get_edited_preset().name; + auto user_bbl_svg_list = wxGetApp().app_config->get_section("user_bbl_svg_list"); + if (user_bbl_svg_list.size() > 0 && user_bbl_svg_list[cur_preset_name].size() > 0) { + texture_filename = user_bbl_svg_list[cur_preset_name]; } + else { + bool is_bbl_preset = bundle->printers.get_selected_preset().is_bbl_vendor_preset(bundle); + if (is_bbl_preset) { + texture_filename = ""; + } + } + } + } else { auto *printer_model = curr->config.opt("printer_model"); if (printer_model != nullptr && ! printer_model->value.empty()) { diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 4bf2376e5..7a7b5ce25 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1565,7 +1565,7 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) if (opt_key == "filament_long_retractions_when_cut"){ unsigned char activate = boost::any_cast(value); if (activate == 1) { - MessageDialog dialog(wxGetApp().plater(), + MessageDialog dialog(wxGetApp().plater(), _L("Experimental feature: Retracting and cutting off the filament at a greater distance during filament changes to minimize flush." "Although it can notably reduce flush, it may also elevate the risk of nozzle clogs or other printing complications.Please use with the latest printer firmware."), "", wxICON_WARNING | wxOK); dialog.ShowModal(); @@ -2748,7 +2748,7 @@ void TabPrintPlate::notify_changed(ObjectBase* object) for (auto item : items) { if (objects_list->GetModel()->GetItemType(item) == itPlate) { ObjectDataViewModelNode* node = static_cast(item.GetID()); - if (node) + if (node) node->set_action_icon(!m_all_keys.empty()); } } @@ -2756,7 +2756,7 @@ void TabPrintPlate::notify_changed(ObjectBase* object) void TabPrintPlate::update_custom_dirty() { - for (auto k : m_null_keys) + for (auto k : m_null_keys) m_options_list[k] = 0; for (auto k : m_all_keys) { if (k == "first_layer_sequence_choice" || k == "other_layers_sequence_choice") { @@ -3573,7 +3573,7 @@ void TabPrinter::build_fff() option.opt.is_code = true; option.opt.height = gcode_field_height;//150; optgroup->append_single_option_line(option); - + optgroup = page->new_optgroup(L("Time lapse G-code"), L"param_gcode", 0); optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) { validate_custom_gcode_cb(this, optgroup, opt_key, value); @@ -4600,13 +4600,13 @@ bool Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, try { //BBS delete preset Preset ¤t_preset = m_presets->get_selected_preset(); - + // Obtain compatible filament and process presets for printers if (m_preset_bundle && m_presets->get_preset_base(current_preset) == ¤t_preset && printer_tab && !current_preset.is_system) { delete_third_printer = true; for (const Preset &preset : m_preset_bundle->filaments.get_presets()) { if (preset.is_compatible && !preset.is_default) { - if (preset.inherits() != "") + if (preset.inherits() != "") filament_presets.push_front(preset); else filament_presets.push_back(preset); @@ -4731,7 +4731,7 @@ bool Tab::select_preset(std::string preset_name, bool delete_current /*=false*/, }); } - + } if (technology_changed) @@ -5483,22 +5483,47 @@ wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent) btn->Bind(wxEVT_BUTTON, ([this](wxCommandEvent e) { bool is_configed_by_BBL = PresetUtils::system_printer_bed_model(m_preset_bundle->printers.get_edited_preset()).size() > 0; + ConfigOptionString custom_texture = *m_config->option("bed_custom_texture"); + PresetBundle & preset_bundle = *wxGetApp().preset_bundle; + auto cur_preset_name = preset_bundle.printers.get_edited_preset().name; + if (is_configed_by_BBL && wxGetApp().app_config->has_section("user_bbl_svg_list")) { + auto user_bbl_svg_list = wxGetApp().app_config->get_section("user_bbl_svg_list"); + if (user_bbl_svg_list.size() > 0 && user_bbl_svg_list[cur_preset_name].size() > 0) { + custom_texture = ConfigOptionString(user_bbl_svg_list[cur_preset_name]); + } + } BedShapeDialog dlg(this); - dlg.build_dialog(*m_config->option("printable_area"), - *m_config->option("bed_custom_texture"), + dlg.build_dialog(*m_config->option("printable_area"), custom_texture, *m_config->option("bed_custom_model") , !is_configed_by_BBL); - if (dlg.ShowModal() == wxID_OK && !is_configed_by_BBL) { + if (dlg.ShowModal() == wxID_OK) { if (dlg.get_valid()) { - const std::vector &shape = dlg.get_shape(); - const std::string & custom_texture = dlg.get_custom_texture(); - const std::string & custom_model = dlg.get_custom_model(); - if (!shape.empty()) { - load_key_value("printable_area", shape); + if (is_configed_by_BBL) { + std::string custom_texture = dlg.get_custom_texture(); + {//save to user_bbl_svg_list + if (!wxGetApp().app_config->has_section("user_bbl_svg_list")) { + std::map data; + data[cur_preset_name] = custom_texture; + wxGetApp().app_config->set_section("user_bbl_svg_list", data); + } else { + auto data = wxGetApp().app_config->get_section("user_bbl_svg_list"); + auto data_modify = const_cast *>(&data); + (*data_modify)[cur_preset_name] = custom_texture; + wxGetApp().app_config->set_section("user_bbl_svg_list", *data_modify); + } + } load_key_value("bed_custom_texture", custom_texture); - load_key_value("bed_custom_model", custom_model); update_changed_ui(); + } else { + const std::vector &shape = dlg.get_shape(); + const std::string & custom_texture = dlg.get_custom_texture(); + const std::string & custom_model = dlg.get_custom_model(); + if (!shape.empty()) { + load_key_value("printable_area", shape); + load_key_value("bed_custom_texture", custom_texture); + load_key_value("bed_custom_model", custom_model); + update_changed_ui(); + } } - } else { show_error(m_parent, _L("Invalid input.")); }