Disable SLA autoslicing page

- Also set instances to unprintable for SLA instead
  of removing them from the model
This commit is contained in:
Martin Šach 2024-12-09 17:58:09 +01:00 committed by Lukas Matena
parent 29da9fcfff
commit 37f5bfc2cd
7 changed files with 163 additions and 75 deletions

View File

@ -208,7 +208,7 @@ void restore_object_instances(Model& model, const ObjectInstances &object_instan
model.objects = objects;
}
void with_single_bed_model(Model &model, const int bed_index, const std::function<void()> &callable) {
void with_single_bed_model_fff(Model &model, const int bed_index, const std::function<void()> &callable) {
const InstanceOffsets original_offssets{MultipleBedsUtils::get_instance_offsets(model)};
const ObjectInstances original_objects{get_object_instances(model)};
const int original_bed{s_multiple_beds.get_active_bed()};
@ -224,6 +224,44 @@ void with_single_bed_model(Model &model, const int bed_index, const std::functio
callable();
}
using InstancesPrintability = std::vector<bool>;
InstancesPrintability get_instances_printability(const Model &model) {
InstancesPrintability result;
for (ModelObject* mo : model.objects) {
for (ModelInstance* mi : mo->instances) {
result.emplace_back(mi->printable);
}
}
return result;
}
void restore_instances_printability(Model& model, const InstancesPrintability &printability)
{
size_t i = 0;
for (ModelObject* mo : model.objects) {
for (ModelInstance* mi : mo->instances) {
mi->printable = printability[i++];
}
}
}
void with_single_bed_model_sla(Model &model, const int bed_index, const std::function<void()> &callable) {
const InstanceOffsets original_offssets{get_instance_offsets(model)};
const InstancesPrintability original_printability{get_instances_printability(model)};
const int original_bed{s_multiple_beds.get_active_bed()};
Slic3r::ScopeGuard guard([&]() {
restore_instance_offsets(model, original_offssets);
restore_instances_printability(model, original_printability);
s_multiple_beds.set_active_bed(original_bed);
});
s_multiple_beds.move_from_bed_to_first_bed(model, bed_index);
s_multiple_beds.set_instances_outside_outside_bed_unprintable(model, bed_index);
s_multiple_beds.set_active_bed(bed_index);
callable();
}
}
bool MultipleBeds::is_instance_on_bed(const ObjectID id, const int bed_index) const
@ -252,6 +290,16 @@ void MultipleBeds::remove_instances_outside_outside_bed(Model& model, const int
), model.objects.end());
}
void MultipleBeds::set_instances_outside_outside_bed_unprintable(Model& model, const int bed_index) const {
for (ModelObject* mo : model.objects) {
for (ModelInstance* mi : mo->instances) {
if (!this->is_instance_on_bed(mi->id(), bed_index)) {
mi->printable = false;
}
}
}
}
void MultipleBeds::move_from_bed_to_first_bed(Model& model, const int bed_index) const
{
if (bed_index < 0 || bed_index >= MAX_NUMBER_OF_BEDS) {

View File

@ -51,6 +51,7 @@ public:
void set_active_bed(int i);
void remove_instances_outside_outside_bed(Model& model, const int bed) const;
void set_instances_outside_outside_bed_unprintable(Model& model, const int bed_index) const;
// Sets !printable to all instances outside the active bed.
void move_from_bed_to_first_bed(Model& model, const int bed) const;
@ -113,14 +114,8 @@ ObjectInstances get_object_instances(const Model& model);
void restore_instance_offsets(Model& model, const InstanceOffsets &offsets);
void restore_object_instances(Model& model, const ObjectInstances &object_instances);
/**
For each print apply call do:
- move all instances according to their active bed
- apply
- move all instances back to their respective beds
*/
void with_single_bed_model(Model &model, const int bed_index, const std::function<void()> &callable);
void with_single_bed_model_fff(Model &model, const int bed_index, const std::function<void()> &callable);
void with_single_bed_model_sla(Model &model, const int bed_index, const std::function<void()> &callable);
}
} // namespace Slic3r

View File

