Merge upstream/main into belt-printer

Brings belt-printer up to main 4b4a261787. Resolutions:

- G-code header (#15897, #15915): main moved the header, config and
  thumbnail block later in _do_export; write_belt_header() moves with it,
  still after the thumbnails and outside the BTT_TFT gate.
- _extrude: first-layer acceleration keeps the per-path first-layer plane
  test with main's cached nozzle index (#16028); main's set_speed out-param
  form (#16108) everywhere else.
- GCodeWriter (#16108): the arc-to-polyline fallback for machine mappings
  that cannot express G2/G3 now runs in the out-param extrude_arc_to_xy,
  which is the overload GCode calls, and appends to the caller's string.
- GCodeProcessorResult: the belt fields join main's forwarding assign.
- Clipper2 (#15969): belt arrange helpers take Slic3r::Point; the tree
  support join types lose their ClipperLib qualifier.
- CLI arrange (#15837): belt printers still reserve no wipe tower.
- Wipe tower options (#15841): the two new sparse-layer toggles are hidden
  for belt printers like the rest of the tower options.
- Keyboard shortcuts (#15706): main's registry replaces the old key switch;
  the belt view toggle is re-registered in the next commit.
- Print::process: the belt purge-plan undo runs before main's SliceStarted
  event.
- scripts/filament_id_snapshot.json: deleted on main (a77209af8f).
- Includes and appended tests: union of both sides.
This commit is contained in:
harrierpigeon
2026-10-04 19:20:33 -05:00
11471 changed files with 2992690 additions and 2720441 deletions
+269 -158
View File
@@ -1,7 +1,56 @@
#include <boost/optional/optional.hpp>
#include <array>
#include <cassert>
#include <cmath>
#include <boost/algorithm/string/erase.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <cstddef>
#include <algorithm>
#include "libslic3r/Color.hpp"
#include "libslic3r/Point.hpp"
#include "libslic3r/Config.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/Line.hpp"
#include "libslic3r/Polyline.hpp"
#include "libslic3r/ExPolygon.hpp"
#include <iterator>
#include "libslic3r/BuildVolume.hpp"
#include "libslic3r/GCode/WipeTower.hpp"
#include "libslic3r/CustomGCode.hpp"
#include "libslic3r/GCode/GCodeProcessor.hpp"
#include <ios>
#include <iomanip>
#include "libslic3r/Arrange.hpp"
#include "libslic3r/PrintBase.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/format.hpp"
#include <cstring>
#include <exception>
#include "libslic3r/ParameterUtils.hpp"
#include <imgui.h>
#include "libslic3r/Format/bbs_3mf.hpp"
#include "libslic3r/Print.hpp"
#include "libslic3r/LocalesUtils.hpp"
#include <cstdlib>
#include <limits>
#include <memory>
#include <map>
#include <mutex>
#include <numeric>
#include "slic3r/GUI/ImGuiWrapper.hpp"
#include <utility>
#include "slic3r/GUI/MeshUtils.hpp"
#include "slic3r/GUI/GLTexture.hpp"
#include "slic3r/GUI/GLShader.hpp"
#include "slic3r/GUI/OpenGLManager.hpp"
#include "slic3r/GUI/SceneRaycaster.hpp"
#include <set>
#include <unordered_map>
#include <unordered_set>
#include "slic3r/GUI/3DScene.hpp"
#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI_ObjectLayers.hpp"
#include <vector>
#include <string>
#include <sstream>
@@ -29,6 +78,7 @@
#include "libslic3r/Tesselate.hpp"
#include "libslic3r/GCode/ThumbnailData.hpp"
#include "libslic3r/Utils.hpp"
#include "libslic3r/LifecycleEvents.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
@@ -47,7 +97,15 @@
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/Utils/FileHelp.hpp"
#include <imgui/imgui_internal.h>
#include <wx/colour.h>
#include <wx/dcgraph.h>
#include <wx/string.h>
#include <wx/types.h>
#include <wx/dcmemory.h>
#include <wx/intl.h>
#include <wx/event.h>
#include <wx/image.h>
#include <wx/gdicmn.h>
using boost::optional;
namespace fs = boost::filesystem;
@@ -809,67 +867,8 @@ void PartPlate::render_logo(bool bottom, bool render_cali)
{
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();
if (!m_partplate_list->load_logo_texture())
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, true, true, 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_logo_triangles.is_initialized())
render_logo_texture(m_partplate_list->m_logo_texture, m_logo_triangles, bottom);
@@ -1064,7 +1063,13 @@ void PartPlate::render_grid(bool bottom) {
void PartPlate::render_height_limit(PartPlate::HeightLimitMode mode)
{
if (m_print && m_print->config().print_sequence == PrintSequence::ByObject && mode != HEIGHT_LIMIT_NONE)
// Orca: a prime tower compacted by "No sparse layers" drags the nozzle back down to the plate on
// every toolchange, so the rod and the lid limit how tall a neighbouring object may be exactly as
// they do in sequential printing. The reference lines are just as useful there.
const bool relevant_for_print_mode = m_print && (m_print->config().print_sequence == PrintSequence::ByObject ||
(m_print->config().print_sequence == PrintSequence::ByLayer &&
wipe_tower_sparse_layers_skipped(m_print->config()) && m_print->has_wipe_tower()));
if (relevant_for_print_mode && mode != HEIGHT_LIMIT_NONE)
{
// draw lower limit
// ORCA: OpenGL Core Profile
@@ -1120,19 +1125,9 @@ void PartPlate::render_plate_name_texture()
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
}
void PartPlate::show_tooltip(const std::string tooltip)
void PartPlate::set_hover_tooltip(const std::string& tooltip)
{
const auto scale = m_plater->get_current_canvas3D()->get_scale();
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {6 * scale, 3 * scale});
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3 * scale);
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
ImGui::PushStyleColor(ImGuiCol_Border, {0, 0, 0, 0});
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.00f, 1.00f, 1.00f, 1.00f));
ImGui::BeginTooltip();
ImGui::TextUnformatted(tooltip.c_str());
ImGui::EndTooltip();
ImGui::PopStyleColor(3);
ImGui::PopStyleVar(2);
m_partplate_list->m_hover_tooltip = tooltip;
}
void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
@@ -1157,21 +1152,21 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
if (!only_name) {
if (hover_id == 1) {
render_icon_texture(m_del_icon.model, m_partplate_list->m_del_hovered_texture);
show_tooltip(_u8L("Remove current plate (if not last one)"));
set_hover_tooltip(_u8L("Remove current plate (if not last one)"));
}
else
render_icon_texture(m_del_icon.model, m_partplate_list->m_del_texture);
if (hover_id == 2) {
render_icon_texture(m_orient_icon.model, m_partplate_list->m_orient_hovered_texture);
show_tooltip(_u8L("Auto orient objects on current plate"));
set_hover_tooltip(_u8L("Auto orient objects on current plate"));
}
else
render_icon_texture(m_orient_icon.model, m_partplate_list->m_orient_texture);
if (hover_id == 3) {
render_icon_texture(m_arrange_icon.model, m_partplate_list->m_arrange_hovered_texture);
show_tooltip(_u8L("Arrange objects on current plate"));
set_hover_tooltip(_u8L("Arrange objects on current plate"));
}
else
render_icon_texture(m_arrange_icon.model, m_partplate_list->m_arrange_texture);
@@ -1180,12 +1175,12 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
if (this->is_locked()) {
render_icon_texture(m_lock_icon.model,
m_partplate_list->m_locked_hovered_texture);
show_tooltip(_u8L("Unlock current plate"));
set_hover_tooltip(_u8L("Unlock current plate"));
}
else {
render_icon_texture(m_lock_icon.model,
m_partplate_list->m_lockopen_hovered_texture);
show_tooltip(_u8L("Lock current plate"));
set_hover_tooltip(_u8L("Lock current plate"));
}
} else {
if (this->is_locked())
@@ -1199,21 +1194,21 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
if (dual_bbl) {
if (hover_id == PLATE_FILAMENT_MAP_ID){
render_icon_texture(m_plate_filament_map_icon.model, m_partplate_list->m_plate_set_filament_map_hovered_texture);
show_tooltip(_u8L("Filament grouping"));
set_hover_tooltip(_u8L("Filament grouping"));
} else
render_icon_texture(m_plate_filament_map_icon.model, m_partplate_list->m_plate_set_filament_map_texture);
}
if (hover_id == 6) {
render_icon_texture(m_plate_name_edit_icon.model, m_partplate_list->m_plate_name_edit_hovered_texture);
show_tooltip(_u8L("Edit current plate name"));
set_hover_tooltip(_u8L("Edit current plate name"));
}
else
render_icon_texture(m_plate_name_edit_icon.model, m_partplate_list->m_plate_name_edit_texture);
if (hover_id == 7) {
render_icon_texture(m_move_front_icon.model, m_partplate_list->m_move_front_hovered_texture);
show_tooltip(_u8L("Move plate to the front"));
set_hover_tooltip(_u8L("Move plate to the front"));
} else
render_icon_texture(m_move_front_icon.model, m_partplate_list->m_move_front_texture);
@@ -1226,7 +1221,7 @@ void PartPlate::render_icons(bool bottom, bool only_name, int hover_id)
else
render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_changed_hovered_texture);
show_tooltip(_u8L("Customize current plate"));
set_hover_tooltip(_u8L("Customize current plate"));
} else {
if (!has_plate_settings)
render_icon_texture(m_plate_settings_icon.model, m_partplate_list->m_plate_settings_texture);
@@ -2641,11 +2636,20 @@ void PartPlate::set_plate_name(const std::string& name)
if (boost::equals(m_name, name))
return;
const std::string previous_name = m_name;
m_name = name;
if (m_print != nullptr)
m_print->set_plate_name(name);
invalidate_plate_name_texture();
if (m_plater != nullptr && !m_plater->is_loading_project()) {
LifecycleEventContext ctx;
ctx.name = name;
ctx.previous_name = previous_name;
ctx.index = m_plate_index;
fire_lifecycle_event(LifecycleEvent::PlateRenamed, ctx);
}
}
//get the print's object, result and index
@@ -3528,7 +3532,7 @@ bool PartPlate::intersects(const BoundingBoxf3& bb) const
return print_volume.intersects(bb);
}
void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali, bool show_grid)
void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_body, bool force_background_color, HeightLimitMode mode, int hover_id, bool render_cali, bool show_grid, bool hide_chrome)
{
glsafe(::glEnable(GL_DEPTH_TEST));
@@ -3576,19 +3580,24 @@ void PartPlate::render(const Transform3d& view_matrix, const Transform3d& projec
shader->stop_using();
}
if (wxGetApp().show_plate_gridlines() && show_grid)
if (wxGetApp().show_plate_gridlines() && show_grid) {
glsafe(::glDepthMask(bottom ? GL_TRUE : GL_FALSE));
render_grid(bottom);
glsafe(::glDepthMask(GL_TRUE));
}
if (!bottom && m_selected && !force_background_color) {
if (!hide_chrome && !bottom && m_selected && !force_background_color) {
if (m_partplate_list)
render_logo(bottom, m_partplate_list->render_cali_logo && render_cali);
else
render_logo(bottom);
}
render_icons(bottom, only_body, hover_id);
if (!force_background_color) {
render_only_numbers(bottom);
if (!hide_chrome) {
render_icons(bottom, only_body, hover_id);
if (!force_background_color) {
render_only_numbers(bottom);
}
}
glsafe(::glDisable(GL_DEPTH_TEST));
@@ -4248,6 +4257,7 @@ Vec2d PartPlateList::compute_shape_position(int index, int cols)
//generate icon textures
void PartPlateList::generate_icon_textures()
{
m_icon_textures_dark = m_is_dark;
// use higher resolution images if graphic card and opengl version allow
GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size(), icon_size = max_tex_size / 8;
std::string path = resources_dir() + "/images/";
@@ -4463,6 +4473,9 @@ void PartPlateList::release_icon_textures()
PartPlateList::is_load_bedtype_textures = false;
PartPlateList::is_load_extruder_only_area_textures = false;
PartPlateList::is_load_cali_texture = false;
m_next_bedtype_texture = 0;
m_next_extruder_only_area_texture = 0;
m_next_cali_texture = 0;
for (int i = 0; i < btCount; i++) {
for (auto& part: bed_texture_info[i].parts) {
if (part.texture) {
@@ -4770,9 +4783,16 @@ int PartPlateList::create_plate(bool adjust_position)
if (m_plater) {
// In GUI mode
wxGetApp().obj_list()->on_plate_added(plate);
wxGetApp().obj_list()->on_plate_added(plate);
}
if (m_plater != nullptr && m_intialized && !m_plater->is_loading_project()) {
LifecycleEventContext ctx;
ctx.name = plate->get_plate_name();
ctx.index = new_index;
fire_lifecycle_event(LifecycleEvent::PlateCreated, ctx);
}
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(":created a new plate %1%") % new_index;
return new_index;
}
@@ -4871,6 +4891,7 @@ int PartPlateList::delete_plate(int index)
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(":plate %1%, has an invalid index %2%") % index % plate->get_index();
return -1;
}
const std::string plate_name = plate->get_plate_name();
if (m_plater) {
// In GUI mode
@@ -4953,6 +4974,13 @@ int PartPlateList::delete_plate(int index)
delete plate;
if (m_plater != nullptr && m_intialized && !m_plater->is_loading_project()) {
LifecycleEventContext ctx;
ctx.name = plate_name;
ctx.index = index;
fire_lifecycle_event(LifecycleEvent::PlateDeleted, ctx);
}
// FIX: context of BackgroundSliceProcess and gcode preview need to be updated before ObjectList::reload_all_plates().
#if 0
if (m_plater != nullptr) {
@@ -5061,6 +5089,7 @@ int PartPlateList::select_plate(int index)
if (m_plate_list.empty() || index >= m_plate_list.size()) {
return -1;
}
const int previous_index = m_current_plate;
// BBS: erase unnecessary snapshot
if (get_curr_plate_index() != index && m_intialized) {
@@ -5087,6 +5116,13 @@ int PartPlateList::select_plate(int index)
//wxQueueEvent(m_plater, new SimpleEvent(EVT_GLCANVAS_PLATE_SELECT));
}
if (previous_index != index && m_intialized && m_plater != nullptr && !m_plater->is_loading_project()) {
LifecycleEventContext ctx;
ctx.name = m_plate_list[index]->get_plate_name();
ctx.index = index;
fire_lifecycle_event(LifecycleEvent::PlateSelected, ctx);
}
return 0;
}
@@ -5983,7 +6019,7 @@ void PartPlateList::postprocess_arrange_polygon(arrangement::ArrangePolygon& arr
/*rendering related functions*/
//render
void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali, bool show_grid)
void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool only_current, bool only_body, int hover_id, bool render_cali, bool show_grid, bool hide_chrome)
{
const std::lock_guard<std::mutex> local_lock(m_plates_mutex);
std::vector<PartPlate*>::iterator it = m_plate_list.begin();
@@ -5995,12 +6031,7 @@ void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& pr
plate_hover_action = hover_id % PartPlate::GRABBER_COUNT;
}
static bool last_dark_mode_status = m_is_dark;
if (m_is_dark != last_dark_mode_status) {
last_dark_mode_status = m_is_dark;
generate_icon_textures();
} else if(m_del_texture.get_id() == 0)
generate_icon_textures();
load_icon_textures();
for (it = m_plate_list.begin(); it != m_plate_list.end(); it++) {
int current_index = (*it)->get_index();
if (only_current && (current_index != m_current_plate))
@@ -6008,19 +6039,37 @@ void PartPlateList::render(const Transform3d& view_matrix, const Transform3d& pr
if (current_index == m_current_plate) {
PartPlate::HeightLimitMode height_mode = (only_current)?PartPlate::HEIGHT_LIMIT_NONE:m_height_limit_mode;
if (plate_hover_index == current_index)
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, plate_hover_action, render_cali, show_grid);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, plate_hover_action, render_cali, show_grid, hide_chrome);
else
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, -1, render_cali, show_grid);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, height_mode, -1, render_cali, show_grid, hide_chrome);
}
else {
if (plate_hover_index == current_index)
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali, show_grid);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, plate_hover_action, render_cali, show_grid, hide_chrome);
else
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali, show_grid);
(*it)->render(view_matrix, projection_matrix, bottom, only_body, false, PartPlate::HEIGHT_LIMIT_NONE, -1, render_cali, show_grid, hide_chrome);
}
}
}
void PartPlateList::render_hover_tooltip() const
{
if (m_hover_tooltip.empty())
return;
const auto scale = m_plater->get_current_canvas3D()->get_scale();
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {6 * scale, 3 * scale});
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 3 * scale);
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
ImGui::PushStyleColor(ImGuiCol_Border, {0, 0, 0, 0});
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.00f, 1.00f, 1.00f, 1.00f));
ImGui::BeginTooltip();
ImGui::TextUnformatted(m_hover_tooltip.c_str());
ImGui::EndTooltip();
ImGui::PopStyleColor(3);
ImGui::PopStyleVar(2);
}
/*int PartPlateList::select_plate_by_hover_id(int hover_id)
{
int index = hover_id / PartPlate::GRABBER_COUNT;
@@ -6124,6 +6173,8 @@ bool PartPlateList::set_shapes(const Pointfs &shape,
}
is_load_bedtype_textures = false; //reload textures
is_load_extruder_only_area_textures = false; // reload textures
m_next_bedtype_texture = 0;
m_next_extruder_only_area_texture = 0;
calc_bounding_boxes();
update_logo_texture_filename(texture_filename);
@@ -7064,53 +7115,120 @@ bool PartPlateList::init_extruder_only_area_info()
return true;
}
void PartPlateList::load_bedtype_textures()
static GLint logo_texture_size()
{
if (PartPlateList::is_load_bedtype_textures) return;
init_bed_type_info();
GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size();
GLint logo_tex_size = (max_tex_size < 2048) ? max_tex_size : 2048;
for (int i = 0; i < (unsigned int)btCount; ++i) {
for (int j = 0; j < bed_texture_info[i].parts.size(); j++) {
std::string filename = resources_dir() + "/images/" + bed_texture_info[i].parts[j].filename;
if (boost::filesystem::exists(filename)) {
PartPlateList::bed_texture_info[i].parts[j].texture = new GLTexture();
if (!PartPlateList::bed_texture_info[i].parts[j].texture->load_from_svg_file(filename, true, true, true, logo_tex_size)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % filename;
}
} else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % filename;
}
}
}
PartPlateList::is_load_bedtype_textures = true;
return std::min<GLint>(OpenGLManager::get_gl_info().get_max_tex_size(), 2048);
}
void PartPlateList::load_extruder_only_area_textures() {
if (PartPlateList::is_load_extruder_only_area_textures) return;
// Loads the texture of the next untried part across the parts of `infos`, in order, advancing
// `next`; false once every part has been tried.
static bool load_next_part_texture(PartPlateList::BedTextureInfo* infos, size_t count, size_t& next, bool compress_and_filter)
{
size_t k = next;
for (size_t i = 0; i < count; ++i) {
if (k >= infos[i].parts.size()) {
k -= infos[i].parts.size();
continue;
}
++next;
PartPlateList::BedTextureInfo::TexturePart& part = infos[i].parts[k];
const std::string filename = resources_dir() + "/images/" + part.filename;
if (boost::filesystem::exists(filename)) {
part.texture = new GLTexture();
if (!part.texture->load_from_svg_file(filename, true, compress_and_filter, compress_and_filter, logo_texture_size()))
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load texture from %1% failed!") % filename;
} else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load texture from %1% failed!") % filename;
}
return true;
}
return false;
}
auto ok = init_extruder_only_area_info();
if (!ok) {
void PartPlateList::load_bedtype_textures()
{
while (load_next_bedtype_texture()) {}
}
bool PartPlateList::load_next_bedtype_texture()
{
if (PartPlateList::is_load_bedtype_textures)
return false;
if (m_next_bedtype_texture == 0)
init_bed_type_info();
if (load_next_part_texture(bed_texture_info, btCount, m_next_bedtype_texture, true))
return true;
PartPlateList::is_load_bedtype_textures = true;
return false;
}
bool PartPlateList::load_logo_texture()
{
if (m_logo_texture_filename.empty()) {
m_logo_texture.reset();
return false;
}
if (m_logo_texture.get_id() != 0 && m_logo_texture.get_source() == m_logo_texture_filename) {
if (m_logo_texture.unsent_compressed_data_available())
// sends to gpu the already available compressed levels of the main texture
m_logo_texture.send_compressed_data_to_gpu();
return true;
}
m_logo_texture.reset();
// starts generating the main texture, compression will run asynchronously
if (boost::algorithm::iends_with(m_logo_texture_filename, ".svg")) {
if (!m_logo_texture.load_from_svg_file(m_logo_texture_filename, true, true, true, logo_texture_size())) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % m_logo_texture_filename;
return false;
}
}
else if (boost::algorithm::iends_with(m_logo_texture_filename, ".png")) {
if (!m_logo_texture.load_from_file(m_logo_texture_filename, true, GLTexture::MultiThreaded, true)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % m_logo_texture_filename;
return false;
}
}
else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": can not load logo texture from %1%, unsupported format") % m_logo_texture_filename;
return false;
}
return true;
}
void PartPlateList::load_icon_textures()
{
if (!icon_textures_loaded())
generate_icon_textures();
}
bool PartPlateList::load_next_plate_texture()
{
if (!render_bedtype_logo) {
load_logo_texture();
return false;
}
return load_next_bedtype_texture() || load_next_cali_texture() || load_next_extruder_only_area_texture();
}
void PartPlateList::load_extruder_only_area_textures()
{
while (load_next_extruder_only_area_texture()) {}
}
bool PartPlateList::load_next_extruder_only_area_texture()
{
if (PartPlateList::is_load_extruder_only_area_textures)
return false;
if (m_next_extruder_only_area_texture == 0 && !init_extruder_only_area_info()) {
PartPlateList::is_load_extruder_only_area_textures = true;
return;
}
GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size();
GLint logo_tex_size = (max_tex_size < 2048) ? max_tex_size : 2048;
for (int i = 0; i < (unsigned int) ExtruderOnlyAreaType::btAreaCount; ++i) {
for (int j = 0; j < extruder_only_area_info[i].parts.size(); j++) {
std::string filename = resources_dir() + "/images/" + extruder_only_area_info[i].parts[j].filename;
if (boost::filesystem::exists(filename)) {
PartPlateList::extruder_only_area_info[i].parts[j].texture = new GLTexture();
if (!PartPlateList::extruder_only_area_info[i].parts[j].texture->load_from_svg_file(filename, true, false, false, logo_tex_size)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % filename;
}
} else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load logo texture from %1% failed!") % filename;
}
}
return false;
}
if (load_next_part_texture(extruder_only_area_info, (size_t) ExtruderOnlyAreaType::btAreaCount, m_next_extruder_only_area_texture, false))
return true;
PartPlateList::is_load_extruder_only_area_textures = true;
return false;
}
void PartPlateList::init_cali_texture_info()
@@ -7125,26 +7243,19 @@ void PartPlateList::init_cali_texture_info()
void PartPlateList::load_cali_textures()
{
if (PartPlateList::is_load_cali_texture) return;
while (load_next_cali_texture()) {}
}
init_cali_texture_info();
GLint max_tex_size = OpenGLManager::get_gl_info().get_max_tex_size();
GLint logo_tex_size = (max_tex_size < 2048) ? max_tex_size : 2048;
for (int i = 0; i < (unsigned int)btCount; ++i) {
for (int j = 0; j < cali_texture_info.parts.size(); j++) {
std::string filename = resources_dir() + "/images/" + cali_texture_info.parts[j].filename;
if (boost::filesystem::exists(filename)) {
PartPlateList::cali_texture_info.parts[j].texture = new GLTexture();
if (!PartPlateList::cali_texture_info.parts[j].texture->load_from_svg_file(filename, true, true, true, logo_tex_size)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load cali texture from %1% failed!") % filename;
}
}
else {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": load cali texture from %1% failed!") % filename;
}
}
}
bool PartPlateList::load_next_cali_texture()
{
if (PartPlateList::is_load_cali_texture)
return false;
if (m_next_cali_texture == 0)
init_cali_texture_info();
if (load_next_part_texture(&cali_texture_info, 1, m_next_cali_texture, true))
return true;
PartPlateList::is_load_cali_texture = true;
return false;
}
void PartPlateList::on_extruder_count_changed(int extruder_count)