Autoslice (part 1)

This commit is contained in:
Lukas Matena 2024-11-06 09:06:38 +01:00
parent 0bd37e6b08
commit e1be0f041c
6 changed files with 166 additions and 60 deletions

View File

@ -318,6 +318,44 @@ void MultipleBeds::ensure_wipe_towers_on_beds(Model& model, const std::vector<st
}
}
#ifdef SLIC3R_GUI
void MultipleBeds::start_autoslice(std::function<void(int, bool)> select_bed_fn)
{
if (is_autoslicing())
return;
m_select_bed_fn = select_bed_fn;
m_autoslicing_original_bed = get_active_bed();
m_autoslicing = true;
}
void MultipleBeds::stop_autoslice(bool restore_original)
{
if (! is_autoslicing())
return;
m_autoslicing = false;
if (restore_original)
m_select_bed_fn(m_autoslicing_original_bed, false);
}
void MultipleBeds::autoslice_next_bed()
{
if (! is_autoslicing())
return;
int next_bed = s_multiple_beds.get_active_bed() + 1;
if (next_bed >= s_multiple_beds.get_number_of_beds())
next_bed = 0;
m_select_bed_fn(next_bed, false);
}
#endif // SLIC3R_GUI
}

View File

@ -64,6 +64,11 @@ public:
Vec2crd get_bed_gap() const;
void ensure_wipe_towers_on_beds(Model& model, const std::vector<std::unique_ptr<Print>>& prints);
void start_autoslice(std::function<void(int,bool)>);
void stop_autoslice(bool restore_original);
bool is_autoslicing() const { return m_autoslicing; }
void autoslice_next_bed();
private:
bool is_instance_on_active_bed(ObjectID id) const;
@ -78,6 +83,9 @@ private:
bool m_legacy_layout = false;
bool m_loading_project = false;
bool m_autoslicing = false;
int m_autoslicing_original_bed = 0;
std::function<void(int, bool)> m_select_bed_fn;
};
extern MultipleBeds s_multiple_beds;

View File