@ -6575,9 +6575,9 @@ enum class PrintStatus {
std::string get_status_text(PrintStatus status) {
switch(status) {
case PrintStatus::idle: return "Idle";
case PrintStatus::running: return "Running";
case PrintStatus::finished: return "Finished";
case PrintStatus::idle: return _u8L("Unsliced");
case PrintStatus::running: return _u8L("Slicing...");
case PrintStatus::finished: return _u8L("Sliced");
}
return {};
}
@ -6601,7 +6601,7 @@ bool bed_selector_thumbnail(
const float side,
const float border,
const GLuint texture_id,
const PrintStatus status
const std::optional<PrintStatus> status
) {
ImGuiWindow* window = GImGui->CurrentWindow;
const ImVec2 current_position = GImGui->CurrentWindow->DC.CursorPos;
@ -6615,16 +6615,18 @@ bool bed_selector_thumbnail(
border
)};
const std::string icon{get_status_icon(status)};
if (status) {
const std::string icon{get_status_icon(*status)};
window->DrawList->AddText(
GImGui->Font,
GImGui->FontSize,
state_pos,
ImGui::GetColorU32(ImGuiCol_Text),
icon.c_str(),
icon.c_str() + icon.size()
);
window->DrawList->AddText(
GImGui->Font,
GImGui->FontSize,
state_pos,
ImGui::GetColorU32(ImGuiCol_Text),
icon.c_str(),
icon.c_str() + icon.size()
);
}
return clicked;
}
@ -6673,11 +6675,14 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
bool clicked = false;
PrintStatus print_status{PrintStatus::idle};
if (wxGetApp().plater()->get_fff_prints()[i]->finished()) {
print_status = PrintStatus::finished;
} else if (m_process->fff_print() == wxGetApp().plater()->get_fff_prints()[i].get() && m_process->running()) {
print_status = PrintStatus::running;
std::optional<PrintStatus> print_status;
if (current_printer_technology() == ptFFF) {
print_status = PrintStatus::idle;
if (wxGetApp().plater()->get_fff_prints()[i]->finished()) {
print_status = PrintStatus::finished;
} else if (m_process->fff_print() == wxGetApp().plater()->get_fff_prints()[i].get() && m_process->running()) {
print_status = PrintStatus::running;
}
}
if (!previous_print_status[i] || print_status != previous_print_status[i]) {
@ -6710,9 +6715,12 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
if (empty)
ImGui::PopItemFlag();
const std::string status_text{get_status_text(print_status)};
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", status_text.c_str());
if (print_status) {
const std::string status_text{get_status_text(*print_status)};
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", status_text.c_str());
}
}
};
ImGuiWrapper& imgui = *wxGetApp().imgui();
@ -6736,7 +6744,10 @@ void Slic3r::GUI::GLCanvas3D::_render_bed_selector()
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2());
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, btn_border);
if (slice_all_beds_button(s_multiple_beds.is_autoslicing(), btn_size, btn_padding)) {
if (
current_printer_technology() == ptFFF &&
slice_all_beds_button(s_multiple_beds.is_autoslicing(), btn_size, btn_padding)
) {
if (!s_multiple_beds.is_autoslicing()) {
s_multiple_beds.start_autoslice([this](int i, bool user) { this->select_bed(i, user); });
wxGetApp().sidebar().switch_to_autoslicing_mode();

View File

@ -94,6 +94,7 @@ void GLGizmoSlaBase::update_volumes()
const int object_idx = m_parent.get_selection().get_object_idx();
const int instance_idx = m_parent.get_selection().get_instance_idx();
const Geometry::Transformation& inst_trafo = po->model_object()->instances[instance_idx]->get_transformation();
const double current_elevation = po->get_current_elevation();

View File

@ -563,6 +563,7 @@ struct Plater::priv
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
ThumbnailsList generate_thumbnails(const ThumbnailsParams& params, Camera::EType camera_type);
void regenerate_thumbnails();
void bring_instance_forward() const;
@ -2162,25 +2163,64 @@ void Plater::priv::process_validation_warning(const std::vector<std::string>& wa
}
}
std::array<Print::ApplyStatus, MAX_NUMBER_OF_BEDS> apply_to_inactive_beds(
std::vector<Print::ApplyStatus> apply_to_inactive_beds(
Model &model,
std::vector<std::unique_ptr<Print>> &prints,
const DynamicPrintConfig &config
) {
std::array<Print::ApplyStatus, MAX_NUMBER_OF_BEDS> result;
std::vector<Print::ApplyStatus> result(MAX_NUMBER_OF_BEDS);
for (std::size_t bed_index{0}; bed_index < prints.size(); ++bed_index) {
const std::unique_ptr<Print> &print{prints[bed_index]};
if (!print || bed_index == s_multiple_beds.get_active_bed()) {
continue;
}
using MultipleBedsUtils::with_single_bed_model;
with_single_bed_model(model, bed_index, [&](){
using MultipleBedsUtils::with_single_bed_model_fff;
with_single_bed_model_fff(model, bed_index, [&](){
result[bed_index] = print->apply(model, config);
});
}
return result;
}
void Plater::priv::regenerate_thumbnails() {
const int num{s_multiple_beds.get_number_of_beds()};
if (num <= 1 || num > MAX_NUMBER_OF_BEDS) {
return;
}
ThumbnailData data;
ThumbnailsParams params;
params.parts_only = true;
params.printable_only = true;
params.show_bed = true;
params.transparent_background = true;
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_bed_selector_thumbnail_texture_ids.size(), s_bed_selector_thumbnail_texture_ids.data()));
s_bed_selector_thumbnail_changed.fill(false);
s_bed_selector_thumbnail_texture_ids.resize(num);
glsafe(glGenTextures(num, s_bed_selector_thumbnail_texture_ids.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_bed_selector_thumbnail_texture_ids[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()));
s_bed_selector_thumbnail_changed[i] = true;
}
glsafe(glBindTexture(GL_TEXTURE_2D, curr_bound_texture));
glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, curr_unpack_alignment));
}
// Update background processing thread from the current config and Model.
// Returns a bitmask of UpdateBackgroundProcessReturnState.
unsigned int Plater::priv::update_background_process(bool force_validation, bool postpone_error_messages)
@ -2236,16 +2276,29 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
Print::ApplyStatus invalidated{Print::ApplyStatus::APPLY_STATUS_INVALIDATED};
bool was_running = background_process.running();
using MultipleBedsUtils::with_single_bed_model;
using MultipleBedsUtils::with_single_bed_model_fff;
using MultipleBedsUtils::with_single_bed_model_sla;
std::array<Print::ApplyStatus, MAX_NUMBER_OF_BEDS> apply_statuses{
apply_to_inactive_beds(q->model(), q->p->fff_prints, full_config)
std::vector<Print::ApplyStatus> apply_statuses{
printer_technology == ptFFF ?
apply_to_inactive_beds(q->model(), q->p->fff_prints, full_config) :
std::vector<Print::ApplyStatus>(1)
};
with_single_bed_model(q->model(), s_multiple_beds.get_active_bed(), [&](){
// Apply new config to the possibly running background task.
invalidated = background_process.apply(q->model(), full_config);
apply_statuses[s_multiple_beds.get_active_bed()] = invalidated;
});
// Apply new config to the possibly running background task.
if (printer_technology == ptFFF) {
with_single_bed_model_fff(q->model(), s_multiple_beds.get_active_bed(), [&](){
invalidated = background_process.apply(q->model(), full_config);
apply_statuses[s_multiple_beds.get_active_bed()] = invalidated;
});
} else if (printer_technology == ptSLA) {
with_single_bed_model_sla(q->model(), s_multiple_beds.get_active_bed(), [&](){
invalidated = background_process.apply(q->model(), full_config);
apply_statuses[0] = invalidated;
});
} else {
throw std::runtime_error{"Ivalid printer technology!"};
}
const bool any_status_changed{std::any_of(
apply_statuses.begin(),
@ -2260,38 +2313,8 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
}
// If current bed was invalidated, update thumbnails for all beds:
if (int num = s_multiple_beds.get_number_of_beds(); num > 1 && any_status_changed) {
ThumbnailData data;
ThumbnailsParams params;
params.parts_only = true;
params.printable_only = true;
params.show_bed = true;
params.transparent_background = true;
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_bed_selector_thumbnail_texture_ids.size(), s_bed_selector_thumbnail_texture_ids.data()));
s_bed_selector_thumbnail_changed.fill(false);
s_bed_selector_thumbnail_texture_ids.resize(num);
glsafe(glGenTextures(num, s_bed_selector_thumbnail_texture_ids.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_bed_selector_thumbnail_texture_ids[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()));
s_bed_selector_thumbnail_changed[i] = true;
}
glsafe(glBindTexture(GL_TEXTURE_2D, curr_bound_texture));
glsafe(glPixelStorei(GL_UNPACK_ALIGNMENT, curr_unpack_alignment));
if (any_status_changed) {
regenerate_thumbnails();
}
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.
@ -4685,6 +4708,10 @@ void Plater::object_list_changed()
p->object_list_changed();
}
void Plater::regenerate_thumbnails() {
p->regenerate_thumbnails();
}
std::vector<size_t> Plater::load_files(const std::vector<fs::path>& input_files, bool load_model, bool load_config, bool imperial_units /*= false*/) { return p->load_files(input_files, load_model, load_config, imperial_units); }
// To be called when providing a list of files to the GUI slic3r on command line.

View File

@ -122,6 +122,7 @@ public:
void reload_print();
void object_list_changed();
void generate_thumbnail(ThumbnailData& data, unsigned int w, unsigned int h, const ThumbnailsParams& thumbnail_params, Camera::EType camera_type);
void regenerate_thumbnails();
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);
// To be called when providing a list of files to the GUI slic3r on command line.

View File

@ -32,6 +32,7 @@
#include <wx/statbox.h>
#include <wx/statbmp.h>
#include <wx/wupdlock.h> // IWYU pragma: keep
#include "libslic3r/MultipleBeds.hpp"
#include "wx/generic/stattextg.h"
#ifdef _WIN32
#include <wx/richtooltip.h>
@ -758,6 +759,10 @@ void Sidebar::on_select_preset(wxCommandEvent& evt)
* and for SLA presets they should be deleted
*/
m_object_list->update_object_list_by_printer_technology();
s_multiple_beds.stop_autoslice(false);
this->switch_from_autoslicing_mode();
this->m_plater->regenerate_thumbnails();
this->m_plater->update();
}
#ifdef __WXMSW__