Merge branch 'et_gcode_viewer' of https://github.com/prusa3d/PrusaSlicer into et_gcode_viewer

This commit is contained in:
Enrico Turri 2020-05-18 15:01:41 +02:00
commit 48091bb9f0
5 changed files with 138 additions and 65 deletions

View file

@ -12,6 +12,7 @@
#include "DoubleSlider.hpp"
#include "GLCanvas3D.hpp"
#include "GLToolbar.hpp"
#include "GUI_Preview.hpp"
#include "libslic3r/Model.hpp"
#if ENABLE_GCODE_VIEWER_STATISTICS
#include <imgui/imgui_internal.h>
@ -279,7 +280,7 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std:
}
// update buffers' render paths
refresh_render_paths(false);
refresh_render_paths(false, false);
#if ENABLE_GCODE_VIEWER_STATISTICS
m_statistics.refresh_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
@ -349,16 +350,16 @@ unsigned int GCodeViewer::get_options_visibility_flags() const
};
unsigned int flags = 0;
flags = set_flag(flags, 0, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Travel));
flags = set_flag(flags, 1, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Retract));
flags = set_flag(flags, 2, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Unretract));
flags = set_flag(flags, 3, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Tool_change));
flags = set_flag(flags, 4, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Color_change));
flags = set_flag(flags, 5, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print));
flags = set_flag(flags, 6, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode));
flags = set_flag(flags, 7, m_shells.visible);
flags = set_flag(flags, 8, m_sequential_view.marker.is_visible());
flags = set_flag(flags, 9, is_legend_enabled());
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Travel), is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Travel));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Retractions), is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Retract));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Unretractions), is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Unretract));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::ToolChanges), is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Tool_change));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::ColorChanges), is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Color_change));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::PausePrints), is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::CustomGCodes), is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode));
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Shells), m_shells.visible);
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::ToolMarker), m_sequential_view.marker.is_visible());
flags = set_flag(flags, static_cast<unsigned int>(Preview::OptionType::Legend), is_legend_enabled());
return flags;
}
@ -368,23 +369,24 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags)
return (flags & (1 << flag)) != 0;
};
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Travel, is_flag_set(0));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Retract, is_flag_set(1));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Unretract, is_flag_set(2));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Tool_change, is_flag_set(3));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Color_change, is_flag_set(4));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print, is_flag_set(5));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode, is_flag_set(6));
m_shells.visible = is_flag_set(7);
m_sequential_view.marker.set_visible(is_flag_set(8));
enable_legend(is_flag_set(9));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Travel, is_flag_set(static_cast<unsigned int>(Preview::OptionType::Travel)));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Retract, is_flag_set(static_cast<unsigned int>(Preview::OptionType::Retractions)));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Unretract, is_flag_set(static_cast<unsigned int>(Preview::OptionType::Unretractions)));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Tool_change, is_flag_set(static_cast<unsigned int>(Preview::OptionType::ToolChanges)));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Color_change, is_flag_set(static_cast<unsigned int>(Preview::OptionType::ColorChanges)));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print, is_flag_set(static_cast<unsigned int>(Preview::OptionType::PausePrints)));
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode, is_flag_set(static_cast<unsigned int>(Preview::OptionType::CustomGCodes)));
m_shells.visible = is_flag_set(static_cast<unsigned int>(Preview::OptionType::Shells));
m_sequential_view.marker.set_visible(is_flag_set(static_cast<unsigned int>(Preview::OptionType::ToolMarker)));
enable_legend(is_flag_set(static_cast<unsigned int>(Preview::OptionType::Legend)));
}
void GCodeViewer::set_layers_z_range(const std::array<double, 2>& layers_z_range)
{
bool keep_sequential_current = layers_z_range[1] <= m_layers_z_range[1];
bool keep_sequential_current_first = layers_z_range[0] >= m_layers_z_range[0];
bool keep_sequential_current_last = layers_z_range[1] <= m_layers_z_range[1];
m_layers_z_range = layers_z_range;
refresh_render_paths(keep_sequential_current);
refresh_render_paths(keep_sequential_current_first, keep_sequential_current_last);
wxGetApp().plater()->update_preview_moves_slider();
}
@ -628,7 +630,7 @@ void GCodeViewer::load_shells(const Print& print, bool initialized)
}
}
void GCodeViewer::refresh_render_paths(bool keep_sequential_current) const
void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const
{
#if ENABLE_GCODE_VIEWER_STATISTICS
auto start_time = std::chrono::high_resolution_clock::now();
@ -661,10 +663,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current) const
m_statistics.render_paths_size = 0;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
m_sequential_view.first = m_vertices.vertices_count;
m_sequential_view.last = 0;
if (!keep_sequential_current)
m_sequential_view.current = m_vertices.vertices_count;
m_sequential_view.endpoints.first = m_vertices.vertices_count;
m_sequential_view.endpoints.last = 0;
if (!keep_sequential_current_first)
m_sequential_view.current.first = 0;
if (!keep_sequential_current_last)
m_sequential_view.current.last = m_vertices.vertices_count;
// first pass: collect visible paths and update sequential view data
std::vector<std::pair<IBuffer*, size_t>> paths;
@ -690,22 +694,23 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current) const
// store valid path
paths.push_back({ &buffer, i });
m_sequential_view.first = std::min(m_sequential_view.first, path.first.s_id);
m_sequential_view.last = std::max(m_sequential_view.last, path.last.s_id);
m_sequential_view.endpoints.first = std::min(m_sequential_view.endpoints.first, path.first.s_id);
m_sequential_view.endpoints.last = std::max(m_sequential_view.endpoints.last, path.last.s_id);
}
}
// update current sequential position
m_sequential_view.current = keep_sequential_current ? std::clamp(m_sequential_view.current, m_sequential_view.first, m_sequential_view.last) : m_sequential_view.last;
m_sequential_view.current.first = keep_sequential_current_first ? std::clamp(m_sequential_view.current.first, m_sequential_view.endpoints.first, m_sequential_view.endpoints.last) : m_sequential_view.endpoints.first;
m_sequential_view.current.last = keep_sequential_current_last ? std::clamp(m_sequential_view.current.last, m_sequential_view.endpoints.first, m_sequential_view.endpoints.last) : m_sequential_view.endpoints.last;
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices.vbo_id));
size_t v_size = VBuffer::vertex_size_bytes();
glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(m_sequential_view.current * v_size), static_cast<GLsizeiptr>(v_size), static_cast<void*>(m_sequential_view.current_position.data())));
glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(m_sequential_view.current.last * v_size), static_cast<GLsizeiptr>(v_size), static_cast<void*>(m_sequential_view.current_position.data())));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
// second pass: filter paths by sequential data
for (auto&& [buffer, id] : paths) {
const Path& path = buffer->paths[id];
if ((m_sequential_view.current < path.first.s_id) || (path.last.s_id < m_sequential_view.first))
if ((m_sequential_view.current.last <= path.first.s_id) || (path.last.s_id <= m_sequential_view.current.first))
continue;
Color color;
@ -722,8 +727,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current) const
it->color = color;
}
it->sizes.push_back(std::min(m_sequential_view.current, path.last.s_id) - path.first.s_id + 1);
it->offsets.push_back(static_cast<size_t>(path.first.i_id * sizeof(unsigned int)));
it->sizes.push_back(std::min(m_sequential_view.current.last, path.last.s_id) - std::max(m_sequential_view.current.first, path.first.s_id) + 1);
unsigned int delta_1st = 0;
if ((path.first.s_id < m_sequential_view.current.first) && (m_sequential_view.current.first <= path.last.s_id))
delta_1st = m_sequential_view.current.first - path.first.s_id;
it->offsets.push_back(static_cast<size_t>((path.first.i_id + delta_1st) * sizeof(unsigned int)));
}
#if ENABLE_GCODE_VIEWER_STATISTICS
@ -1013,7 +1022,7 @@ void GCodeViewer::render_legend() const
{
m_extrusions.role_visibility_flags = is_visible(role) ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role);
// update buffers' render paths
refresh_render_paths(false);
refresh_render_paths(false, false);
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
wxGetApp().plater()->update_preview_bottom_toolbar();
}