@ -102,10 +102,10 @@ static bool show_imgui_demo_window = false;
namespace Slic3r {
namespace GUI {
void GLCanvas3D::select_bed(int i)
void GLCanvas3D::select_bed(int i, bool triggered_by_user)
{
int old_bed = s_multiple_beds.get_active_bed();
if (i == old_bed || i == -1)
if ((i == old_bed && !s_multiple_beds.is_autoslicing()) || i == -1)
return;
wxGetApp().plater()->canvas3D()->m_process->stop();
m_sequential_print_clearance.m_evaluating = true;
@ -115,7 +115,7 @@ void GLCanvas3D::select_bed(int i)
// Among else, on_process_completed would be called, which would stop slicing of
// the new bed. We need to stop the process, pump all the events out of the queue
// and then switch the beds.
wxGetApp().CallAfter([i, old_bed]() {
wxGetApp().CallAfter([i, old_bed, triggered_by_user]() {
wxYield();
s_multiple_beds.set_active_bed(i);
s_beds_just_switched = true;
@ -125,6 +125,8 @@ void GLCanvas3D::select_bed(int i)
wxGetApp().plater()->get_camera().translate_world(s_multiple_beds.get_bed_translation(i) - s_multiple_beds.get_bed_translation(old_bed));
}
wxGetApp().plater()->schedule_background_process();
if (s_multiple_beds.is_autoslicing() && triggered_by_user)
s_multiple_beds.stop_autoslice(false);
});
}
@ -1899,21 +1901,7 @@ void GLCanvas3D::render()
#endif // SHOW_IMGUI_DEMO_WINDOW
{
if (s_multiple_beds.get_number_of_beds() != 1 && wxGetApp().plater()->is_preview_shown()) {
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::ImageButton((void*)(int64_t)s_th_tex_id[i], ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0)))
select_bed(i);
if (inactive)
ImGui::PopStyleColor();
}
ImGui::End();
}
}
const bool is_looking_downward = camera.is_looking_downward();
@ -1922,40 +1910,41 @@ void GLCanvas3D::render()
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
_render_background();
_render_objects(GLVolumeCollection::ERenderType::Opaque);
_render_sla_slices();
_render_selection();
_render_bed_axes();
if (is_looking_downward)
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), false);
if (!m_main_toolbar.is_enabled() && current_printer_technology() != ptSLA)
_render_gcode();
_render_objects(GLVolumeCollection::ERenderType::Transparent);
if (! s_multiple_beds.is_autoslicing()) {
_render_objects(GLVolumeCollection::ERenderType::Opaque);
_render_sla_slices();
_render_selection();
_render_bed_axes();
if (is_looking_downward)
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), false);
if (!m_main_toolbar.is_enabled() && current_printer_technology() != ptSLA)
_render_gcode();
_render_objects(GLVolumeCollection::ERenderType::Transparent);
_render_sequential_clearance();
#if ENABLE_RENDER_SELECTION_CENTER
_render_selection_center();
#endif // ENABLE_RENDER_SELECTION_CENTER
if (!m_main_toolbar.is_enabled())
_render_gcode_cog();
_render_sequential_clearance();
#if ENABLE_RENDER_SELECTION_CENTER
_render_selection_center();
#endif // ENABLE_RENDER_SELECTION_CENTER
if (!m_main_toolbar.is_enabled())
_render_gcode_cog();
// we need to set the mouse's scene position here because the depth buffer
// could be invalidated by the following gizmo render methods
// this position is used later into on_mouse() to drag the objects
if (m_picking_enabled)
m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast<coord_t>());
// we need to set the mouse's scene position here because the depth buffer
// could be invalidated by the following gizmo render methods
// this position is used later into on_mouse() to drag the objects
if (m_picking_enabled)
m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast<coord_t>());
// sidebar hints need to be rendered before the gizmos because the depth buffer
// could be invalidated by the following gizmo render methods
_render_selection_sidebar_hints();
_render_current_gizmo();
if (!is_looking_downward)
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), true);
// sidebar hints need to be rendered before the gizmos because the depth buffer
// could be invalidated by the following gizmo render methods
_render_selection_sidebar_hints();
_render_current_gizmo();
if (!is_looking_downward)
_render_bed(camera.get_view_matrix(), camera.get_projection_matrix(), true);
#if ENABLE_RAYCAST_PICKING_DEBUG
if (m_picking_enabled && !m_mouse.dragging && !m_gizmos.is_dragging() && !m_rectangle_selection.is_dragging())
m_scene_raycaster.render_hit(camera);
#endif // ENABLE_RAYCAST_PICKING_DEBUG
#if ENABLE_RAYCAST_PICKING_DEBUG
if (m_picking_enabled && !m_mouse.dragging && !m_gizmos.is_dragging() && !m_rectangle_selection.is_dragging())
m_scene_raycaster.render_hit(camera);
#endif // ENABLE_RAYCAST_PICKING_DEBUG
#if ENABLE_SHOW_CAMERA_TARGET
_render_camera_target();
@ -1963,11 +1952,74 @@ void GLCanvas3D::render()
_render_camera_target_validation_box();
#endif // ENABLE_SHOW_CAMERA_TARGET
if (m_picking_enabled && m_rectangle_selection.is_dragging())
m_rectangle_selection.render(*this);
if (m_picking_enabled && m_rectangle_selection.is_dragging())
m_rectangle_selection.render(*this);
} else {
// Autoslicing.
// Render the combined statistics if all is ready.
bool valid = true;
double total_g = 0;
for (size_t i=0; i<s_multiple_beds.get_number_of_beds(); ++i) {
const Print* print = wxGetApp().plater()->get_fff_prints()[i].get();
if (!print->finished()) {
// TODO: Only active bed invalidation can be detected here.
valid = false;
break;
}
total_g += print->print_statistics().total_used_filament;
}
ImGui::Begin("Total stats");
if (valid)
ImGui::Text("%s", std::to_string(total_g).c_str());
else
ImGui::Text("Wait until all beds are sliced...");
ImGui::End();
if (!valid) {
if (fff_print()->finished())
s_multiple_beds.autoslice_next_bed();
else
wxGetApp().plater()->schedule_background_process();
}
}
// draw overlays
_render_overlays();
{
if (s_multiple_beds.get_number_of_beds() != 1 && wxGetApp().plater()->is_preview_shown()) {
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() || s_multiple_beds.is_autoslicing();
if (inactive)
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0., 0., 0., .5));
if (bool clicked = (i >= int(s_th_tex_id.size()))
? ImGui::Button(std::to_string(i).c_str(), ImVec2(100,100))
: ImGui::ImageButton((void*)(int64_t)s_th_tex_id[i], ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0));
clicked)
select_bed(i, true);
if (inactive)
ImGui::PopStyleColor();
std::string status_text;
if (wxGetApp().plater()->get_fff_prints()[i]->finished())
status_text = "finished";
else if (m_process->fff_print() == wxGetApp().plater()->get_fff_prints()[i].get() && m_process->running())
status_text = "running";
else
status_text = "idle";
ImGui::SameLine();
ImGui::Text("%s", status_text.c_str());
}
if (ImGui::Button("ALL", ImVec2(105, 105))) {
if (! s_multiple_beds.is_autoslicing())
s_multiple_beds.start_autoslice([this](int i, bool user) { this->select_bed(i, user); });
}
ImGui::End();
}
}
// draw overlays
_render_overlays();
if (wxGetApp().plater()->is_render_statistic_dialog_visible()) {
ImGuiPureWrap::begin(std::string("Render statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
@ -2046,7 +2098,8 @@ void GLCanvas3D::render()
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width());
wxGetApp().plater()->render_sliders(*this);
if (! s_multiple_beds.is_autoslicing())
wxGetApp().plater()->render_sliders(*this);
wxGetApp().imgui()->render();
@ -3696,7 +3749,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
} else if (evt.LeftDown()) {
select_bed(s_multiple_beds.get_last_hovered_bed());
select_bed(s_multiple_beds.get_last_hovered_bed(), true);
}
}

