NEW:add "user custom texture" in bbl machine

jira: STUDIO-7407
Change-Id: I6e6fdac76573aa96dd2898cd5880604b8358fa74
This commit is contained in:
zhou.xu 2024-06-24 16:46:01 +08:00 committed by Lane.Wei
parent 56f628dac1
commit f493a4495b
7 changed files with 180 additions and 100 deletions

View File

@ -637,7 +637,7 @@ GeometryBuffer Bed3D::update_bed_triangles() const
(*model_offset_ptr)(2) = -0.41 + GROUND_Z;
std::vector<Vec2d> 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<Vec2d> new_bed_shape; // offset to correct origin

View File

@ -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;

View File

@ -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);

View File

@ -70,8 +70,6 @@ std::array<unsigned char, 4> PlateTextureForeground = {0x0, 0xae, 0x42, 0xff};
namespace Slic3r {
namespace GUI {
class Bed3D;
std::array<float, 4> PartPlate::SELECT_COLOR = { 0.2666f, 0.2784f, 0.2784f, 1.0f }; //{ 0.4196f, 0.4235f, 0.4235f, 1.0f };
std::array<float, 4> PartPlate::UNSELECT_COLOR = { 0.82f, 0.82f, 0.82f, 1.0f };
std::array<float, 4> 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<unsigned int *>(&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<GLTexture*>(&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<unsigned int*>(&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

View File

@ -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<PartPlate*> 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();

View File

@ -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<ConfigOptionString>("printer_model");
if (printer_model != nullptr && ! printer_model->value.empty()) {

View File

@ -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<unsigned char>(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<ObjectDataViewModelNode*>(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 &current_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) == &current_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<ConfigOptionString>("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<ConfigOptionPoints>("printable_area"),
*m_config->option<ConfigOptionString>("bed_custom_texture"),
dlg.build_dialog(*m_config->option<ConfigOptionPoints>("printable_area"), custom_texture,
*m_config->option<ConfigOptionString>("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<Vec2d> &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<std::string, std::string> 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<std::map<std::string, std::string> *>(&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<Vec2d> &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."));
}