Multiple beds (part 4): Thumbnails (buttons, G-codes)

This commit is contained in:
Lukas Matena 2024-05-13 13:40:53 +02:00
parent e88c625567
commit 9035caa337
5 changed files with 86 additions and 11 deletions

View File

@ -110,10 +110,27 @@ void MultipleBeds::move_active_to_first_bed(Model& model, const BuildVolume& bui
}
bool MultipleBeds::is_instance_on_active_bed(ObjectID id) const
{
auto it = m_inst_to_bed.find(id);
return (it != m_inst_to_bed.end() && it->second == m_active_bed);
}
bool MultipleBeds::is_glvolume_on_thumbnail_bed(const Model& model, int obj_idx, int instance_idx) const
{
if (obj_idx < 0 || instance_idx < 0 || obj_idx >= int(model.objects.size()) || instance_idx >= int(model.objects[obj_idx]->instances.size()))
return false;
auto it = m_inst_to_bed.find(model.objects[obj_idx]->instances[instance_idx]->id());
if (it == m_inst_to_bed.end())
return false;
return (m_bed_for_thumbnails_generation < 0 || it->second == m_bed_for_thumbnails_generation);
}
}

View File

@ -11,6 +11,7 @@ namespace Slic3r {
class Model;
class BuildVolume;
class PrintBase;
extern bool s_reload_preview_after_switching_beds;
@ -27,12 +28,17 @@ public:
int get_number_of_beds() const { return m_number_of_beds; }
bool should_show_next_bed() const { return m_show_next_bed; }
void request_next_bed(bool show);
int get_active_bed() const { return m_active_bed; }
void set_active_bed(int i);
void move_active_to_first_bed(Model& model, const BuildVolume& build_volume, bool to_or_from) const;
void set_thumbnail_bed_idx(int bed_idx) { m_bed_for_thumbnails_generation = bed_idx; }
int get_thumbnail_bed_idx() const { return m_bed_for_thumbnails_generation; }
bool is_glvolume_on_thumbnail_bed(const Model& model, int obj_idx, int instance_idx) const;
private:
@ -42,8 +48,10 @@ private:
int m_number_of_beds = 1;
int m_active_bed = 0;
int m_bed_for_thumbnails_generation = -1;
bool m_show_next_bed = false;
std::map<ObjectID, int> m_inst_to_bed;
std::map<PrintBase*, size_t> m_printbase_to_texture;
};

View File