View File

@ -526,9 +526,13 @@ private:
Selection m_selection;
const DynamicPrintConfig* m_config;
Model* m_model;
public:
BackgroundSlicingProcess *m_process;
private:
bool m_requires_check_outside_state{ false };
void select_bed(int i, bool triggered_by_user);
std::array<unsigned int, 2> m_old_size{ 0, 0 };
// Screen is only refreshed from the OnIdle handler if it is dirty.
@ -742,8 +746,6 @@ private:
// returns the containment state in the given out_state, if non-null
bool check_volumes_outside_state(GLVolumeCollection& volumes, ModelInstanceEPrintVolumeState* out_state, bool selection_only = true) const;
void select_bed(int i);
public:
void init_gcode_viewer() { m_gcode_viewer.init(); }
void reset_gcode_toolpaths() { m_gcode_viewer.reset(); }

View File

@ -2228,10 +2228,6 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
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();
@ -2945,6 +2941,9 @@ void Plater::priv::set_current_panel(wxPanel* panel)
panel_sizer->Layout();
if (current_panel == view3D) {
s_multiple_beds.stop_autoslice(true);
if (old_panel == preview)
preview->get_canvas3d()->unbind_event_handlers();
@ -7314,6 +7313,11 @@ std::vector<std::unique_ptr<Print>>& Plater::get_fff_prints()
return p->fff_prints;
}
const std::vector<GCodeProcessorResult>& Plater::get_gcode_results() const
{
return p->gcode_results;
}
wxMenu* Plater::object_menu() { return p->menus.object_menu(); }
wxMenu* Plater::part_menu() { return p->menus.part_menu(); }
wxMenu* Plater::text_part_menu() { return p->menus.text_part_menu(); }

View File

@ -102,6 +102,7 @@ public:
SLAPrint& active_sla_print();
std::vector<std::unique_ptr<Print>>& get_fff_prints();
const std::vector<GCodeProcessorResult>& get_gcode_results() const;
void new_project();
void load_project();