mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-05 15:10:39 +08:00
Autoslice (part 1)
This commit is contained in:
parent
0bd37e6b08
commit
e1be0f041c
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(); }
|
||||
|
@ -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(); }
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user