@ -108,12 +108,15 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c
void Bed3D::render(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, float scale_factor, bool show_texture)
{
bool is_thumbnail = s_multiple_beds.get_thumbnail_bed_idx() != -1;
bool is_preview = wxGetApp().plater()->is_preview_shown();
int bed_to_highlight = -1;
static std::vector<int> beds_to_render;
beds_to_render.clear();
if (is_preview)
if (is_thumbnail)
beds_to_render.push_back(s_multiple_beds.get_thumbnail_bed_idx());
else if (is_preview)
beds_to_render.push_back(s_multiple_beds.get_active_bed());
else {
beds_to_render.resize(s_multiple_beds.get_number_of_beds() + int(s_multiple_beds.should_show_next_bed()));

View File

@ -85,6 +85,8 @@
#include <imgui/imgui_internal.h>
#include <slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp>
extern std::vector<GLuint> s_th_tex_id;
static constexpr const float TRACKBALLSIZE = 0.8f;
static const Slic3r::ColorRGBA DEFAULT_BG_DARK_COLOR = { 0.478f, 0.478f, 0.478f, 1.0f };
@ -1833,14 +1835,12 @@ void GLCanvas3D::render()
{
if (s_multiple_beds.get_number_of_beds() != 1) {
ImGui::SetNextWindowPos(ImVec2(10,10));
ImGui::SetNextWindowSize(ImVec2(120., 150.));
ImGui::Begin("Bed selector", 0, ImGuiWindowFlags_NoResize);
for (int i = 0; i < s_multiple_beds.get_number_of_beds(); ++i) {
bool inactive = i != s_multiple_beds.get_active_bed();
if (inactive)
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0., 0., 0., .5));
if (ImGui::Button((std::string("Bed number ") + std::to_string(i + 1)).c_str())) {
if (ImGui::ImageButton((void*)s_th_tex_id[i], ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0))) {
int old_bed = s_multiple_beds.get_active_bed();
s_multiple_beds.set_active_bed(i);
if (wxGetApp().plater()->is_preview_shown()) {
@ -4658,8 +4658,10 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
for (GLVolume* vol : volumes.volumes) {
if (!vol->is_modifier && !vol->is_wipe_tower && (!thumbnail_params.parts_only || vol->composite_id.volume_id >= 0)) {
if (!thumbnail_params.printable_only || is_visible(*vol))
visible_volumes.emplace_back(vol);
if (!thumbnail_params.printable_only || is_visible(*vol)) {
if (s_multiple_beds.is_glvolume_on_thumbnail_bed(wxGetApp().model(), vol->composite_id.object_id, vol->composite_id.instance_id))
visible_volumes.emplace_back(vol);
}
}
}
@ -4689,7 +4691,13 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
// extends the near and far z of the frustrum to avoid the bed being clipped
// box in eye space
const BoundingBoxf3 t_bed_box = m_bed.extended_bounding_box().transformed(view_matrix);
BoundingBoxf3 t_bed_box = m_bed.extended_bounding_box();
if (s_multiple_beds.get_thumbnail_bed_idx() != -1) {
BoundingBoxf3 bed_bb = m_bed.build_volume().bounding_volume();
bed_bb.translate(s_multiple_beds.get_bed_translation(s_multiple_beds.get_thumbnail_bed_idx()));
t_bed_box.merge(bed_bb);
}
t_bed_box = t_bed_box.transformed(view_matrix);
near_z = -t_bed_box.max.z();
far_z = -t_bed_box.min.z();
}

View File

@ -144,6 +144,8 @@
#include "Widgets/CheckBox.hpp"
#include "GL/glew.h"
using boost::optional;
namespace fs = boost::filesystem;
using Slic3r::_3DScene;
@ -153,6 +155,8 @@ using Slic3r::GUI::format_wxstr;
static const std::pair<unsigned int, unsigned int> THUMBNAIL_SIZE_3MF = { 256, 256 };
std::vector<GLuint> s_th_tex_id;
namespace Slic3r {
namespace GUI {
@ -2116,10 +2120,6 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
background_process.select_technology(this->printer_technology);
// bitmap of enum UpdateBackgroundProcessReturnState
unsigned int return_state = 0;
@ -2171,6 +2171,43 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// Move all instances back to their respective beds.
s_multiple_beds.move_active_to_first_bed(q->model(), q->build_volume(), false);
// If current bed was invalidated, update thumbnails for all beds:
if (int num = s_multiple_beds.get_number_of_beds(); num > 1 && ! (invalidated & Print::ApplyStatus::APPLY_STATUS_UNCHANGED)) {
ThumbnailData data;
ThumbnailsParams params;
params.parts_only = true;
params.printable_only = true;
params.show_bed = true;
params.transparent_background = false;
int w = 100, h = 100;
int curr_bound_texture = 0;
glsafe(glGetIntegerv(GL_TEXTURE_BINDING_2D, &curr_bound_texture));
int curr_unpack_alignment = 0;
glsafe(glGetIntegerv(GL_UNPACK_ALIGNMENT, &curr_unpack_alignment));
glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(glDeleteTextures(s_th_tex_id.size(), s_th_tex_id.data()));
s_th_tex_id.resize(num);
glsafe(glGenTextures(num, s_th_tex_id.data()));
for (int i = 0; i < num; ++i) {
s_multiple_beds.set_thumbnail_bed_idx(i);
generate_thumbnail(data, w, h, params, GUI::Camera::EType::Ortho);
s_multiple_beds.set_thumbnail_bed_idx(-1);
glsafe(glBindTexture(GL_TEXTURE_2D, s_th_tex_id[i]));
glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
glsafe(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
glsafe(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, static_cast<GLsizei>(w), static_cast<GLsizei>(h), 0, GL_RGBA, GL_UNSIGNED_BYTE, data.pixels.data()));
}
glsafe(glBindTexture(GL_TEXTURE_2D, curr_bound_texture));
glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, curr_unpack_alignment));
}
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.
if (view3D->is_layers_editing_enabled())
view3D->get_wxglcanvas()->Refresh();
@ -3330,6 +3367,8 @@ void Plater::priv::generate_thumbnail(ThumbnailData& data, unsigned int w, unsig
ThumbnailsList Plater::priv::generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type)
{
s_multiple_beds.set_thumbnail_bed_idx(s_multiple_beds.get_active_bed());
ScopeGuard guard([]() { s_multiple_beds.set_thumbnail_bed_idx(-1); });
ThumbnailsList thumbnails;
for (const Vec2d& size : params.sizes) {
thumbnails.push_back(ThumbnailData());