View file

@ -222,9 +222,14 @@ public:
void init_shader();
};
unsigned int first{ 0 };
unsigned int last{ 0 };
unsigned int current{ 0 };
struct Endpoints
{
unsigned int first{ 0 };
unsigned int last{ 0 };
};
Endpoints endpoints;
Endpoints current;
Vec3f current_position{ Vec3f::Zero() };
Marker marker;
};
@ -285,7 +290,12 @@ public:
const std::vector<double>& get_layers_zs() const { return m_layers_zs; };
const SequentialView& get_sequential_view() const { return m_sequential_view; }
void update_sequential_view_current(unsigned int low, unsigned int high) { m_sequential_view.current = high; refresh_render_paths(true); }
void update_sequential_view_current(unsigned int first, unsigned int last)
{
m_sequential_view.current.first = first;
m_sequential_view.current.last = last;
refresh_render_paths(true, true);
}
EViewType get_view_type() const { return m_view_type; }
void set_view_type(EViewType type) {
@ -310,7 +320,7 @@ private:
bool init_shaders();
void load_toolpaths(const GCodeProcessor::Result& gcode_result);
void load_shells(const Print& print, bool initialized);
void refresh_render_paths(bool keep_sequential_current) const;
void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const;
void render_toolpaths() const;
void render_shells() const;
void render_legend() const;

View file

@ -298,17 +298,17 @@ bool Preview::init(wxWindow* parent, Model* model)
m_combochecklist_options = new wxComboCtrl();
m_combochecklist_options->Create(this, wxID_ANY, _L("Options"), wxDefaultPosition, wxDefaultSize, wxCB_READONLY);
std::string options_items = GUI::into_u8(
_L("Travel") + "|0|" +
_L("Retractions") + "|0|" +
_L("Unretractions") + "|0|" +
_L("Tool changes") + "|0|" +
_L("Color changes") + "|0|" +
_L("Pause prints") + "|0|" +
_L("Custom GCodes") + "|0|" +
_L("Shells") + "|0|" +
_L("Tool marker") + "|1|" +
_L("Legend") + "|1"
);
get_option_type_string(OptionType::Travel) + "|0|" +
get_option_type_string(OptionType::Retractions) + "|0|" +
get_option_type_string(OptionType::Unretractions) + "|0|" +
get_option_type_string(OptionType::ToolChanges) + "|0|" +
get_option_type_string(OptionType::ColorChanges) + "|0|" +
get_option_type_string(OptionType::PausePrints) + "|0|" +
get_option_type_string(OptionType::CustomGCodes) + "|0|" +
get_option_type_string(OptionType::Shells) + "|0|" +
get_option_type_string(OptionType::ToolMarker) + "|0|" +
get_option_type_string(OptionType::Legend) + "|1"
);
Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items);
#else
m_checkbox_travel = new wxCheckBox(this, wxID_ANY, _(L("Travel")));
@ -328,19 +328,19 @@ bool Preview::init(wxWindow* parent, Model* model)
#endif // ENABLE_GCODE_VIEWER
#if ENABLE_GCODE_VIEWER
m_moves_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL);
m_moves_slider = new DoubleSlider::Control(this, wxID_ANY, 0, 0, 0, 100, wxDefaultPosition, wxSize(-1, 3 * GetTextExtent("m").y), wxSL_HORIZONTAL);
m_moves_slider->SetDrawMode(DoubleSlider::dmSequentialGCodeView);
m_moves_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_moves_slider_scroll_changed, this);
m_bottom_toolbar_sizer = new wxBoxSizer(wxHORIZONTAL);
m_bottom_toolbar_sizer->AddSpacer(10);
m_bottom_toolbar_sizer->AddSpacer(5);
m_bottom_toolbar_sizer->Add(m_label_view_type, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
m_bottom_toolbar_sizer->Add(m_choice_view_type, 0, wxALIGN_CENTER_VERTICAL, 5);
m_bottom_toolbar_sizer->AddSpacer(10);
m_bottom_toolbar_sizer->Add(m_choice_view_type, 0, wxALIGN_CENTER_VERTICAL, 0);
m_bottom_toolbar_sizer->AddSpacer(5);
m_bottom_toolbar_sizer->Add(m_label_show, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5);
m_bottom_toolbar_sizer->Add(m_combochecklist_options, 0, wxALIGN_CENTER_VERTICAL, 5);
m_bottom_toolbar_sizer->Add(m_combochecklist_options, 0, wxALIGN_CENTER_VERTICAL, 0);
m_bottom_toolbar_sizer->Add(m_combochecklist_features, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 5);
m_bottom_toolbar_sizer->AddSpacer(10);
m_bottom_toolbar_sizer->AddSpacer(5);
m_bottom_toolbar_sizer->Add(m_moves_slider, 1, wxALL | wxEXPAND, 5);
#else
wxBoxSizer* bottom_sizer = new wxBoxSizer(wxHORIZONTAL);
@ -686,8 +686,27 @@ void Preview::on_combochecklist_features(wxCommandEvent& evt)
#if ENABLE_GCODE_VIEWER
void Preview::on_combochecklist_options(wxCommandEvent& evt)
{
m_canvas->set_gcode_options_visibility_from_flags(Slic3r::GUI::combochecklist_get_flags(m_combochecklist_options));
refresh_print();
auto xored = [](unsigned int flags1, unsigned int flags2, unsigned int flag) {
auto is_flag_set = [](unsigned int flags, unsigned int flag) {
return (flags & (1 << flag)) != 0;
};
return !is_flag_set(flags1, flag) != !is_flag_set(flags2, flag);
};
unsigned int curr_flags = m_canvas->get_gcode_options_visibility_flags();
unsigned int new_flags = Slic3r::GUI::combochecklist_get_flags(m_combochecklist_options);
if (curr_flags == new_flags)
return;
m_canvas->set_gcode_options_visibility_from_flags(new_flags);
bool skip_refresh = xored(curr_flags, new_flags, static_cast<unsigned int>(OptionType::Shells)) ||
xored(curr_flags, new_flags, static_cast<unsigned int>(OptionType::ToolMarker));
if (!skip_refresh)
refresh_print();
else
m_canvas->set_as_dirty();
}
#else
void Preview::on_checkbox_travel(wxCommandEvent& evt)
@ -1082,16 +1101,16 @@ void Preview::update_layers_slider_from_canvas(wxKeyEvent& event)
void Preview::update_moves_slider()
{
const GCodeViewer::SequentialView& view = m_canvas->get_gcode_sequential_view();
std::vector<double> values(view.last - view.first + 1);
std::vector<double> values(view.endpoints.last - view.endpoints.first + 1);
unsigned int count = 0;
for (unsigned int i = view.first; i <= view.last; ++i)
for (unsigned int i = view.endpoints.first; i <= view.endpoints.last; ++i)
{
values[count++] = static_cast<double>(i + 1);
}
m_moves_slider->SetSliderValues(values);
m_moves_slider->SetMaxValue(view.last - view.first);
m_moves_slider->SetSelectionSpan(0, view.current);
m_moves_slider->SetMaxValue(view.endpoints.last - view.endpoints.first);
m_moves_slider->SetSelectionSpan(view.current.first - view.endpoints.first, view.current.last - view.endpoints.first);
}
#else
void Preview::update_double_slider_from_canvas(wxKeyEvent & event)
@ -1356,6 +1375,25 @@ void Preview::on_moves_slider_scroll_changed(wxCommandEvent& event)
m_canvas->update_gcode_sequential_view_current(static_cast<unsigned int>(m_moves_slider->GetLowerValueD()), static_cast<unsigned int>(m_moves_slider->GetHigherValueD()));
m_canvas->render();
}
wxString Preview::get_option_type_string(OptionType type) const
{
switch (type)
{
case OptionType::Travel: { return _L("Travel"); }
case OptionType::Retractions: { return _L("Retractions"); }
case OptionType::Unretractions: { return _L("Unretractions"); }
case OptionType::ToolChanges: { return _L("Tool changes"); }
case OptionType::ColorChanges: { return _L("Color changes"); }
case OptionType::PausePrints: { return _L("Pause prints"); }
case OptionType::CustomGCodes: { return _L("Custom GCodes"); }
case OptionType::Shells: { return _L("Shells"); }
case OptionType::ToolMarker: { return _L("Tool marker"); }
case OptionType::Legend: { return _L("Legend"); }
default: { return ""; }
}
}
#endif // ENABLE_GCODE_VIEWER
} // namespace GUI

View file

@ -136,6 +136,20 @@ class Preview : public wxPanel
public:
#if ENABLE_GCODE_VIEWER
enum class OptionType : unsigned int
{
Travel,
Retractions,
Unretractions,
ToolChanges,
ColorChanges,
PausePrints,
CustomGCodes,
Shells,
ToolMarker,
Legend
};
Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process,
GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process = []() {});
#else
@ -235,6 +249,7 @@ private:
#if ENABLE_GCODE_VIEWER
void on_layers_slider_scroll_changed(wxCommandEvent& event);
void on_moves_slider_scroll_changed(wxCommandEvent& event);
wxString get_option_type_string(OptionType type) const;
#else
void on_sliders_scroll_changed(wxCommandEvent& event);
#endif // ENABLE_GCODE_VIEWER

View file

@ -298,7 +298,8 @@ void OtherInstanceMessageHandler::shutdown(MainFrame* main_frame)
m_stop = false;
}
#endif //BACKGROUND_MESSAGE_LISTENER
m_initialized = false;
m_callback_evt_handler = nullptr;
m_initialized = false;
}
}