Multiple beds (part 2):

- Vectorizing Print, SLAPrint and GCodeProcessorResult
- Connect multiple beds to background slicing process
- TODO: A lot of code (notifications, etc.) commented-out.
This commit is contained in:
Lukas Matena 2024-10-01 15:59:27 +02:00
parent accc4ce266
commit 7da3ce6961
11 changed files with 94 additions and 61 deletions

View File

@ -129,6 +129,8 @@ bool BackgroundSlicingProcess::select_technology(PrinterTechnology tech)
}
changed = true;
}
if (tech == ptFFF)
m_print = m_fff_print;
assert(m_print != nullptr);
return changed;
}

View File

@ -87,8 +87,8 @@ public:
// Stop the background processing and finalize the bacgkround processing thread, remove temp files.
~BackgroundSlicingProcess();
void set_fff_print(Print *print) { m_fff_print = print; }
void set_sla_print(SLAPrint *print) { m_sla_print = print; }
void set_fff_print(Print* print) { if (m_fff_print != print) stop(); m_fff_print = print; }
void set_sla_print(SLAPrint *print) { if (m_sla_print != print) stop(); m_sla_print = print; }
void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
void set_gcode_result(GCodeProcessorResult* result) { m_gcode_result = result; }

View File

@ -41,6 +41,7 @@
#include "libslic3r/Print.hpp"
#include "libslic3r/SLAPrint.hpp"
#include "NotificationManager.hpp"
#include "libslic3r/MultipleBeds.hpp"
#ifdef _WIN32
#include "BitmapComboBox.hpp"
@ -184,10 +185,10 @@ void View3D::render()
Preview::Preview(
wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config,
BackgroundSlicingProcess* process, GCodeProcessorResult* gcode_result, std::function<void()> schedule_background_process_func)
BackgroundSlicingProcess* process, std::vector<GCodeProcessorResult>* gcode_results, std::function<void()> schedule_background_process_func)
: m_config(config)
, m_process(process)
, m_gcode_result(gcode_result)
, m_gcode_results(gcode_results)
, m_schedule_background_process(schedule_background_process_func)
{
if (init(parent, bed, model))
@ -200,6 +201,11 @@ void Preview::set_layers_slider_values_range(int bottom, int top)
std::max(bottom, m_layers_slider->GetMinPos()));
}
GCodeProcessorResult* Preview::active_gcode_result()
{
return &(*m_gcode_results)[s_multiple_beds.get_active_bed()];
}
bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model)
{
if (!Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 /* disable wxTAB_TRAVERSAL */))
@ -437,7 +443,7 @@ void Preview::create_sliders()
});
m_layers_slider->set_callback_on_get_print([]() -> const Print& {
return GUI::wxGetApp().plater()->fff_print();
return GUI::wxGetApp().plater()->active_fff_print();
});
m_layers_slider->set_callback_on_get_custom_code([](const std::string& code_in, double height) -> std::string
@ -612,12 +618,12 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
ticks_info_from_model = plater->model().custom_gcode_per_print_z;
else {
ticks_info_from_model.mode = CustomGCode::Mode::SingleExtruder;
ticks_info_from_model.gcodes = m_gcode_result->custom_gcode_per_print_z;
ticks_info_from_model.gcodes = active_gcode_result()->custom_gcode_per_print_z;
}
check_layers_slider_values(ticks_info_from_model.gcodes, layers_z);
//first of all update extruder colors to avoid crash, when we are switching printer preset from MM to SM
m_layers_slider->SetExtruderColors(plater->get_extruder_color_strings_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result));
m_layers_slider->SetExtruderColors(plater->get_extruder_color_strings_from_plater_config(wxGetApp().is_editor() ? nullptr : active_gcode_result()));
m_layers_slider->SetSliderValues(layers_z);
m_layers_slider->force_ruler_update();
assert(m_layers_slider->GetMinPos() == 0);
@ -647,9 +653,9 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
bool sequential_print = wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_bool("complete_objects");
m_layers_slider->SetDrawMode(sla_print_technology, sequential_print);
if (sla_print_technology)
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times_running_total);
m_layers_slider->SetLayersTimes(plater->active_sla_print().print_statistics().layers_times_running_total);
else
m_layers_slider->SetLayersTimes(m_canvas->get_gcode_layers_times_cache(), m_gcode_result->print_statistics.modes.front().time);
m_layers_slider->SetLayersTimes(m_canvas->get_gcode_layers_times_cache(), active_gcode_result()->print_statistics.modes.front().time);
m_layers_slider->Thaw();
@ -664,7 +670,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
auto get_print_obj_idxs = [plater]() ->std::string {
if (plater->printer_technology() == ptSLA)
return "sla";
const Print& print = GUI::wxGetApp().plater()->fff_print();
const Print& print = GUI::wxGetApp().plater()->active_fff_print();
std::string idxs;
for (auto object : print.objects())
idxs += std::to_string(object->id().id) + "_";
@ -676,7 +682,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
wxGetApp().app_config->get_bool("allow_auto_color_change") &&
m_layers_slider->is_new_print(get_print_obj_idxs()))
{
const Print& print = wxGetApp().plater()->fff_print();
const Print& print = wxGetApp().plater()->active_fff_print();
//bool is_possible_auto_color_change = false;
for (auto object : print.objects()) {
@ -841,7 +847,7 @@ void Preview::update_sliders_from_canvas(wxKeyEvent& event)
void Preview::update_moves_slider(std::optional<int> visible_range_min, std::optional<int> visible_range_max)
{
if (m_gcode_result->moves.empty())
if (active_gcode_result()->moves.empty())
return;
const libvgcode::Interval& range = m_canvas->get_gcode_view_enabled_range();
@ -945,15 +951,15 @@ void Preview::load_print_as_fff(bool keep_z_range)
}
libvgcode::EViewType gcode_view_type = m_canvas->get_gcode_view_type();
const bool gcode_preview_data_valid = !m_gcode_result->moves.empty();
const bool gcode_preview_data_valid = !active_gcode_result()->moves.empty();
const bool is_pregcode_preview = !gcode_preview_data_valid && wxGetApp().is_editor();
const std::vector<std::string> tool_colors = wxGetApp().plater()->get_extruder_color_strings_from_plater_config(m_gcode_result);
const std::vector<std::string> tool_colors = wxGetApp().plater()->get_extruder_color_strings_from_plater_config(active_gcode_result());
const std::vector<CustomGCode::Item>& color_print_values = wxGetApp().is_editor() ?
wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_gcode_result->custom_gcode_per_print_z;
wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : active_gcode_result()->custom_gcode_per_print_z;
std::vector<std::string> color_print_colors;
if (!color_print_values.empty()) {
color_print_colors = wxGetApp().plater()->get_color_strings_for_color_print(m_gcode_result);
color_print_colors = wxGetApp().plater()->get_color_strings_for_color_print(active_gcode_result());
color_print_colors.push_back("#808080"); // gray color for pause print or custom G-code
}
@ -963,7 +969,7 @@ void Preview::load_print_as_fff(bool keep_z_range)
m_canvas->set_selected_extruder(0);
if (gcode_preview_data_valid) {
// Load the real G-code preview.
m_canvas->load_gcode_preview(*m_gcode_result, tool_colors, color_print_colors);
m_canvas->load_gcode_preview(*active_gcode_result(), tool_colors, color_print_colors);
// the view type may have been changed by the call m_canvas->load_gcode_preview()
gcode_view_type = m_canvas->get_gcode_view_type();
zs = m_canvas->get_gcode_layers_zs();

View File

@ -86,7 +86,9 @@ class Preview : public wxPanel
DynamicPrintConfig* m_config;
BackgroundSlicingProcess* m_process;
GCodeProcessorResult* m_gcode_result;
std::vector<GCodeProcessorResult>* m_gcode_results;
GCodeProcessorResult* active_gcode_result();
// Calling this function object forces Plater::schedule_background_process.
std::function<void()> m_schedule_background_process;
@ -117,7 +119,7 @@ public:
};
Preview(wxWindow* parent, Bed3D& bed, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process,
GCodeProcessorResult* gcode_result, std::function<void()> schedule_background_process = []() {});
std::vector<GCodeProcessorResult>* gcode_results, std::function<void()> schedule_background_process = []() {});
virtual ~Preview();
wxGLCanvas* get_wxglcanvas() { return m_canvas_widget; }

View File

@ -519,7 +519,7 @@ bool GLGizmoFdmSupports::has_backend_supports()
void GLGizmoFdmSupports::auto_generate()
{
std::string err = wxGetApp().plater()->fff_print().validate();
std::string err = wxGetApp().plater()->active_fff_print().validate();
if (!err.empty()) {
MessageDialog dlg(GUI::wxGetApp().plater(), _L("Automatic painting requires valid print setup.") + " \n" + from_u8(err), _L("Warning"), wxOK);
dlg.ShowModal();

View File

@ -194,9 +194,9 @@ arr2::SceneBuilder build_scene(Plater &plater, ArrangeSelectionMode mode)
builder.set_model(plater.model());
if (plater.printer_technology() == ptSLA)
builder.set_sla_print(&plater.sla_print());
builder.set_sla_print(&plater.active_sla_print());
else
builder.set_fff_print(&plater.fff_print());
builder.set_fff_print(&plater.active_fff_print());
return builder;
}

View File

@ -95,7 +95,7 @@ void SLAImportJob::reset()
{
p->sel = Sel::modelAndProfile;
p->mesh = {};
p->profile = p->plater->sla_print().full_print_config();
p->profile = p->plater->active_sla_print().full_print_config();
p->quality = SLAImportQuality::Balanced;
p->path.Clear();
p->err = "";
@ -142,7 +142,7 @@ void SLAImportJob::finalize(bool canceled, std::exception_ptr &eptr)
if (p->sel != Sel::modelOnly) {
if (p->profile.empty())
p->profile = p->plater->sla_print().full_print_config();
p->profile = p->plater->active_sla_print().full_print_config();
const ModelObjectPtrs& objects = p->plater->model().objects;
for (auto object : objects)

View File

@ -1082,7 +1082,7 @@ bool MainFrame::can_export_supports() const
return false;
bool can_export = false;
const PrintObjects& objects = m_plater->sla_print().objects();
const PrintObjects& objects = m_plater->active_sla_print().objects();
for (const SLAPrintObject* object : objects)
{
if (!object->support_mesh().empty() || !object->pad_mesh().empty())

View File

@ -241,6 +241,7 @@ enum ExportingStatus{
EXPORTING_TO_LOCAL
};
// Plater / private
struct Plater::priv
{
@ -252,11 +253,11 @@ struct Plater::priv
// Data
Slic3r::DynamicPrintConfig *config; // FIXME: leak?
Slic3r::Print fff_print;
Slic3r::SLAPrint sla_print;
std::vector<std::unique_ptr<Slic3r::Print>> fff_prints;
std::vector<std::unique_ptr<Slic3r::SLAPrint>> sla_prints;
Slic3r::Model model;
PrinterTechnology printer_technology = ptFFF;
Slic3r::GCodeProcessorResult gcode_result;
std::vector<Slic3r::GCodeProcessorResult> gcode_results;
// GUI elements
wxSizer* panel_sizer{ nullptr };
@ -634,9 +635,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
, collapse_toolbar(GLToolbar::Normal, "Collapse")
, m_project_filename(wxEmptyString)
{
background_process.set_fff_print(&fff_print);
background_process.set_sla_print(&sla_print);
background_process.set_gcode_result(&gcode_result);
for (int i = 0; i < s_multiple_beds.get_max_beds(); ++i) {
gcode_results.emplace_back();
fff_prints.emplace_back(std::make_unique<Print>());
sla_prints.emplace_back(std::make_unique<SLAPrint>());
}
background_process.set_fff_print(fff_prints.front().get());
background_process.set_sla_print(sla_prints.front().get());
background_process.set_gcode_result(&gcode_results.front());
background_process.set_thumbnail_cb([this](const ThumbnailsParams& params) { return this->generate_thumbnails(params, Camera::EType::Ortho); });
background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED);
background_process.set_finished_event(EVT_PROCESS_COMPLETED);
@ -648,12 +654,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
auto statuscb = [this](const Slic3r::PrintBase::SlicingStatus &status) {
wxQueueEvent(this->q, new Slic3r::SlicingStatusEvent(EVT_SLICING_UPDATE, 0, status));
};
fff_print.set_status_callback(statuscb);
sla_print.set_status_callback(statuscb);
std::for_each(fff_prints.begin(), fff_prints.end(), [statuscb](std::unique_ptr<Print>& p) { p->set_status_callback(statuscb); });
std::for_each(sla_prints.begin(), sla_prints.end(), [statuscb](std::unique_ptr<SLAPrint>& p) { p->set_status_callback(statuscb); });
this->q->Bind(EVT_SLICING_UPDATE, &priv::on_slicing_update, this);
view3D = new View3D(q, bed, &model, config, &background_process);
preview = new Preview(q, bed, &model, config, &background_process, &gcode_result, [this]() { schedule_background_process(); });
preview = new Preview(q, bed, &model, config, &background_process, &gcode_results, [this]() { schedule_background_process(); });
// set default view_toolbar icons size equal to GLGizmosManager::Default_Icons_Size
view_toolbar.set_icons_size(GLGizmosManager::Default_Icons_Size);
@ -1922,7 +1928,7 @@ void Plater::priv::delete_all_objects_from_model()
view3D->enable_layers_editing(false);
reset_gcode_toolpaths();
gcode_result.reset();
std::for_each(gcode_results.begin(), gcode_results.end(), [](auto& g) { g.reset(); });
view3D->get_canvas3d()->reset_sequential_print_clearance();
view3D->get_canvas3d()->reset_all_gizmos();
@ -1955,7 +1961,7 @@ void Plater::priv::reset()
view3D->enable_layers_editing(false);
reset_gcode_toolpaths();
gcode_result.reset();
std::for_each(gcode_results.begin(), gcode_results.end(), [](auto& g) { g.reset(); });
view3D->get_canvas3d()->reset_sequential_print_clearance();
@ -2103,6 +2109,17 @@ void Plater::priv::process_validation_warning(const std::vector<std::string>& wa
// Returns a bitmask of UpdateBackgroundProcessReturnState.
unsigned int Plater::priv::update_background_process(bool force_validation, bool postpone_error_messages)
{
int active_bed = s_multiple_beds.get_active_bed();
background_process.set_fff_print(fff_prints[active_bed].get());
background_process.set_sla_print(sla_prints[active_bed].get());
background_process.set_gcode_result(&gcode_results[active_bed]);
background_process.select_technology(this->printer_technology);
// bitmap of enum UpdateBackgroundProcessReturnState
unsigned int return_state = 0;
@ -2307,7 +2324,9 @@ bool Plater::priv::restart_background_process(unsigned int state)
( ((state & UPDATE_BACKGROUND_PROCESS_FORCE_RESTART) != 0 && ! this->background_process.finished()) ||
(state & UPDATE_BACKGROUND_PROCESS_FORCE_EXPORT) != 0 ||
(state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ) ) {
// The print is valid and it can be started.
if (this->background_process.start()) {
if (!show_warning_dialog)
on_slicing_began();
@ -2981,17 +3000,17 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
int warning_step = evt.status.warning_step;
PrintStateBase::StateWithWarnings state;
if (evt.status.flags & PrintBase::SlicingStatus::UPDATE_PRINT_STEP_WARNINGS) {
state = this->printer_technology == ptFFF ?
this->fff_print.step_state_with_warnings(static_cast<PrintStep>(warning_step)) :
this->sla_print.step_state_with_warnings(static_cast<SLAPrintStep>(warning_step));
// LUKAS state = this->printer_technology == ptFFF ?
//this->fff_print.step_state_with_warnings(static_cast<PrintStep>(warning_step)) :
//this->sla_print.step_state_with_warnings(static_cast<SLAPrintStep>(warning_step));
} else if (this->printer_technology == ptFFF) {
const PrintObject *print_object = this->fff_print.get_object(object_id);
if (print_object)
state = print_object->step_state_with_warnings(static_cast<PrintObjectStep>(warning_step));
//LUKAS const PrintObject *print_object = this->fff_print.get_object(object_id);
//if (print_object)
// state = print_object->step_state_with_warnings(static_cast<PrintObjectStep>(warning_step));
} else {
const SLAPrintObject *print_object = this->sla_print.get_object(object_id);
if (print_object)
state = print_object->step_state_with_warnings(static_cast<SLAPrintObjectStep>(warning_step));
// LUKAS const SLAPrintObject *print_object = this->sla_print.get_object(object_id);
// if (print_object)
// state = print_object->step_state_with_warnings(static_cast<SLAPrintObjectStep>(warning_step));
}
// Now process state.warnings.
for (auto const& warning : state.warnings) {
@ -4042,10 +4061,6 @@ void Plater::render_project_state_debug_window() const { p->render_project_state
Sidebar& Plater::sidebar() { return *p->sidebar; }
const Model& Plater::model() const { return p->model; }
Model& Plater::model() { return p->model; }
const Print& Plater::fff_print() const { return p->fff_print; }
Print& Plater::fff_print() { return p->fff_print; }
const SLAPrint& Plater::sla_print() const { return p->sla_print; }
SLAPrint& Plater::sla_print() { return p->sla_print; }
bool Plater::is_project_temp() const
{
@ -4193,7 +4208,7 @@ void Plater::load_gcode(const wxString& filename)
m_last_loaded_gcode = filename;
// cleanup view before to start loading/processing
p->gcode_result.reset();
std::for_each(p->gcode_results.begin(), p->gcode_results.end(), [](auto& g) { g.reset(); });
reset_gcode_toolpaths();
p->preview->reload_print();
p->get_current_canvas3D()->render();
@ -4215,7 +4230,7 @@ void Plater::load_gcode(const wxString& filename)
show_error(this, ex.what());
return;
}
p->gcode_result = std::move(processor.extract_result());
p->gcode_results.front() = std::move(processor.extract_result());
// show results
try
@ -4225,7 +4240,7 @@ void Plater::load_gcode(const wxString& filename)
catch (const std::exception&)
{
wxEndBusyCursor();
p->gcode_result.reset();
p->gcode_results.front().reset();
reset_gcode_toolpaths();
set_default_bed_shape();
p->preview->reload_print();
@ -5531,7 +5546,7 @@ void Plater::export_gcode(bool prefer_removable)
start_dir,
from_path(default_output_file.filename()),
printer_technology() == ptFFF ? GUI::file_wildcards(FT_GCODE, ext) :
GUI::sla_wildcards(p->sla_print.printer_config().sla_archive_format.value.c_str(), ext),
GUI::sla_wildcards(p->sla_prints.front()->printer_config().sla_archive_format.value.c_str(), ext),
wxFD_SAVE | wxFD_OVERWRITE_PROMPT
);
if (dlg.ShowModal() == wxID_OK) {
@ -5648,7 +5663,7 @@ void Plater::export_stl_obj(bool extended, bool selection_only)
auto mesh_to_export_sla = [&, this](const ModelObject& mo, int instance_id) {
TriangleMesh mesh;
const SLAPrintObject *object = this->p->sla_print.get_print_object_by_model_object_id(mo.id());
const SLAPrintObject *object; // LUKAS = this->p->sla_print.get_print_object_by_model_object_id(mo.id());
if (!object || !object->get_mesh_to_print() || object->get_mesh_to_print()->empty()) {
if (!extended)
@ -7180,6 +7195,11 @@ wxMenu* Plater::instance_menu() { return p->menus.instance_menu();
wxMenu* Plater::layer_menu() { return p->menus.layer_menu(); }
wxMenu* Plater::multi_selection_menu() { return p->menus.multi_selection_menu(); }
Print& Plater::active_fff_print() { return *p->fff_prints[s_multiple_beds.get_active_bed()]; }
SLAPrint& Plater::active_sla_print() { return *p->sla_prints[s_multiple_beds.get_active_bed()]; }
SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() :
m_was_scheduled(wxGetApp().plater()->is_background_process_update_scheduled())
{
@ -7196,7 +7216,7 @@ PlaterAfterLoadAutoArrange::PlaterAfterLoadAutoArrange()
Plater* plater = wxGetApp().plater();
m_enabled = plater->model().objects.empty() &&
plater->printer_technology() == ptFFF &&
is_XL_printer(plater->fff_print().config());
is_XL_printer(plater->active_fff_print().config());
}
PlaterAfterLoadAutoArrange::~PlaterAfterLoadAutoArrange()

View File

@ -92,10 +92,13 @@ public:
Sidebar& sidebar();
const Model& model() const;
Model& model();
const Print& fff_print() const;
Print& fff_print();
const SLAPrint& sla_print() const;
SLAPrint& sla_print();
//const Print& fff_print() const;
//Print& fff_print();
//const SLAPrint& sla_print() const;
//SLAPrint& sla_print();
Print& active_fff_print();
SLAPrint& active_sla_print();
void new_project();
void load_project();

View File

@ -921,7 +921,7 @@ void Sidebar::update_sliced_info_sizer()
{
if (m_plater->printer_technology() == ptSLA)
{
const SLAPrintStatistics& ps = m_plater->sla_print().print_statistics();
const SLAPrintStatistics& ps = m_plater->active_sla_print().print_statistics();
wxString new_label = _L("Used Material (ml)") + ":";
const bool is_supports = ps.support_used_material > 0.0;
if (is_supports)
@ -965,7 +965,7 @@ void Sidebar::update_sliced_info_sizer()
}
else
{
const PrintStatistics& ps = m_plater->fff_print().print_statistics();
const PrintStatistics& ps = m_plater->active_fff_print().print_statistics();
const bool is_wipe_tower = ps.total_wipe_tower_filament > 0;
bool imperial_units = wxGetApp().app_config->get_bool("use_inches");