From 7f2d1522ce31f2467c238ca330d342d5eb37d872 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 3 Sep 2021 15:35:44 +0200 Subject: [PATCH 01/27] Rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3 --- src/libslic3r/Technologies.hpp | 27 ++-- src/slic3r/GUI/GCodeViewer.cpp | 243 +++++++++++++++++++++++++++- src/slic3r/GUI/GCodeViewer.hpp | 56 +++++++ src/slic3r/GUI/GLModel.cpp | 20 +++ src/slic3r/GUI/GLModel.hpp | 9 ++ src/slic3r/GUI/GLShadersManager.cpp | 9 ++ 6 files changed, 351 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 6132430f1..d031b9527 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -37,24 +37,33 @@ //==================== -// 2.4.0.alpha0 techs +// 2.4.0.alpha1 techs //==================== -#define ENABLE_2_4_0_ALPHA0 1 +#define ENABLE_2_4_0_ALPHA1 1 // Enable delayed rendering of transparent volumes -#define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA1) // Enable the fix of importing color print view from gcode files into GCodeViewer -#define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA1) // Enable drawing contours, at cut level, for sinking volumes -#define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA1) // Enable implementation of retract acceleration in gcode processor -#define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA1) // Enable the fix for exporting and importing to/from 3mf file of mirrored volumes -#define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA1) // Enable rendering seams (and other options) in preview using models -#define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA1) // Enable save and save as commands to be enabled also when the plater is empty and allow to load empty projects -#define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) +#define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA1) + + +//==================== +// 2.4.0.alpha2 techs +//==================== +#define ENABLE_2_4_0_ALPHA2 1 + +// Enable rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3 +#define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 3fc624264..1e0b9b124 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -807,6 +807,25 @@ void GCodeViewer::render() case EMoveType::Unretract: case EMoveType::Seam: { #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; + buffer.shader = "gouraud_light_instanced"; + buffer.model.model.init_from(diamond(16)); + buffer.model.color = option_color(type); + buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; + } + else { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; + buffer.vertices.format = VBuffer::EFormat::PositionNormal3; + buffer.shader = "gouraud_light"; + + buffer.model.data = diamond(16); + buffer.model.color = option_color(type); + buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; + } + break; +#else if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; buffer.shader = "gouraud_light_instanced"; @@ -819,6 +838,7 @@ void GCodeViewer::render() buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; } break; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #else buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; buffer.vertices.format = VBuffer::EFormat::Position; @@ -1221,7 +1241,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) { if (prev.type != curr.type || !buffer.paths.back().matches(curr)) { // add starting index - indices.push_back(static_cast(indices.size())); + indices.push_back(static_cast(indices.size())); buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1); buffer.paths.back().sub_paths.front().first.position = prev.position; } @@ -1229,11 +1249,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) Path& last_path = buffer.paths.back(); if (last_path.sub_paths.front().first.i_id != last_path.sub_paths.back().last.i_id) { // add previous index - indices.push_back(static_cast(indices.size())); + indices.push_back(static_cast(indices.size())); } // add current index - indices.push_back(static_cast(indices.size())); + indices.push_back(static_cast(indices.size())); last_path.sub_paths.back().last = { ibuffer_id, indices.size() - 1, move_id, curr.position }; }; @@ -1436,7 +1456,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) }; #if ENABLE_SEAMS_USING_MODELS - // format data into the buffers to be rendered as model + // format data into the buffers to be rendered as instanced model auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { // append position instances.push_back(curr.position.x()); @@ -1450,6 +1470,49 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // append id instances_ids.push_back(move_id); }; + +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // format data into the buffers to be rendered as batched model + auto add_vertices_as_model_batch = [](const GCodeProcessor::MoveVertex& curr, const GLModel::InitializationData& data, VertexBuffer& vertices, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { + const double width = static_cast(1.5f * curr.width); + const double height = static_cast(1.5f * curr.height); + + const Transform3d trafo = Geometry::assemble_transform(curr.position.cast(), Vec3d::Zero(), { width, width, height }); + const Eigen::Matrix normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose(); + + for (const auto& entity : data.entities) { + // append vertices + for (size_t i = 0; i < entity.positions.size(); ++i) { + // append position + const Vec3d position = trafo * entity.positions[i].cast(); + vertices.push_back(static_cast(position.x())); + vertices.push_back(static_cast(position.y())); + vertices.push_back(static_cast(position.z())); + + // append normal + const Vec3d normal = normal_matrix * entity.normals[i].cast(); + vertices.push_back(static_cast(normal.x())); + vertices.push_back(static_cast(normal.y())); + vertices.push_back(static_cast(normal.z())); + } + } + + // append instance position + instances.push_back(curr.position.x()); + instances.push_back(curr.position.y()); + instances.push_back(curr.position.z()); + // append instance id + instances_ids.push_back(move_id); + }; + + auto add_indices_as_model_batch = [](const GLModel::InitializationData& data, IndexBuffer& indices, IBufferType base_index) { + for (const auto& entity : data.entities) { + for (size_t i = 0; i < entity.indices.size(); ++i) { + indices.push_back(static_cast(entity.indices[i] + base_index)); + } + } + }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1533,7 +1596,12 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // add another vertex buffer +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); + if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { +#else if (v_multibuffer.back().size() * sizeof(float) > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS v_multibuffer.push_back(VertexBuffer()); if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { Path& last_path = t_buffer.paths.back(); @@ -1550,6 +1618,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, i); break; } #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + case TBuffer::ERenderPrimitiveType::InstancedModel: + { + add_model_instance(curr, inst_buffer, inst_id_buffer, i); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.instances_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + break; + } + case TBuffer::ERenderPrimitiveType::BatchedModel: + { + add_vertices_as_model_batch(curr, t_buffer.model.data, v_buffer, inst_buffer, inst_id_buffer, i); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.batched_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + break; + } +#else case TBuffer::ERenderPrimitiveType::Model: { add_model_instance(curr, inst_buffer, inst_id_buffer, i); @@ -1559,6 +1645,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) break; } #endif // ENABLE_SEAMS_USING_MODELS +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS } // collect options zs for later use @@ -1741,6 +1828,23 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { + const InstanceBuffer& inst_buffer = instances[i]; + if (!inst_buffer.empty()) { + t_buffer.model.instances.buffer = inst_buffer; + t_buffer.model.instances.s_ids = instances_ids[i]; + } + } + else { + if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { + const InstanceBuffer& inst_buffer = instances[i]; + if (!inst_buffer.empty()) { + t_buffer.model.instances.buffer = inst_buffer; + t_buffer.model.instances.s_ids = instances_ids[i]; + } + } +#else if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { const InstanceBuffer& inst_buffer = instances[i]; if (!inst_buffer.empty()) { @@ -1749,6 +1853,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } else { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS const MultiVertexBuffer& v_multibuffer = vertices[i]; for (const VertexBuffer& v_buffer : v_multibuffer) { @@ -1842,10 +1947,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the indices for the current segment exceeds the threshold size of the current index buffer // create another index buffer +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t indiced_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.indices_size_bytes() : t_buffer.max_indices_per_segment_size_bytes(); + if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - indiced_size_to_add) { +#else if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - t_buffer.max_indices_per_segment_size_bytes()) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS i_multibuffer.push_back(IndexBuffer()); vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && + t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); } @@ -1853,14 +1968,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer // create another index buffer +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t vertices_size_to_add = (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) ? t_buffer.model.data.vertices_size_bytes() : t_buffer.max_vertices_per_segment_size_bytes(); + if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - vertices_size_to_add) { +#else if (curr_vertex_buffer.second * t_buffer.vertices.vertex_size_bytes() > t_buffer.vertices.max_size_bytes() - t_buffer.max_vertices_per_segment_size_bytes()) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS i_multibuffer.push_back(IndexBuffer()); ++curr_vertex_buffer.first; curr_vertex_buffer.second = 0; vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point && + t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS Path& last_path = t_buffer.paths.back(); last_path.add_sub_path(prev, static_cast(i_multibuffer.size()) - 1, 0, i - 1); } @@ -1884,6 +2009,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast(i_multibuffer.size()) - 1, i_buffer, i); break; } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + case TBuffer::ERenderPrimitiveType::BatchedModel: { + add_indices_as_model_batch(t_buffer.model.data, i_buffer, curr_vertex_buffer.second); + curr_vertex_buffer.second += t_buffer.model.data.vertices_count(); + break; + } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS default: { break; } } } @@ -1898,7 +2030,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel) { +#else if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS const MultiIndexBuffer& i_multibuffer = indices[i]; for (const IndexBuffer& i_buffer : i_multibuffer) { @@ -2174,7 +2310,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool continue; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || + buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t id : buffer.model.instances.s_ids) { if (id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) continue; @@ -2239,7 +2380,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool bool found = false; for (const TBuffer& buffer : m_buffers) { #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel || + buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { +#else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t i = 0; i < buffer.model.instances.s_ids.size(); ++i) { if (buffer.model.instances.s_ids[i] == m_sequential_view.current.last) { size_t offset = i * buffer.model.instances.instance_size_floats(); @@ -2400,10 +2546,19 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // second pass: for buffers using instanced and batched models, update the instances render ranges +#else // second pass: for buffers using instanced models, update the instances render ranges +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS for (size_t b = 0; b < m_buffers.size(); ++b) { TBuffer& buffer = const_cast(m_buffers[b]); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::InstancedModel && + buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::BatchedModel) +#else if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS continue; buffer.model.instances.render_ranges.reset(); @@ -2689,6 +2844,66 @@ void GCodeViewer::render_toolpaths() } } }; + +#if ENABLE_SEAMS_USING_BATCHED_MODELS +#if ENABLE_GCODE_VIEWER_STATISTICS + auto render_as_batched_model = [this](TBuffer& buffer, GLShaderProgram& shader) { +#else + auto render_as_batched_model = [](TBuffer& buffer, GLShaderProgram& shader) { +#endif // ENABLE_GCODE_VIEWER_STATISTICS + + struct Range + { + unsigned int first; + unsigned int last; + bool intersects(const Range& other) const { return (other.last < first || other.first > last) ? false : true; } + }; + Range buffer_range = { 0, 0 }; + size_t indices_per_instance = buffer.model.data.indices_count(); + + for (size_t j = 0; j < buffer.indices.size(); ++j) { + const IBuffer& i_buffer = buffer.indices[j]; + buffer_range.last = buffer_range.first + i_buffer.count / indices_per_instance; + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); + glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + bool has_normals = buffer.vertices.normal_size_floats() > 0; + if (has_normals) { + glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); + + for (auto& range : buffer.model.instances.render_ranges.ranges) { + Range range_range = { range.offset, range.offset + range.count }; + if (range_range.intersects(buffer_range)) { + shader.set_uniform("uniform_color", range.color); + unsigned int offset = (range_range.first > buffer_range.first) ? range_range.first - buffer_range.first : 0; + size_t offset_bytes = static_cast(offset) * indices_per_instance * sizeof(IBufferType); + Range render_range = { std::max(range_range.first, buffer_range.first), std::min(range_range.last, buffer_range.last) }; + size_t count = static_cast(render_range.last - render_range.first) * indices_per_instance; + if (count > 0) { + glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)count, GL_UNSIGNED_SHORT, (const void*)offset_bytes)); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.gl_batched_models_calls_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + } + } + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + if (has_normals) + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + buffer_range.first = buffer_range.last; + } + }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS auto line_width = [](double zoom) { @@ -2712,11 +2927,22 @@ void GCodeViewer::render_toolpaths() shader->start_using(); #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::InstancedModel) { +#else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS shader->set_uniform("emission_factor", 0.25f); render_as_instanced_model(buffer, *shader); shader->set_uniform("emission_factor", 0.0f); } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::BatchedModel) { + shader->set_uniform("emission_factor", 0.25f); + render_as_batched_model(buffer, *shader); + shader->set_uniform("emission_factor", 0.0f); + } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS else { #endif // ENABLE_SEAMS_USING_MODELS for (size_t j = 0; j < buffer.indices.size(); ++j) { @@ -2882,6 +3108,7 @@ void GCodeViewer::render_legend(float& legend_height) } case EItemType::Circle: { ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size)); +#if !ENABLE_SEAMS_USING_BATCHED_MODELS if (m_buffers[buffer_id(EMoveType::Retract)].shader == "options_120") { draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); @@ -2891,6 +3118,7 @@ void GCodeViewer::render_legend(float& legend_height) draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); } else +#endif // !ENABLE_SEAMS_USING_BATCHED_MODELS draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); break; @@ -3756,7 +3984,11 @@ void GCodeViewer::render_statistics() add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count); add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count); #if ENABLE_SEAMS_USING_MODELS + ImGui::Separator(); add_counter(std::string("Instanced models:"), m_statistics.gl_instanced_models_calls_count); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + add_counter(std::string("Batched models:"), m_statistics.gl_batched_models_calls_count); +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -3788,6 +4020,9 @@ void GCodeViewer::render_statistics() add_counter(std::string("Extrude segments count:"), m_statistics.extrude_segments_count); #if ENABLE_SEAMS_USING_MODELS add_counter(std::string("Instances count:"), m_statistics.instances_count); +#if ENABLE_SEAMS_USING_BATCHED_MODELS + add_counter(std::string("Batched count:"), m_statistics.batched_count); +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS ImGui::Separator(); add_counter(std::string("VBuffers count:"), m_statistics.vbuffers_count); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 429175fe6..86a7dcf85 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -105,9 +105,16 @@ class GCodeViewer }; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // buffer containing instances data used to render a toolpaths using instanced or batched models + // instance record format: + // instanced models: 5 floats -> position.x|position.y|position.z|width|height (which are sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced()) + // batched models: 3 floats -> position.x|position.y|position.z +#else // buffer containing instances data used to render a toolpaths using instanced models // instance record format: 5 floats -> position.x|position.y|position.z|width|height // which is sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced() +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS struct InstanceVBuffer { // ranges used to render only subparts of the intances @@ -130,6 +137,16 @@ class GCodeViewer void reset(); }; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + enum class EFormat : unsigned char + { + InstancedModel, + BatchedModel + }; + + EFormat format; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS + // cpu-side buffer containing all instances data InstanceBuffer buffer; // indices of the moves for all instances @@ -138,7 +155,18 @@ class GCodeViewer size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t instance_size_floats() const { + switch (format) + { + case EFormat::InstancedModel: { return 5; } + case EFormat::BatchedModel: { return 3; } + default: { return 0; } + } + } +#else size_t instance_size_floats() const { return 5; } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS size_t instance_size_bytes() const { return instance_size_floats() * sizeof(float); } void reset(); @@ -280,7 +308,12 @@ class GCodeViewer Line, #if ENABLE_SEAMS_USING_MODELS Triangle, +#if ENABLE_SEAMS_USING_BATCHED_MODELS + InstancedModel, + BatchedModel +#else Model +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #else Triangle #endif // ENABLE_SEAMS_USING_MODELS @@ -298,6 +331,9 @@ class GCodeViewer GLModel model; Color color; InstanceVBuffer instances; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + GLModel::InitializationData data; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS void reset(); }; @@ -362,7 +398,15 @@ class GCodeViewer case ERenderPrimitiveType::Triangle: { return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } +#if ENABLE_SEAMS_USING_BATCHED_MODELS + case ERenderPrimitiveType::InstancedModel: { return model.model.is_initialized() && !model.instances.buffer.empty(); } + case ERenderPrimitiveType::BatchedModel: { + return model.data.vertices_count() > 0 && model.data.indices_count() && + !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; + } +#else case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.buffer.empty(); } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS default: { return false; } } } @@ -520,6 +564,9 @@ class GCodeViewer int64_t gl_triangles_calls_count{ 0 }; #if ENABLE_SEAMS_USING_MODELS int64_t gl_instanced_models_calls_count{ 0 }; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + int64_t gl_batched_models_calls_count{ 0 }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS // memory int64_t results_size{ 0 }; @@ -541,6 +588,9 @@ class GCodeViewer int64_t extrude_segments_count{ 0 }; #if ENABLE_SEAMS_USING_MODELS int64_t instances_count{ 0 }; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + int64_t batched_count{ 0 }; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS int64_t vbuffers_count{ 0 }; int64_t ibuffers_count{ 0 }; @@ -569,6 +619,9 @@ class GCodeViewer gl_triangles_calls_count = 0; #if ENABLE_SEAMS_USING_MODELS gl_instanced_models_calls_count = 0; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + gl_batched_models_calls_count = 0; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -594,6 +647,9 @@ class GCodeViewer extrude_segments_count = 0; #if ENABLE_SEAMS_USING_MODELS instances_count = 0; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + batched_count = 0; +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS #endif // ENABLE_SEAMS_USING_MODELS vbuffers_count = 0; ibuffers_count = 0; diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 5cddd7fa3..d22925673 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -19,6 +19,26 @@ namespace Slic3r { namespace GUI { +#if ENABLE_SEAMS_USING_BATCHED_MODELS +size_t GLModel::InitializationData::vertices_count() const +{ + size_t ret = 0; + for (const Entity& entity : entities) { + ret += entity.positions.size(); + } + return ret; +} + +size_t GLModel::InitializationData::indices_count() const +{ + size_t ret = 0; + for (const Entity& entity : entities) { + ret += entity.indices.size(); + } + return ret; +} +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS + void GLModel::init_from(const InitializationData& data) { if (!m_render_data.empty()) // call reset() if you want to reuse this model diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 8e0039b08..7422466f0 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -48,6 +48,15 @@ namespace GUI { }; std::vector entities; + +#if ENABLE_SEAMS_USING_BATCHED_MODELS + size_t vertices_count() const; + size_t vertices_size_floats() const { return vertices_count() * 6; } + size_t vertices_size_bytes() const { return vertices_size_floats() * sizeof(float); } + + size_t indices_count() const; + size_t indices_size_bytes() const { return indices_count() * sizeof(unsigned int); } +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS }; private: diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index edbe2bb46..5dd478b57 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -33,11 +33,19 @@ std::pair GLShadersManager::init() bool valid = true; +#if ENABLE_SEAMS_USING_BATCHED_MODELS + // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview +#else // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" }); // used to render printbed valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview +#if ENABLE_SEAMS_USING_BATCHED_MODELS + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) + valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); +#else #if ENABLE_SEAMS_USING_MODELS if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); @@ -49,6 +57,7 @@ std::pair GLShadersManager::init() #if ENABLE_SEAMS_USING_MODELS } #endif // ENABLE_SEAMS_USING_MODELS +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor From 9c8c44e4ddc111548e338e6d9ca78d38f97383a6 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 6 Sep 2021 11:37:59 +0200 Subject: [PATCH 02/27] ENABLE_SEAMS_USING_BATCHED_MODELS - Fixed preview legend update --- src/slic3r/GUI/GCodeViewer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 1e0b9b124..8bf5ba5d8 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3764,7 +3764,11 @@ void GCodeViewer::render_legend(float& legend_height) auto add_option = [this, append_item](EMoveType move_type, EOptionsColors color, const std::string& text) { const TBuffer& buffer = m_buffers[buffer_id(move_type)]; if (buffer.visible && buffer.has_data()) +#if ENABLE_SEAMS_USING_BATCHED_MODELS + append_item(EItemType::Circle, Options_Colors[static_cast(color)], text); +#else append_item((buffer.shader == "options_110") ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast(color)], text); +#endif // ENABLE_SEAMS_USING_BATCHED_MODELS }; // options section From ce0beabb434b80d8db9117a8db3f056e63bd8bd7 Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Fri, 3 Sep 2021 11:56:04 +0200 Subject: [PATCH 03/27] add new mac icon and update MainFrame.cpp --- resources/icons/PrusaSlicer-mac_128px.png | Bin 0 -> 6890 bytes src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 resources/icons/PrusaSlicer-mac_128px.png diff --git a/resources/icons/PrusaSlicer-mac_128px.png b/resources/icons/PrusaSlicer-mac_128px.png new file mode 100644 index 0000000000000000000000000000000000000000..ff0b093beb1d3c6b8cf7e215397a654e03549cde GIT binary patch literal 6890 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 - m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG), "PrusaSlicer"); + m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-mac_128px.png"), wxBITMAP_TYPE_PNG), "PrusaSlicer"); break; case GUI_App::EAppMode::GCodeViewer: m_taskbar_icon = std::make_unique(wxTBI_DOCK); From 07bdb5fbe3df35f18e7c800b136d7da52c2a1fcc Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Fri, 3 Sep 2021 12:08:24 +0200 Subject: [PATCH 04/27] add gcodeviewer --- .../icons/PrusaSlicer-gcodeviewer-mac-128px.png | Bin 0 -> 12218 bytes src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png diff --git a/resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png b/resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png new file mode 100644 index 0000000000000000000000000000000000000000..b62f3fddc84e662f1b011cc19aad7128781cb3ca GIT binary patch literal 12218 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 KAYLVE82BGiN2+}Q literal 0 HcmV?d00001 diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 687333f19..31acc1c57 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -146,7 +146,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S break; case GUI_App::EAppMode::GCodeViewer: m_taskbar_icon = std::make_unique(wxTBI_DOCK); - m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer_128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); + m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer-mac-128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); break; } #endif // __APPLE__ From b41e3214736ad4fdf8789f39db7a8e206a54807b Mon Sep 17 00:00:00 2001 From: Jason Scurtu Date: Fri, 3 Sep 2021 12:09:32 +0200 Subject: [PATCH 05/27] rename --- ...px.png => PrusaSlicer-gcodeviewer-mac_128px.png} | Bin src/slic3r/GUI/MainFrame.cpp | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename resources/icons/{PrusaSlicer-gcodeviewer-mac-128px.png => PrusaSlicer-gcodeviewer-mac_128px.png} (100%) diff --git a/resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png b/resources/icons/PrusaSlicer-gcodeviewer-mac_128px.png similarity index 100% rename from resources/icons/PrusaSlicer-gcodeviewer-mac-128px.png rename to resources/icons/PrusaSlicer-gcodeviewer-mac_128px.png diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 31acc1c57..51dbc201d 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -146,7 +146,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S break; case GUI_App::EAppMode::GCodeViewer: m_taskbar_icon = std::make_unique(wxTBI_DOCK); - m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer-mac-128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); + m_taskbar_icon->SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer-mac_128px.png"), wxBITMAP_TYPE_PNG), "G-code Viewer"); break; } #endif // __APPLE__ From 428509ac00885348cf5455ae1b6eadfd0e96f6ca Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 6 Sep 2021 18:08:13 +0200 Subject: [PATCH 06/27] Pimped up GCodeProcessor::TimeProcessor::post_process(): replaced implicit lambda capture with explicit listing of captured context for readability and code correctness. Captured this as const. --- src/libslic3r/GCode/GCodeProcessor.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index c4f262675..e375179e2 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -476,11 +476,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st g1_times_cache_it.emplace_back(machine.g1_times_cache.begin()); // add lines M73 to exported gcode - auto process_line_G1 = [&]() { + auto process_line_G1 = [ + // Lambdas, mostly for string formatting, all with an empty capture block. + time_in_minutes, format_time_float, format_line_M73_main, format_line_M73_stop_int, format_line_M73_stop_float, time_in_last_minute, + &self = std::as_const(*this), + // Caches, to be modified + &g1_times_cache_it, &last_exported_main, &last_exported_stop, + // String output + &export_line] + (const size_t g1_lines_counter) { unsigned int exported_lines_count = 0; - if (export_remaining_time_enabled) { + if (self.export_remaining_time_enabled) { for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { - const TimeMachine& machine = machines[i]; + const TimeMachine& machine = self.machines[i]; if (machine.enabled) { // export pair // Skip all machine.g1_times_cache below g1_lines_counter. @@ -581,8 +589,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st parser.parse_line(gcode_line, [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) { if (line.cmd_is("G1")) { - unsigned int extra_lines_count = process_line_G1(); - ++g1_lines_counter; + unsigned int extra_lines_count = process_line_G1(g1_lines_counter ++); if (extra_lines_count > 0) offsets.push_back({ line_id, extra_lines_count }); } From 0bc77cef3ec30075b14a01702e3a3877964516a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 7 Sep 2021 07:33:57 +0200 Subject: [PATCH 07/27] Fixed build on Linux and macOS that was failing because of using std::to_chars and std::from_chars with floating-point values. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old version of GCC and Clang support only integers to be passed to std::to_chars and std::from_chars. macOS older version of Clang doesn't support std::from_chars at all. So for Linux and macOS, it was replaced std::from_chars with strtod and temporarily was replace std::to_chars with snprintf. --- src/libslic3r/GCodeReader.cpp | 7 +++++++ src/libslic3r/GCodeWriter.cpp | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp index 54e6802e6..aa5268539 100644 --- a/src/libslic3r/GCodeReader.cpp +++ b/src/libslic3r/GCodeReader.cpp @@ -71,9 +71,16 @@ const char* GCodeReader::parse_line_internal(const char *ptr, const char *end, G } if (axis != NUM_AXES_WITH_UNKNOWN) { // Try to parse the numeric value. +#ifdef WIN32 double v; auto [pend, ec] = std::from_chars(++ c, end, v); if (pend != c && is_end_of_word(*pend)) { +#else + // The older version of GCC and Clang support std::from_chars just for integers, so strtod we used it instead. + char *pend = nullptr; + double v = strtod(++ c, &pend); + if (pend != nullptr && is_end_of_word(*pend)) { +#endif // The axis value has been parsed correctly. if (axis != UNKNOWN_AXIS) gline.m_axis[int(axis)] = float(v); diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 3aecdfd1f..c97180982 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -309,7 +309,16 @@ public: void emit_axis(const char axis, const double v, size_t digits) { *ptr_err.ptr ++ = ' '; *ptr_err.ptr ++ = axis; +#ifdef WIN32 this->ptr_err = std::to_chars(this->ptr_err.ptr, this->buf_end, v, std::chars_format::fixed, digits); +#else + int buf_capacity = int(this->buf_end - this->ptr_err.ptr); + int ret = snprintf(this->ptr_err.ptr, buf_capacity, "%.*lf", int(digits), v); + if (ret <= 0 || ret > buf_capacity) + ptr_err.ec = std::errc::value_too_large; + else + this->ptr_err.ptr = this->ptr_err.ptr + ret; +#endif } void emit_xy(const Vec2d &point) { From d35183921b0696effd194a0cb47cce83020f5efc Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 7 Sep 2021 09:41:14 +0200 Subject: [PATCH 08/27] Revert of 7b4c98d72704a86acc99eb57837fd3bcb941f981, clamp toolpaths widths increased to 2mm and added default values for toolpaths width and height --- src/libslic3r/GCode/GCodeProcessor.cpp | 26 +++++++++++++------------- src/libslic3r/Technologies.hpp | 9 --------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index e375179e2..2c58c2a25 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -21,6 +21,9 @@ #include +static const float DEFAULT_TOOLPATH_WIDTH = 0.4f; +static const float DEFAULT_TOOLPATH_HEIGHT = 0.2f; + static const float INCHES_TO_MM = 25.4f; static const float MMMIN_TO_MMSEC = 1.0f / 60.0f; static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2 @@ -2217,9 +2220,6 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) return; EMoveType type = move_type(delta_pos); - if (type == EMoveType::Extrude && m_end_position[Z] == 0.0f) - type = EMoveType::Travel; - if (type == EMoveType::Extrude) { float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; @@ -2243,6 +2243,12 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) } } + if (m_height == 0.0f) + m_height = DEFAULT_TOOLPATH_HEIGHT; + + if (m_end_position[Z] == 0.0f) + m_end_position[Z] = m_height; + #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_height_compare.update(m_height, m_extrusion_role); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING @@ -2259,23 +2265,17 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) // cross section: rectangle + 2 semicircles m_width = delta_pos[E] * static_cast(M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + static_cast(1.0 - 0.25 * M_PI) * m_height; -#if ENABLE_CLAMP_TOOLPATHS_WIDTH - if (m_producers_enabled && m_producer != EProducer::PrusaSlicer) - // clamp width to avoid artifacts which may arise from wrong values of m_height - m_width = std::min(m_width, std::max(1.0f, 4.0f * m_height)); -#else + if (m_width == 0.0f) + m_width = DEFAULT_TOOLPATH_WIDTH; + // clamp width to avoid artifacts which may arise from wrong values of m_height - m_width = std::min(m_width, std::max(1.0f, 4.0f * m_height)); -#endif // ENABLE_CLAMP_TOOLPATHS_WIDTH + m_width = std::min(m_width, std::max(2.0f, 4.0f * m_height)); #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_width_compare.update(m_width, m_extrusion_role); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING } - if (type == EMoveType::Extrude && (m_width == 0.0f || m_height == 0.0f)) - type = EMoveType::Travel; - // time estimate section auto move_length = [](const AxisCoords& delta_pos) { float sq_xyz_length = sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]); diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 405119fc0..6132430f1 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -57,13 +57,4 @@ #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) -//==================== -// 2.4.0.alpha2 techs -//==================== -#define ENABLE_2_4_0_ALPHA2 1 - -// Enable clamping toolpaths width only for gcodes files produced by 3rd part softwares -#define ENABLE_CLAMP_TOOLPATHS_WIDTH (1 && ENABLE_2_4_0_ALPHA2) - - #endif // _prusaslicer_technologies_h_ From 5c9bc26ed5efee227dad831e89702f331a5891b5 Mon Sep 17 00:00:00 2001 From: Justin Schuh Date: Tue, 7 Sep 2021 00:45:10 -0700 Subject: [PATCH 09/27] Replace OpenProcess with GetCurrentProcess where appropriate (#6914) GetCurrentProcess is more correct and resolves spurious AV warnings. --- src/libslic3r/BlacklistedLibraryCheck.cpp | 11 ++++------- src/libslic3r/utils.cpp | 15 +++++---------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/BlacklistedLibraryCheck.cpp b/src/libslic3r/BlacklistedLibraryCheck.cpp index d9dea188f..76f675c70 100644 --- a/src/libslic3r/BlacklistedLibraryCheck.cpp +++ b/src/libslic3r/BlacklistedLibraryCheck.cpp @@ -33,22 +33,20 @@ std::wstring BlacklistedLibraryCheck::get_blacklisted_string() bool BlacklistedLibraryCheck::perform_check() { - // Get a handle to the process. - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId()); - if (NULL == hProcess) - return false; + // Get the pseudo-handle for the current process. + HANDLE hCurrentProcess = GetCurrentProcess(); // Get a list of all the modules in this process. HMODULE hMods[1024]; DWORD cbNeeded; - if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL)) + if (EnumProcessModulesEx(hCurrentProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL)) { //printf("Total Dlls: %d\n", cbNeeded / sizeof(HMODULE)); for (unsigned int i = 0; i < cbNeeded / sizeof(HMODULE); ++ i) { wchar_t szModName[MAX_PATH]; // Get the full path to the module's file. - if (GetModuleFileNameExW(hProcess, hMods[i], szModName, MAX_PATH)) + if (GetModuleFileNameExW(hCurrentProcess, hMods[i], szModName, MAX_PATH)) { // Add to list if blacklisted if (BlacklistedLibraryCheck::is_blacklisted(szModName)) { @@ -61,7 +59,6 @@ bool BlacklistedLibraryCheck::perform_check() } } - CloseHandle(hProcess); //printf("\n"); return !m_found.empty(); } diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index c330f34b2..c5dbdac9c 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -984,16 +984,11 @@ std::string log_memory_info(bool ignore_loglevel) } PROCESS_MEMORY_COUNTERS_EX, *PPROCESS_MEMORY_COUNTERS_EX; #endif /* PROCESS_MEMORY_COUNTERS_EX */ - - HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId()); - if (hProcess != nullptr) { - PROCESS_MEMORY_COUNTERS_EX pmc; - if (GetProcessMemoryInfo(hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) - out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; - else - out += " Used memory: N/A"; - CloseHandle(hProcess); - } + PROCESS_MEMORY_COUNTERS_EX pmc; + if (GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc))) + out = " WorkingSet: " + format_memsize_MB(pmc.WorkingSetSize) + "; PrivateBytes: " + format_memsize_MB(pmc.PrivateUsage) + "; Pagefile(peak): " + format_memsize_MB(pmc.PagefileUsage) + "(" + format_memsize_MB(pmc.PeakPagefileUsage) + ")"; + else + out += " Used memory: N/A"; #elif defined(__linux__) or defined(__APPLE__) // Get current memory usage. #ifdef __APPLE__ From c1c8a60271083e3577a150b19042c052787a5891 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 7 Sep 2021 11:13:12 +0200 Subject: [PATCH 10/27] Changed color for toolpaths whose extrusion role is unknown --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 8c2ef573f..49fd17ce8 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -503,7 +503,7 @@ void GCodeViewer::SequentialView::render(float legend_height) const } const std::vector GCodeViewer::Extrusion_Role_Colors {{ - { 0.75f, 0.75f, 0.75f, 1.0f }, // erNone + { 0.90f, 0.70f, 0.70f, 1.0f }, // erNone { 1.00f, 0.90f, 0.30f, 1.0f }, // erPerimeter { 1.00f, 0.49f, 0.22f, 1.0f }, // erExternalPerimeter { 0.12f, 0.12f, 1.00f, 1.0f }, // erOverhangPerimeter From 771a8927763f312401fa73b92cb950c31d2fd89b Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 11:18:07 +0200 Subject: [PATCH 11/27] Optimization of GCodeProcessor for speed. --- src/libslic3r/GCode/GCodeProcessor.cpp | 306 +++++++++++++++++-------- src/libslic3r/GCodeReader.cpp | 12 +- src/libslic3r/GCodeReader.hpp | 15 +- 3 files changed, 232 insertions(+), 101 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 2c58c2a25..142dd015d 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -360,7 +360,8 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for writing.\n")); auto time_in_minutes = [](float time_in_seconds) { - return int(::roundf(time_in_seconds / 60.0f)); + assert(time_in_seconds >= 0.f); + return int((time_in_seconds + 0.5f) / 60.0f); }; auto time_in_last_minute = [](float time_in_seconds) { @@ -392,7 +393,6 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st return std::string(line_M73); }; - GCodeReader parser; std::string gcode_line; size_t g1_lines_counter = 0; // keeps track of last exported pair @@ -411,11 +411,12 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st std::string export_line; // replace placeholder lines with the proper final value - auto process_placeholders = [&](const std::string& gcode_line) { + // gcode_line is in/out parameter, to reduce expensive memory allocation + auto process_placeholders = [&](std::string& gcode_line) { unsigned int extra_lines_count = 0; // remove trailing '\n' - std::string line = gcode_line.substr(0, gcode_line.length() - 1); + auto line = std::string_view(gcode_line).substr(0, gcode_line.length() - 1); std::string ret; if (line.length() > 1) { @@ -456,7 +457,10 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st } } - return std::tuple(!ret.empty(), ret.empty() ? gcode_line : ret, (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1); + if (! ret.empty()) + // Not moving the move operator on purpose, so that the gcode_line allocation will grow and it will not be reallocated after handful of lines are processed. + gcode_line = ret; + return std::tuple(!ret.empty(), (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1); }; // check for temporary lines @@ -569,39 +573,56 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st unsigned int line_id = 0; std::vector> offsets; - while (std::getline(in, gcode_line)) { - if (!in.good()) { - fclose(out); - throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n")); - } + { + // Read the input stream 64kB at a time, extract lines and process them. + in.sync_with_stdio(false); + std::vector buffer(65536 * 10, 0); + // Line buffer. + assert(gcode_line.empty()); + while (! in.eof()) { + in.read(buffer.data(), buffer.size()); + if (! in.eof() && ! in.good()) { + fclose(out); + throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n")); + } + auto it = buffer.begin(); + auto it_bufend = buffer.begin() + in.gcount(); + while (it != it_bufend) { + // Find end of line. + bool eol = false; + auto it_end = it; + for (; it_end != it_bufend && ! (eol = *it_end == '\r' || *it_end == '\n'); ++ it_end) ; + // End of line is indicated also if end of file was reached. + eol |= in.eof() && it_end == it_bufend; + gcode_line.insert(gcode_line.end(), it, it_end); + if (eol) { + ++line_id; - ++line_id; - - gcode_line += "\n"; - // replace placeholder lines - auto [processed, result, lines_added_count] = process_placeholders(gcode_line); - if (processed && lines_added_count > 0) - offsets.push_back({ line_id, lines_added_count }); - gcode_line = result; - if (!processed) { - // remove temporary lines - if (is_temporary_decoration(gcode_line)) - continue; - - // add lines M73 where needed - parser.parse_line(gcode_line, - [&](GCodeReader& reader, const GCodeReader::GCodeLine& line) { - if (line.cmd_is("G1")) { + gcode_line += "\n"; + // replace placeholder lines + auto [processed, lines_added_count] = process_placeholders(gcode_line); + if (processed && lines_added_count > 0) + offsets.push_back({ line_id, lines_added_count }); + if (! processed && ! is_temporary_decoration(gcode_line) && GCodeReader::GCodeLine::cmd_is(gcode_line, "G1")) { + // remove temporary lines, add lines M73 where needed unsigned int extra_lines_count = process_line_G1(g1_lines_counter ++); if (extra_lines_count > 0) offsets.push_back({ line_id, extra_lines_count }); } - }); - } - export_line += gcode_line; - if (export_line.length() > 65535) - write_string(export_line); + export_line += gcode_line; + if (export_line.length() > 65535) + write_string(export_line); + gcode_line.clear(); + } + // Skip EOL. + it = it_end; + if (it != it_bufend && *it == '\r') + ++ it; + if (it != it_bufend && *it == '\n') + ++ it; + } + } } if (!export_line.empty()) @@ -1171,8 +1192,6 @@ void GCodeProcessor::reset() void GCodeProcessor::process_file(const std::string& filename, bool apply_postprocess, std::function cancel_callback) { - auto last_cancel_callback_time = std::chrono::high_resolution_clock::now(); - CNumericLocalesSetter locales_setter; #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1184,7 +1203,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr if (m_producers_enabled) { m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { const std::string_view cmd = line.cmd(); - if (cmd.length() == 0) { + if (cmd.empty()) { const std::string_view comment = line.comment(); if (comment.length() > 1 && detect_producer(comment)) m_parser.quit_parsing(); @@ -1211,17 +1230,15 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr m_result.id = ++s_result_id; // 1st move must be a dummy move m_result.moves.emplace_back(MoveVertex()); - m_parser.parse_file(filename, [this, cancel_callback, &last_cancel_callback_time](GCodeReader& reader, const GCodeReader::GCodeLine& line) { - if (cancel_callback != nullptr) { - // call the cancel callback every 100 ms - auto curr_time = std::chrono::high_resolution_clock::now(); - if (std::chrono::duration_cast(curr_time - last_cancel_callback_time).count() > 100) { - cancel_callback(); - last_cancel_callback_time = curr_time; - } + size_t parse_line_callback_cntr = 10000; + m_parser.parse_file(filename, [this, cancel_callback, &parse_line_callback_cntr](GCodeReader& reader, const GCodeReader::GCodeLine& line) { + if (-- parse_line_callback_cntr == 0) { + // Don't call the cancel_callback() too often, do it every at every 10000'th line. + parse_line_callback_cntr = 10000; + cancel_callback(); } - process_gcode_line(line); - }); + this->process_gcode_line(line); + }); // update width/height of wipe moves for (MoveVertex& move : m_result.moves) { @@ -1401,61 +1418,170 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) const std::string_view cmd = line.cmd(); if (cmd.length() > 1) { // process command lines - switch (::toupper(cmd[0])) + switch (cmd[0]) { + case 'g': case 'G': - { - switch (::atoi(&cmd[1])) - { - case 0: { process_G0(line); break; } // Move - case 1: { process_G1(line); break; } // Move - case 10: { process_G10(line); break; } // Retract - case 11: { process_G11(line); break; } // Unretract - case 20: { process_G20(line); break; } // Set Units to Inches - case 21: { process_G21(line); break; } // Set Units to Millimeters - case 22: { process_G22(line); break; } // Firmware controlled retract - case 23: { process_G23(line); break; } // Firmware controlled unretract - case 28: { process_G28(line); break; } // Move to origin - case 90: { process_G90(line); break; } // Set to Absolute Positioning - case 91: { process_G91(line); break; } // Set to Relative Positioning - case 92: { process_G92(line); break; } // Set Position - default: { break; } + switch (cmd.size()) { + case 2: + switch (cmd[1]) { + case '0': { process_G0(line); break; } // Move + case '1': { process_G1(line); break; } // Move + default: break; } break; + case 3: + switch (cmd[1]) { + case '1': + switch (cmd[2]) { + case '0': { process_G10(line); break; } // Retract + case '1': { process_G11(line); break; } // Unretract + default: break; + } + break; + case '2': + switch (cmd[2]) { + case '0': { process_G20(line); break; } // Set Units to Inches + case '1': { process_G21(line); break; } // Set Units to Millimeters + case '2': { process_G22(line); break; } // Firmware controlled retract + case '3': { process_G23(line); break; } // Firmware controlled unretract + case '8': { process_G28(line); break; } // Move to origin + default: break; + } + break; + case '9': + switch (cmd[2]) { + case '0': { process_G90(line); break; } // Set to Absolute Positioning + case '1': { process_G91(line); break; } // Set to Relative Positioning + case '2': { process_G92(line); break; } // Set Position + default: break; + } + break; + } + break; + default: + break; } + break; + case 'm': case 'M': - { - switch (::atoi(&cmd[1])) - { - case 1: { process_M1(line); break; } // Sleep or Conditional stop - case 82: { process_M82(line); break; } // Set extruder to absolute mode - case 83: { process_M83(line); break; } // Set extruder to relative mode - case 104: { process_M104(line); break; } // Set extruder temperature - case 106: { process_M106(line); break; } // Set fan speed - case 107: { process_M107(line); break; } // Disable fan - case 108: { process_M108(line); break; } // Set tool (Sailfish) - case 109: { process_M109(line); break; } // Set extruder temperature and wait - case 132: { process_M132(line); break; } // Recall stored home offsets - case 135: { process_M135(line); break; } // Set tool (MakerWare) - case 201: { process_M201(line); break; } // Set max printing acceleration - case 203: { process_M203(line); break; } // Set maximum feedrate - case 204: { process_M204(line); break; } // Set default acceleration - case 205: { process_M205(line); break; } // Advanced settings - case 221: { process_M221(line); break; } // Set extrude factor override percentage - case 401: { process_M401(line); break; } // Repetier: Store x, y and z position - case 402: { process_M402(line); break; } // Repetier: Go to stored position - case 566: { process_M566(line); break; } // Set allowable instantaneous speed change - case 702: { process_M702(line); break; } // Unload the current filament into the MK3 MMU2 unit at the end of print. - default: { break; } + switch (cmd.size()) { + case 2: + switch (cmd[1]) { + case '1': { process_M1(line); break; } // Sleep or Conditional stop + default: break; } break; - } - case 'T': - { - process_T(line); // Select Tool + case 3: + switch (cmd[1]) { + case '8': + switch (cmd[2]) { + case '2': { process_M82(line); break; } // Set extruder to absolute mode + case '3': { process_M83(line); break; } // Set extruder to relative mode + default: break; + } + break; + default: + break; + } + break; + case 4: + switch (cmd[1]) { + case '1': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '4': { process_M104(line); break; } // Set extruder temperature + case '6': { process_M106(line); break; } // Set fan speed + case '7': { process_M107(line); break; } // Disable fan + case '8': { process_M108(line); break; } // Set tool (Sailfish) + case '9': { process_M109(line); break; } // Set extruder temperature and wait + default: break; + } + break; + case '3': + switch (cmd[3]) { + case '2': { process_M132(line); break; } // Recall stored home offsets + case '5': { process_M135(line); break; } // Set tool (MakerWare) + default: break; + } + break; + default: + break; + } + break; + case '2': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '1': { process_M201(line); break; } // Set max printing acceleration + case '3': { process_M203(line); break; } // Set maximum feedrate + case '4': { process_M204(line); break; } // Set default acceleration + case '5': { process_M205(line); break; } // Advanced settings + default: break; + } + break; + case '2': + switch (cmd[3]) { + case '1': { process_M221(line); break; } // Set extrude factor override percentage + default: break; + } + break; + default: + break; + } + break; + case '4': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '1': { process_M401(line); break; } // Repetier: Store x, y and z position + case '2': { process_M402(line); break; } // Repetier: Go to stored position + default: break; + } + break; + default: + break; + } + break; + case '5': + switch (cmd[2]) { + case '6': + switch (cmd[3]) { + case '6': { process_M566(line); break; } // Set allowable instantaneous speed change + default: break; + } + break; + default: + break; + } + break; + case '7': + switch (cmd[2]) { + case '0': + switch (cmd[3]) { + case '2': { process_M702(line); break; } // Unload the current filament into the MK3 MMU2 unit at the end of print. + default: break; + } + break; + default: + break; + } + break; + default: + break; + } + break; + default: break; } - default: { break; } + break; + case 't': + case 'T': + process_T(line); // Select Tool + break; + default: + break; } } else { diff --git a/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp index aa5268539..4c4bebee4 100644 --- a/src/libslic3r/GCodeReader.cpp +++ b/src/libslic3r/GCodeReader.cpp @@ -133,7 +133,7 @@ void GCodeReader::update_coordinates(GCodeLine &gline, std::pairhas(Y) ? (this->y() - reader.y()) : 0; return sqrt(x*x + y*y); } - bool cmd_is(const char *cmd_test) const { - const char *cmd = GCodeReader::skip_whitespaces(m_raw.c_str()); - size_t len = strlen(cmd_test); - return strncmp(cmd, cmd_test, len) == 0 && GCodeReader::is_end_of_word(cmd[len]); - } + bool cmd_is(const char *cmd_test) const { return cmd_is(m_raw, cmd_test); } bool extruding(const GCodeReader &reader) const { return this->cmd_is("G1") && this->dist_E(reader) > 0; } bool retracting(const GCodeReader &reader) const { return this->cmd_is("G1") && this->dist_E(reader) < 0; } bool travel() const { return this->cmd_is("G1") && ! this->has(E); } @@ -66,6 +62,12 @@ public: float e() const { return m_axis[E]; } float f() const { return m_axis[F]; } + static bool cmd_is(const std::string &gcode_line, const char *cmd_test) { + const char *cmd = GCodeReader::skip_whitespaces(gcode_line.c_str()); + size_t len = strlen(cmd_test); + return strncmp(cmd, cmd_test, len) == 0 && GCodeReader::is_end_of_word(cmd[len]); + } + private: std::string m_raw; float m_axis[NUM_AXES]; @@ -109,7 +111,8 @@ public: void parse_line(const std::string &line, Callback callback) { GCodeLine gline; this->parse_line(line.c_str(), line.c_str() + line.size(), gline, callback); } - void parse_file(const std::string &file, callback_t callback); + // Returns false if reading the file failed. + bool parse_file(const std::string &file, callback_t callback); void quit_parsing() { m_parsing = false; } float& x() { return m_position[X]; } From af20419ed4997bc08f419b13dead78eb905a10b3 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 7 Sep 2021 11:18:58 +0200 Subject: [PATCH 12/27] Fix for #6903 - Compare presets window titles inaccurate... --- src/slic3r/GUI/UnsavedChangesDialog.cpp | 16 +++++++++++----- src/slic3r/GUI/UnsavedChangesDialog.hpp | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp index 2b63bc79b..ef480f60f 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.cpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp @@ -696,7 +696,12 @@ void DiffViewCtrl::context_menu(wxDataViewEvent& event) auto it = m_items_map.find(item); if (it == m_items_map.end() || !it->second.is_long) return; - FullCompareDialog(it->second.opt_name, it->second.old_val, it->second.new_val).ShowModal(); + + size_t column_cnt = this->GetColumnCount(); + const wxString old_value_header = this->GetColumn(column_cnt - 2)->GetTitle(); + const wxString new_value_header = this->GetColumn(column_cnt - 1)->GetTitle(); + FullCompareDialog(it->second.opt_name, it->second.old_val, it->second.new_val, + old_value_header, new_value_header).ShowModal(); #ifdef __WXOSX__ wxWindow* parent = this->GetParent(); @@ -1281,7 +1286,8 @@ void UnsavedChangesDialog::on_sys_color_changed() // FullCompareDialog //------------------------------------------ -FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value) +FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value, + const wxString& old_value_header, const wxString& new_value_header) : wxDialog(nullptr, wxID_ANY, option_name, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxGetApp().UpdateDarkUI(this); @@ -1302,8 +1308,8 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString grid_sizer->Add(text, 0, wxALL, border); }; - add_header(_L("Old value")); - add_header(_L("New value")); + add_header(old_value_header); + add_header(new_value_header); auto get_set_from_val = [](wxString str) { if (str.Find("\n") == wxNOT_FOUND) @@ -1327,7 +1333,7 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString std::set_difference(new_set.begin(), new_set.end(), old_set.begin(), old_set.end(), std::inserter(new_old_diff_set, new_old_diff_set.begin())); auto add_value = [grid_sizer, border, this](wxString label, const std::set& diff_set, bool is_colored = false) { - wxTextCtrl* text = new wxTextCtrl(this, wxID_ANY, label, wxDefaultPosition, wxSize(400, 400), wxTE_MULTILINE | wxTE_READONLY | wxBORDER_SIMPLE | wxTE_RICH); + wxTextCtrl* text = new wxTextCtrl(this, wxID_ANY, label, wxDefaultPosition, wxSize(400, 400), wxTE_MULTILINE | wxTE_READONLY | wxBORDER_DEFAULT | wxTE_RICH); wxGetApp().UpdateDarkUI(text); text->SetStyle(0, label.Len(), wxTextAttr(is_colored ? wxColour(orange) : wxNullColour, wxNullColour, this->GetFont())); diff --git a/src/slic3r/GUI/UnsavedChangesDialog.hpp b/src/slic3r/GUI/UnsavedChangesDialog.hpp index 966743033..9dbaf6e99 100644 --- a/src/slic3r/GUI/UnsavedChangesDialog.hpp +++ b/src/slic3r/GUI/UnsavedChangesDialog.hpp @@ -299,7 +299,8 @@ protected: class FullCompareDialog : public wxDialog { public: - FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value); + FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& new_value, + const wxString& old_value_header, const wxString& new_value_header); ~FullCompareDialog() {} }; From 761c06ed9282c76475ab9986cd0cd0a5c340022d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 7 Sep 2021 12:25:30 +0200 Subject: [PATCH 13/27] GCodeViewer - Fixed crash when importing gcode generated with Simplify3D and switching to tool view --- src/libslic3r/GCode/GCodeProcessor.cpp | 13 +++++++++---- src/slic3r/GUI/GCodeViewer.cpp | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 2c58c2a25..4b38020c1 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -961,10 +961,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config) } // replace missing values with default - std::string default_color = "#FF8000"; for (size_t i = 0; i < m_result.extruder_colors.size(); ++i) { if (m_result.extruder_colors[i].empty()) - m_result.extruder_colors[i] = default_color; + m_result.extruder_colors[i] = "#FF8000"; } m_extruder_colors.resize(m_result.extruder_colors.size()); @@ -1350,7 +1349,7 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename) if (pos != cmt.npos) { std::string data_str = cmt.substr(pos + 1); std::vector values_str; - boost::split(values_str, data_str, boost::is_any_of("|"), boost::token_compress_on); + boost::split(values_str, data_str, boost::is_any_of("|,"), boost::token_compress_on); for (const std::string& s : values_str) { out.emplace_back(static_cast(string_to_double_decimal_point(s))); } @@ -1374,10 +1373,16 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename) m_result.filament_densities.clear(); extract_floats(comment, "filamentDensities", m_result.filament_densities); } + else if (comment.find("extruderDiameter") != comment.npos) { + std::vector extruder_diameters; + extract_floats(comment, "extruderDiameter", extruder_diameters); + m_result.extruders_count = extruder_diameters.size(); + } } }); - m_result.extruders_count = std::max(1, std::min(m_result.filament_diameters.size(), m_result.filament_densities.size())); + if (m_result.extruders_count == 0) + m_result.extruders_count = std::max(1, std::min(m_result.filament_diameters.size(), m_result.filament_densities.size())); if (bed_size.is_defined()) { m_result.bed_shape = { diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 49fd17ce8..979214fb5 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -695,8 +695,8 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std: // update tool colors m_tool_colors = decode_colors(str_tool_colors); - // ensure at least one (default) color is defined - if (m_tool_colors.empty()) + // ensure there are enough colors defined + while (m_tool_colors.size() < std::max(size_t(1), gcode_result.extruders_count)) m_tool_colors.push_back(decode_color("#FF8000")); // update ranges for coloring / legend From e30ff22b8a2d586abb3b023519b40f715c44e1ad Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 14:20:16 +0200 Subject: [PATCH 14/27] GCodePostProcessor - use C files instead of C++ streams, C files are faster. Also fixed a regression - crashes on undefined cancellation callback. --- src/libslic3r/GCode/GCodeProcessor.cpp | 48 +++++++++++++++----------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index f7709e9d6..aa6912fc4 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -347,17 +347,25 @@ void GCodeProcessor::TimeProcessor::reset() machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].enabled = true; } +struct FilePtr { + FilePtr(FILE *f) : f(f) {} + ~FilePtr() { this->close(); } + void close() { if (f) ::fclose(f); } + FILE* f = nullptr; +}; + void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves) { - boost::nowide::ifstream in(filename); - if (!in.good()) + FilePtr in{ boost::nowide::fopen(filename.c_str(), "rb") }; + if (in.f == nullptr) throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for reading.\n")); // temporary file to contain modified gcode std::string out_path = filename + ".postprocess"; - FILE* out = boost::nowide::fopen(out_path.c_str(), "wb"); - if (out == nullptr) + FilePtr out{ boost::nowide::fopen(out_path.c_str(), "wb") }; + if (out.f == nullptr) { throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for writing.\n")); + } auto time_in_minutes = [](float time_in_seconds) { assert(time_in_seconds >= 0.f); @@ -559,11 +567,10 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st }; // helper function to write to disk - auto write_string = [&](const std::string& str) { - fwrite((const void*)export_line.c_str(), 1, export_line.length(), out); - if (ferror(out)) { - in.close(); - fclose(out); + auto write_string = [&export_line, &out, &out_path](const std::string& str) { + fwrite((const void*)export_line.c_str(), 1, export_line.length(), out.f); + if (ferror(out.f)) { + out.close(); boost::nowide::remove(out_path.c_str()); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nIs the disk full?\n")); } @@ -575,25 +582,23 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st { // Read the input stream 64kB at a time, extract lines and process them. - in.sync_with_stdio(false); std::vector buffer(65536 * 10, 0); // Line buffer. assert(gcode_line.empty()); - while (! in.eof()) { - in.read(buffer.data(), buffer.size()); - if (! in.eof() && ! in.good()) { - fclose(out); + for (;;) { + size_t cnt_read = ::fread(buffer.data(), 1, buffer.size(), in.f); + if (::ferror(in.f)) throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n")); - } + bool eof = cnt_read == 0; auto it = buffer.begin(); - auto it_bufend = buffer.begin() + in.gcount(); - while (it != it_bufend) { + auto it_bufend = buffer.begin() + cnt_read; + while (it != it_bufend || (eof && ! gcode_line.empty())) { // Find end of line. bool eol = false; auto it_end = it; for (; it_end != it_bufend && ! (eol = *it_end == '\r' || *it_end == '\n'); ++ it_end) ; // End of line is indicated also if end of file was reached. - eol |= in.eof() && it_end == it_bufend; + eol |= eof && it_end == it_bufend; gcode_line.insert(gcode_line.end(), it, it_end); if (eol) { ++line_id; @@ -622,13 +627,15 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st if (it != it_bufend && *it == '\n') ++ it; } + if (eof) + break; } } if (!export_line.empty()) write_string(export_line); - fclose(out); + out.close(); in.close(); // updates moves' gcode ids which have been modified by the insertion of the M73 lines @@ -1234,7 +1241,8 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr if (-- parse_line_callback_cntr == 0) { // Don't call the cancel_callback() too often, do it every at every 10000'th line. parse_line_callback_cntr = 10000; - cancel_callback(); + if (cancel_callback) + cancel_callback(); } this->process_gcode_line(line); }); From 719c91514bd71cf04d4abec70a958fd3710f5f01 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 7 Sep 2021 15:19:59 +0200 Subject: [PATCH 15/27] ObjectList:: Allow use BACKSPACE to delete selected items --- src/slic3r/GUI/GUI_ObjectList.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index c99d9090c..bf174cbf1 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1044,13 +1044,8 @@ void ObjectList::key_event(wxKeyEvent& event) { if (event.GetKeyCode() == WXK_TAB) Navigate(event.ShiftDown() ? wxNavigationKeyEvent::IsBackward : wxNavigationKeyEvent::IsForward); - else if (event.GetKeyCode() == WXK_DELETE -#ifdef __WXOSX__ - || event.GetKeyCode() == WXK_BACK -#endif //__WXOSX__ - ) { + else if (event.GetKeyCode() == WXK_DELETE || event.GetKeyCode() == WXK_BACK ) remove(); - } else if (event.GetKeyCode() == WXK_F5) wxGetApp().plater()->reload_all_from_disk(); else if (wxGetKeyState(wxKeyCode('A')) && wxGetKeyState(WXK_CONTROL/*WXK_SHIFT*/)) From 32733b7db943ccf823a27f9fca83a17c8aaae350 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 15:42:50 +0200 Subject: [PATCH 16/27] GCodeProcessor collects positions of line ends for GCodeViewer, GCodeViewer no more parses G-code just to extract line end positions. Removed start_mapping_gcode_window(), void stop_mapping_gcode_window(), they are no more needed. --- src/libslic3r/GCode/GCodeProcessor.cpp | 16 ++++-- src/libslic3r/GCode/GCodeProcessor.hpp | 4 +- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 5 +- src/slic3r/GUI/GCodeViewer.cpp | 62 ++++----------------- src/slic3r/GUI/GCodeViewer.hpp | 9 +-- src/slic3r/GUI/GLCanvas3D.cpp | 10 ---- src/slic3r/GUI/GLCanvas3D.hpp | 3 - src/slic3r/GUI/Plater.cpp | 10 ---- src/slic3r/GUI/Plater.hpp | 3 - 9 files changed, 30 insertions(+), 92 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index aa6912fc4..ec586dbef 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -354,7 +354,7 @@ struct FilePtr { FILE* f = nullptr; }; -void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves) +void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends) { FilePtr in{ boost::nowide::fopen(filename.c_str(), "rb") }; if (in.f == nullptr) @@ -567,13 +567,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st }; // helper function to write to disk - auto write_string = [&export_line, &out, &out_path](const std::string& str) { + size_t out_file_pos = 0; + lines_ends.clear(); + auto write_string = [&export_line, &out, &out_path, &out_file_pos, &lines_ends](const std::string& str) { fwrite((const void*)export_line.c_str(), 1, export_line.length(), out.f); if (ferror(out.f)) { out.close(); boost::nowide::remove(out_path.c_str()); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nIs the disk full?\n")); } + for (size_t i = 0; i < export_line.size(); ++ i) + if (export_line[i] == '\n') + lines_ends.emplace_back(out_file_pos + i + 1); + out_file_pos += export_line.size(); export_line.clear(); }; @@ -736,7 +742,9 @@ void GCodeProcessor::Result::reset() { } #else void GCodeProcessor::Result::reset() { - moves = std::vector(); + + moves.clear(); + lines_ends.clear(); bed_shape = Pointfs(); settings_ids.reset(); extruders_count = 0; @@ -1270,7 +1278,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr // post-process to add M73 lines into the gcode if (apply_postprocess) - m_time_processor.post_process(filename, m_result.moves); + m_time_processor.post_process(filename, m_result.moves, m_result.lines_ends); #if ENABLE_GCODE_VIEWER_DATA_CHECKING std::cout << "\n"; diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 4fcdd8df3..bb9310888 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -306,7 +306,7 @@ namespace Slic3r { // post process the file with the given filename to add remaining time lines M73 // and updates moves' gcode ids accordingly - void post_process(const std::string& filename, std::vector& moves); + void post_process(const std::string& filename, std::vector& moves, std::vector& lines_ends); }; struct UsedFilaments // filaments per ColorChange @@ -350,6 +350,8 @@ namespace Slic3r { std::string filename; unsigned int id; std::vector moves; + // Positions of ends of lines of the final G-code this->filename after TimeProcessor::post_process() finalizes the G-code. + std::vector lines_ends; Pointfs bed_shape; SettingsIds settings_ids; size_t extruders_count; diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 8a58e5ec9..b4de4a509 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -574,11 +574,8 @@ Print::ApplyStatus BackgroundSlicingProcess::apply(const Model &model, const Dyn // Some FFF status was invalidated, and the G-code was not exported yet. // Let the G-code preview UI know that the final G-code preview is not valid. // In addition, this early memory deallocation reduces memory footprint. - if (m_gcode_result != nullptr) { - //FIXME calling platter from here is not a staple of a good architecture. - GUI::wxGetApp().plater()->stop_mapping_gcode_window(); + if (m_gcode_result != nullptr) m_gcode_result->reset(); - } } return invalidated; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 979214fb5..946cbb275 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -284,45 +284,14 @@ void GCodeViewer::SequentialView::Marker::render() const ImGui::PopStyleVar(); } -void GCodeViewer::SequentialView::GCodeWindow::load_gcode() +void GCodeViewer::SequentialView::GCodeWindow::load_gcode(const std::string& filename, const std::vector &lines_ends) { - if (m_filename.empty()) - return; - + assert(! m_file.is_open()); if (m_file.is_open()) return; - try - { - // generate mapping for accessing data in file by line number - boost::nowide::ifstream f(m_filename); - - f.seekg(0, f.end); - uint64_t file_length = static_cast(f.tellg()); - f.seekg(0, f.beg); - - std::string line; - uint64_t offset = 0; - while (std::getline(f, line)) { - uint64_t line_length = static_cast(line.length()); - m_lines_map.push_back({ offset, line_length }); - offset += static_cast(line_length) + 1; - } - - if (offset != file_length) { - // if the final offset does not match with file length, lines are terminated with CR+LF - // so update all offsets accordingly - for (size_t i = 0; i < m_lines_map.size(); ++i) { - m_lines_map[i].first += static_cast(i); - } - } - } - catch (...) - { - BOOST_LOG_TRIVIAL(error) << "Unable to load data from " << m_filename << ". Cannot show G-code window."; - reset(); - return; - } + m_filename = filename; + m_lines_ends = std::move(lines_ends); m_selected_line_id = 0; m_last_lines_size = 0; @@ -345,7 +314,9 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u ret.reserve(end_id - start_id + 1); for (uint64_t id = start_id; id <= end_id; ++id) { // read line from file - std::string gline(m_file.data() + m_lines_map[id - 1].first, m_lines_map[id - 1].second); + const size_t start = id == 1 ? 0 : m_lines_ends[id - 2]; + const size_t len = m_lines_ends[id - 1] - start; + std::string gline(m_file.data() + start, len); std::string command; std::string parameters; @@ -379,7 +350,7 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u static const ImVec4 PARAMETERS_COLOR = { 1.0f, 1.0f, 1.0f, 1.0f }; static const ImVec4 COMMENT_COLOR = { 0.7f, 0.7f, 0.7f, 1.0f }; - if (!m_visible || m_filename.empty() || m_lines_map.empty() || curr_line_id == 0) + if (!m_visible || m_filename.empty() || m_lines_ends.empty() || curr_line_id == 0) return; // window height @@ -397,8 +368,8 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, u const uint64_t half_lines_count = lines_count / 2; uint64_t start_id = (curr_line_id >= half_lines_count) ? curr_line_id - half_lines_count : 0; uint64_t end_id = start_id + lines_count - 1; - if (end_id >= static_cast(m_lines_map.size())) { - end_id = static_cast(m_lines_map.size()) - 1; + if (end_id >= static_cast(m_lines_ends.size())) { + end_id = static_cast(m_lines_ends.size()) - 1; start_id = end_id - lines_count + 1; } @@ -606,8 +577,7 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& // release gpu memory, if used reset(); - m_sequential_view.gcode_window.set_filename(gcode_result.filename); - m_sequential_view.gcode_window.load_gcode(); + m_sequential_view.gcode_window.load_gcode(gcode_result.filename, gcode_result.lines_ends); #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER if (wxGetApp().is_gcode_viewer()) @@ -1146,16 +1116,6 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const fclose(fp); } -void GCodeViewer::start_mapping_gcode_window() -{ - m_sequential_view.gcode_window.load_gcode(); -} - -void GCodeViewer::stop_mapping_gcode_window() -{ - m_sequential_view.gcode_window.stop_mapping_file(); -} - void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) { // max index buffer size, in bytes diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 429175fe6..b918dee23 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -639,18 +639,17 @@ public: std::string m_filename; boost::iostreams::mapped_file_source m_file; // map for accessing data in file by line number - std::vector> m_lines_map; + std::vector m_lines_ends; // current visible lines std::vector m_lines; public: GCodeWindow() = default; ~GCodeWindow() { stop_mapping_file(); } - void set_filename(const std::string& filename) { m_filename = filename; } - void load_gcode(); + void load_gcode(const std::string& filename, const std::vector &lines_ends); void reset() { stop_mapping_file(); - m_lines_map.clear(); + m_lines_ends.clear(); m_lines.clear(); m_filename.clear(); } @@ -777,8 +776,6 @@ public: void export_toolpaths_to_obj(const char* filename) const; - void start_mapping_gcode_window(); - void stop_mapping_gcode_window(); void toggle_gcode_window_visibility() { m_sequential_view.gcode_window.toggle_visibility(); } #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e28189220..f50c7fe25 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1114,16 +1114,6 @@ int GLCanvas3D::check_volumes_outside_state() const return (int)state; } -void GLCanvas3D::start_mapping_gcode_window() -{ - m_gcode_viewer.start_mapping_gcode_window(); -} - -void GLCanvas3D::stop_mapping_gcode_window() -{ - m_gcode_viewer.stop_mapping_gcode_window(); -} - void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx) { m_render_sla_auxiliaries = visible; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 3750e3a3e..799fa11c7 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -621,9 +621,6 @@ public: const GCodeViewer::SequentialView& get_gcode_sequential_view() const { return m_gcode_viewer.get_sequential_view(); } void update_gcode_sequential_view_current(unsigned int first, unsigned int last) { m_gcode_viewer.update_sequential_view_current(first, last); } - void start_mapping_gcode_window(); - void stop_mapping_gcode_window(); - void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void update_instance_printable_state_for_object(size_t obj_idx); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index af8734184..2c77dcb7a 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6143,16 +6143,6 @@ BoundingBoxf Plater::bed_shape_bb() const return p->bed_shape_bb(); } -void Plater::start_mapping_gcode_window() -{ - p->preview->get_canvas3d()->start_mapping_gcode_window(); -} - -void Plater::stop_mapping_gcode_window() -{ - p->preview->get_canvas3d()->stop_mapping_gcode_window(); -} - void Plater::arrange() { p->m_ui_jobs.arrange(); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 99f7e3cda..f1a493b0f 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -282,9 +282,6 @@ public: GLCanvas3D* get_current_canvas3D(); BoundingBoxf bed_shape_bb() const; - void start_mapping_gcode_window(); - void stop_mapping_gcode_window(); - void arrange(); void find_new_position(const ModelInstancePtrs &instances); From b5a007a683124ec3b01b61e892ed8eb39c034248 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 16:23:43 +0200 Subject: [PATCH 17/27] WIP to G-code export parallelization through pipelining: New class GCodeOutputStream as a G-code consumer. In the following steps the GCodeOutputStream will be pipelined with GCodeProcessor. --- src/libslic3r/GCode.cpp | 152 ++++++++++++++++++++-------------------- src/libslic3r/GCode.hpp | 48 ++++++++----- 2 files changed, 107 insertions(+), 93 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 19909b2bc..54815188e 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -744,27 +744,27 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re std::string path_tmp(path); path_tmp += ".tmp"; - FILE *file = boost::nowide::fopen(path_tmp.c_str(), "wb"); - if (file == nullptr) + GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb")); + if (! file.is_open()) throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); try { m_placeholder_parser_failed_templates.clear(); this->_do_export(*print, file, thumbnail_cb); - fflush(file); - if (ferror(file)) { - fclose(file); + file.flush(); + if (file.is_error()) { + file.close(); boost::nowide::remove(path_tmp.c_str()); throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed\nIs the disk full?\n"); } } catch (std::exception & /* ex */) { // Rethrow on any exception. std::runtime_exception and CanceledException are expected to be thrown. // Close and remove the file. - fclose(file); + file.close(); boost::nowide::remove(path_tmp.c_str()); throw; } - fclose(file); + file.close(); if (! m_placeholder_parser_failed_templates.empty()) { // G-code export proceeded, but some of the PlaceholderParser substitutions failed. @@ -1046,7 +1046,7 @@ std::vector sort_object_instances_by_model_order(const Pri return instances; } -void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thumbnail_cb) +void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb) { PROFILE_FUNC(); @@ -1111,10 +1111,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu #endif /* HAS_PRESSURE_EQUALIZER */ // Write information on the generator. - _write_format(file, "; %s\n\n", Slic3r::header_slic3r_generated().c_str()); + file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str()); DoExport::export_thumbnails_to_file(thumbnail_cb, print.full_print_config().option("thumbnails")->values, - [this, file](const char* sz) { this->_write(file, sz); }, + [&file](const char* sz) { file.write(sz); }, [&print]() { print.throw_if_canceled(); }); // Write notes (content of the Print Settings tab -> Notes) @@ -1125,10 +1125,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Remove the trailing '\r' from the '\r\n' sequence. if (! line.empty() && line.back() == '\r') line.pop_back(); - _write_format(file, "; %s\n", line.c_str()); + file.write_format("; %s\n", line.c_str()); } if (! lines.empty()) - _write(file, "\n"); + file.write("\n"); } print.throw_if_canceled(); @@ -1139,22 +1139,22 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu const double first_layer_height = print.config().first_layer_height.value; for (size_t region_id = 0; region_id < print.num_print_regions(); ++ region_id) { const PrintRegion ®ion = print.get_print_region(region_id); - _write_format(file, "; external perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frExternalPerimeter, layer_height).width()); - _write_format(file, "; perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, layer_height).width()); - _write_format(file, "; infill extrusion width = %.2fmm\n", region.flow(*first_object, frInfill, layer_height).width()); - _write_format(file, "; solid infill extrusion width = %.2fmm\n", region.flow(*first_object, frSolidInfill, layer_height).width()); - _write_format(file, "; top infill extrusion width = %.2fmm\n", region.flow(*first_object, frTopSolidInfill, layer_height).width()); + file.write_format("; external perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frExternalPerimeter, layer_height).width()); + file.write_format("; perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, layer_height).width()); + file.write_format("; infill extrusion width = %.2fmm\n", region.flow(*first_object, frInfill, layer_height).width()); + file.write_format("; solid infill extrusion width = %.2fmm\n", region.flow(*first_object, frSolidInfill, layer_height).width()); + file.write_format("; top infill extrusion width = %.2fmm\n", region.flow(*first_object, frTopSolidInfill, layer_height).width()); if (print.has_support_material()) - _write_format(file, "; support material extrusion width = %.2fmm\n", support_material_flow(first_object).width()); + file.write_format("; support material extrusion width = %.2fmm\n", support_material_flow(first_object).width()); if (print.config().first_layer_extrusion_width.value > 0) - _write_format(file, "; first layer extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, first_layer_height, true).width()); - _write_format(file, "\n"); + file.write_format("; first layer extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, first_layer_height, true).width()); + file.write_format("\n"); } print.throw_if_canceled(); // adds tags for time estimators if (print.config().remaining_times.value) - _write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str()); + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str()); // Prepare the helper object for replacing placeholders in custom G-code and output filename. m_placeholder_parser = print.placeholder_parser(); @@ -1218,7 +1218,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Disable fan. if (! print.config().cooling.get_at(initial_extruder_id) || print.config().disable_fan_first_layers.get_at(initial_extruder_id)) - _write(file, m_writer.set_fan(0, true)); + file.write(m_writer.set_fan(0, true)); // Let the start-up script prime the 1st printing tool. m_placeholder_parser.set("initial_tool", initial_extruder_id); @@ -1261,10 +1261,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false); // adds tag for processor - _write_format(file, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); + file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); // Write the custom start G-code - _writeln(file, start_gcode); + file.writeln(start_gcode); // Process filament-specific gcode. /* if (has_wipe_tower) { @@ -1272,14 +1272,14 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu } else { DynamicConfig config; config.set_key_value("filament_extruder_id", new ConfigOptionInt(int(initial_extruder_id))); - _writeln(file, this->placeholder_parser_process("start_filament_gcode", print.config().start_filament_gcode.values[initial_extruder_id], initial_extruder_id, &config)); + file.writeln(this->placeholder_parser_process("start_filament_gcode", print.config().start_filament_gcode.values[initial_extruder_id], initial_extruder_id, &config)); } */ this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true); print.throw_if_canceled(); // Set other general things. - _write(file, this->preamble()); + file.write(this->preamble()); // Calculate wiping points if needed DoExport::init_ooze_prevention(print, m_ooze_prevention); @@ -1291,7 +1291,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu if (! (has_wipe_tower && print.config().single_extruder_multi_material_priming)) { // Set initial extruder only after custom start G-code. // Ugly hack: Do not set the initial extruder if the extruder is primed using the MMU priming towers at the edge of the print bed. - _write(file, this->set_extruder(initial_extruder_id, 0.)); + file.write(this->set_extruder(initial_extruder_id, 0.)); } // Do all objects for each layer. @@ -1317,8 +1317,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // This happens before Z goes down to layer 0 again, so that no collision happens hopefully. m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer m_avoid_crossing_perimeters.use_external_mp_once(); - _write(file, this->retract()); - _write(file, this->travel_to(Point(0, 0), erNone, "move to origin position for next object")); + file.write(this->retract()); + file.write(this->travel_to(Point(0, 0), erNone, "move to origin position for next object")); m_enable_cooling_markers = true; // Disable motion planner when traveling to first object point. m_avoid_crossing_perimeters.disable_once(); @@ -1330,7 +1330,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Set first layer bed and extruder temperatures, don't wait for it to reach the temperature. this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false); this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false); - _writeln(file, between_objects_gcode); + file.writeln(between_objects_gcode); } // Reset the cooling buffer internal state (the current position, feed rate, accelerations). m_cooling_buffer->reset(); @@ -1346,7 +1346,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu } #ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) - _write(file, m_pressure_equalizer->process("", true)); + file.write(m_pressure_equalizer->process("", true)); #endif /* HAS_PRESSURE_EQUALIZER */ ++ finished_objects; // Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed. @@ -1361,9 +1361,9 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Prusa Multi-Material wipe tower. if (has_wipe_tower && ! layers_to_print.empty()) { m_wipe_tower.reset(new WipeTowerIntegration(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get())); - _write(file, m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height")); + file.write(m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height")); if (print.config().single_extruder_multi_material_priming) { - _write(file, m_wipe_tower->prime(*this)); + file.write(m_wipe_tower->prime(*this)); // Verify, whether the print overaps the priming extrusions. BoundingBoxf bbox_print(get_print_extrusions_extents(print)); coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON; @@ -1375,15 +1375,15 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu bool overlap = bbox_prime.overlap(bbox_print); if (print.config().gcode_flavor == gcfMarlinLegacy || print.config().gcode_flavor == gcfMarlinFirmware) { - _write(file, this->retract()); - _write(file, "M300 S800 P500\n"); // Beep for 500ms, tone 800Hz. + file.write(this->retract()); + file.write("M300 S800 P500\n"); // Beep for 500ms, tone 800Hz. if (overlap) { // Wait for the user to remove the priming extrusions. - _write(file, "M1 Remove priming towers and click button.\n"); + file.write("M1 Remove priming towers and click button.\n"); } else { // Just wait for a bit to let the user check, that the priming succeeded. //TODO Add a message explaining what the printer is waiting for. This needs a firmware fix. - _write(file, "M1 S10\n"); + file.write("M1 S10\n"); } } else { // This is not Marlin, M1 command is probably not supported. @@ -1410,19 +1410,19 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu } #ifdef HAS_PRESSURE_EQUALIZER if (m_pressure_equalizer) - _write(file, m_pressure_equalizer->process("", true)); + file.write(m_pressure_equalizer->process("", true)); #endif /* HAS_PRESSURE_EQUALIZER */ if (m_wipe_tower) // Purge the extruder, pull out the active filament. - _write(file, m_wipe_tower->finalize(*this)); + file.write(m_wipe_tower->finalize(*this)); } // Write end commands to file. - _write(file, this->retract()); - _write(file, m_writer.set_fan(false)); + file.write(this->retract()); + file.write(m_writer.set_fan(false)); // adds tag for processor - _write_format(file, ";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); + file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str()); // Process filament-specific gcode in extruder order. { @@ -1434,48 +1434,48 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu // Process the end_filament_gcode for the active filament only. int extruder_id = m_writer.extruder()->id(); config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id)); - _writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config)); + file.writeln(this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config)); } else { for (const std::string &end_gcode : print.config().end_filament_gcode.values) { int extruder_id = (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front()); config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id)); - _writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config)); + file.writeln(this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config)); } } - _writeln(file, this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id(), &config)); + file.writeln(this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id(), &config)); } - _write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100% - _write(file, m_writer.postamble()); + file.write(m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100% + file.write(m_writer.postamble()); // adds tags for time estimators if (print.config().remaining_times.value) - _write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str()); + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str()); print.throw_if_canceled(); // Get filament stats. - _write(file, DoExport::update_print_stats_and_format_filament_stats( + file.write(DoExport::update_print_stats_and_format_filament_stats( // Const inputs has_wipe_tower, print.wipe_tower_data(), m_writer.extruders(), // Modifies print.m_print_statistics)); - _write(file, "\n"); - _write_format(file, "; total filament used [g] = %.2lf\n", print.m_print_statistics.total_weight); - _write_format(file, "; total filament cost = %.2lf\n", print.m_print_statistics.total_cost); + file.write("\n"); + file.write_format("; total filament used [g] = %.2lf\n", print.m_print_statistics.total_weight); + file.write_format("; total filament cost = %.2lf\n", print.m_print_statistics.total_cost); if (print.m_print_statistics.total_toolchanges > 0) - _write_format(file, "; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges); - _write_format(file, ";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str()); + file.write_format("; total toolchanges = %i\n", print.m_print_statistics.total_toolchanges); + file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str()); // Append full config, delimited by two 'phony' configuration keys prusaslicer_config = begin and prusaslicer_config = end. // The delimiters are structured as configuration key / value pairs to be parsable by older versions of PrusaSlicer G-code viewer. { - _write(file, "\n; prusaslicer_config = begin\n"); + file.write("\n; prusaslicer_config = begin\n"); std::string full_config; append_full_config(print, full_config); if (!full_config.empty()) - _write(file, full_config); - _write(file, "; prusaslicer_config = end\n"); + file.write(full_config); + file.write("; prusaslicer_config = end\n"); } print.throw_if_canceled(); } @@ -1565,16 +1565,16 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc // Print the machine envelope G-code for the Marlin firmware based on the "machine_max_xxx" parameters. // Do not process this piece of G-code by the time estimator, it already knows the values through another sources. -void GCode::print_machine_envelope(FILE *file, Print &print) +void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print) { if ((print.config().gcode_flavor.value == gcfMarlinLegacy || print.config().gcode_flavor.value == gcfMarlinFirmware) && print.config().machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) { - fprintf(file, "M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n", + file.write_format("M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n", int(print.config().machine_max_acceleration_x.values.front() + 0.5), int(print.config().machine_max_acceleration_y.values.front() + 0.5), int(print.config().machine_max_acceleration_z.values.front() + 0.5), int(print.config().machine_max_acceleration_e.values.front() + 0.5)); - fprintf(file, "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n", + file.write_format("M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n", int(print.config().machine_max_feedrate_x.values.front() + 0.5), int(print.config().machine_max_feedrate_y.values.front() + 0.5), int(print.config().machine_max_feedrate_z.values.front() + 0.5), @@ -1587,18 +1587,18 @@ void GCode::print_machine_envelope(FILE *file, Print &print) int travel_acc = print.config().gcode_flavor == gcfMarlinLegacy ? int(print.config().machine_max_acceleration_extruding.values.front() + 0.5) : int(print.config().machine_max_acceleration_travel.values.front() + 0.5); - fprintf(file, "M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n", + file.write_format("M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n", int(print.config().machine_max_acceleration_extruding.values.front() + 0.5), int(print.config().machine_max_acceleration_retracting.values.front() + 0.5), travel_acc); assert(is_decimal_separator_point()); - fprintf(file, "M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n", + file.write_format("M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n", print.config().machine_max_jerk_x.values.front(), print.config().machine_max_jerk_y.values.front(), print.config().machine_max_jerk_z.values.front(), print.config().machine_max_jerk_e.values.front()); - fprintf(file, "M205 S%d T%d ; sets the minimum extruding and travel feed rate, mm/sec\n", + file.write_format("M205 S%d T%d ; sets the minimum extruding and travel feed rate, mm/sec\n", int(print.config().machine_min_extruding_rate.values.front() + 0.5), int(print.config().machine_min_travel_rate.values.front() + 0.5)); } @@ -1608,7 +1608,7 @@ void GCode::print_machine_envelope(FILE *file, Print &print) // Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. // M140 - Set Extruder Temperature // M190 - Set Extruder Temperature and Wait -void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) { // Initial bed temperature based on the first extruder. int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id); @@ -1621,7 +1621,7 @@ void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const s // the custom start G-code emited these. std::string set_temp_gcode = m_writer.set_bed_temperature(temp, wait); if (! temp_set_by_gcode) - _write(file, set_temp_gcode); + file.write(set_temp_gcode); } // Write 1st layer extruder temperatures into the G-code. @@ -1629,7 +1629,7 @@ void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const s // M104 - Set Extruder Temperature // M109 - Set Extruder Temperature and Wait // RepRapFirmware: G10 Sxx -void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) +void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait) { // Is the bed temperature set by the provided custom G-code? int temp_by_gcode = -1; @@ -1646,7 +1646,7 @@ void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, c // Set temperature of the first printing extruder only. int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id); if (temp > 0) - _write(file, m_writer.set_temperature(temp, wait, first_printing_extruder_id)); + file.write(m_writer.set_temperature(temp, wait, first_printing_extruder_id)); } else { // Set temperatures of all the printing extruders. for (unsigned int tool_id : print.extruders()) { @@ -1654,7 +1654,7 @@ void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, c if (print.config().ooze_prevention.value) temp += print.config().standby_temperature_delta.value; if (temp > 0) - _write(file, m_writer.set_temperature(temp, wait, tool_id)); + file.write(m_writer.set_temperature(temp, wait, tool_id)); } } } @@ -1891,7 +1891,7 @@ namespace Skirt { // and performing the extruder specific extrusions together. void GCode::process_layer( // Write into the output file. - FILE *file, + GCodeOutputStream &file, const Print &print, // Set of object & print layers of the same PrintObject and with the same print_z. const std::vector &layers, @@ -2306,7 +2306,7 @@ void GCode::process_layer( // printf("G-code after filter:\n%s\n", out.c_str()); #endif /* HAS_PRESSURE_EQUALIZER */ - _write(file, gcode); + file.write(gcode); BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << log_memory_info(); } @@ -2642,22 +2642,22 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill return gcode; } -void GCode::_write(FILE* file, const char *what) +void GCode::GCodeOutputStream::write(const char *what) { if (what != nullptr) { const char* gcode = what; // writes string to file - fwrite(gcode, 1, ::strlen(gcode), file); + fwrite(gcode, 1, ::strlen(gcode), this->f); } } -void GCode::_writeln(FILE* file, const std::string &what) +void GCode::GCodeOutputStream::writeln(const std::string &what) { if (! what.empty()) - _write(file, (what.back() == '\n') ? what : (what + '\n')); + this->write(what.back() == '\n' ? what : what + '\n'); } -void GCode::_write_format(FILE* file, const char* format, ...) +void GCode::GCodeOutputStream::write_format(const char* format, ...) { va_list args; va_start(args, format); @@ -2681,7 +2681,7 @@ void GCode::_write_format(FILE* file, const char* format, ...) char *bufptr = buffer_dynamic ? (char*)malloc(buflen) : buffer; int res = ::vsnprintf(bufptr, buflen, format, args); if (res > 0) - _write(file, bufptr); + this->write(bufptr); if (buffer_dynamic) free(bufptr); diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index d2d241054..06900410a 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -184,13 +184,39 @@ public: }; private: - void _do_export(Print &print, FILE *file, ThumbnailsGeneratorCallback thumbnail_cb); + class GCodeOutputStream { + public: + GCodeOutputStream(FILE *f) : f(f) {} + ~GCodeOutputStream() { this->close(); } + + bool is_open() const { return f; } + bool is_error() const { return ::ferror(f); } + + void flush() { ::fflush(f); } + void close() { if (f) ::fclose(f); } + + // Write a string into a file. + void write(const std::string& what) { this->write(what.c_str()); } + void write(const char* what); + + // Write a string into a file. + // Add a newline, if the string does not end with a newline already. + // Used to export a custom G-code section processed by the PlaceholderParser. + void writeln(const std::string& what); + + // Formats and write into a file the given data. + void write_format(const char* format, ...); + + private: + FILE *f = nullptr; + }; + void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); static std::vector collect_layers_to_print(const PrintObject &object); static std::vector>> collect_layers_to_print(const Print &print); void process_layer( // Write into the output file. - FILE *file, + GCodeOutputStream &file, const Print &print, // Set of object & print layers of the same PrintObject and with the same print_z. const std::vector &layers, @@ -358,22 +384,10 @@ private: // Processor GCodeProcessor m_processor; - // Write a string into a file. - void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str()); } - void _write(FILE* file, const char *what); - - // Write a string into a file. - // Add a newline, if the string does not end with a newline already. - // Used to export a custom G-code section processed by the PlaceholderParser. - void _writeln(FILE* file, const std::string& what); - - // Formats and write into a file the given data. - void _write_format(FILE* file, const char* format, ...); - std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1); - void print_machine_envelope(FILE *file, Print &print); - void _print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); - void _print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); + void print_machine_envelope(GCodeOutputStream &file, Print &print); + void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); + void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); // On the first printing layer. This flag triggers first layer speeds. bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; } // To control print speed of 1st object layer over raft interface. From eb2debc2c6f212dfe3bed71f0a072bd674a20e5b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 7 Sep 2021 16:48:13 +0200 Subject: [PATCH 18/27] ObjectList: Fixed DnD of Volumes inside the Object --- src/slic3r/GUI/ObjectDataViewModel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 9417364ef..88527e9fd 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -1361,7 +1361,8 @@ wxDataViewItem ObjectDataViewModel::ReorganizeChildren( const int current_volume if (!node_parent) // happens if item.IsOk()==false return ret_item; - const size_t shift = node_parent->GetChildren().Item(0)->m_type == itSettings ? 1 : 0; + size_t shift; + for (shift = 0; shift < node_parent->GetChildCount() && node_parent->GetNthChild(shift)->GetType() != itVolume; shift ++); ObjectDataViewModelNode *deleted_node = node_parent->GetNthChild(current_volume_id+shift); node_parent->GetChildren().Remove(deleted_node); From 152e236ddad9170ac22afb7a82db455c357f66b8 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 17:25:53 +0200 Subject: [PATCH 19/27] Trying to fix the windows build --- src/libslic3r/GCode.cpp | 4 ++++ src/libslic3r/GCode.hpp | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 54815188e..ff0076880 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2642,6 +2642,10 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill return gcode; } +bool GCode::GCodeOutputStream::is_error() const { return ::ferror(f); } +void GCode::GCodeOutputStream::flush() { ::fflush(f); } +void GCode::GCodeOutputStream::close() { if (f) ::fclose(f); } + void GCode::GCodeOutputStream::write(const char *what) { if (what != nullptr) { diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 06900410a..89e4570a9 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -190,10 +190,10 @@ private: ~GCodeOutputStream() { this->close(); } bool is_open() const { return f; } - bool is_error() const { return ::ferror(f); } + bool is_error() const; - void flush() { ::fflush(f); } - void close() { if (f) ::fclose(f); } + void flush(); + void close(); // Write a string into a file. void write(const std::string& what) { this->write(what.c_str()); } From 0da0a7b2a0e2a45f55ce51434761f37d34937df6 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 7 Sep 2021 17:58:06 +0200 Subject: [PATCH 20/27] Fix of recent GCode / GCodeProcessor refactoring: Don't close a FILE twice. --- src/libslic3r/GCode.cpp | 20 +++++++++++++++++--- src/libslic3r/GCode/GCodeProcessor.cpp | 7 ++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index ff0076880..f2deba046 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2642,9 +2642,23 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill return gcode; } -bool GCode::GCodeOutputStream::is_error() const { return ::ferror(f); } -void GCode::GCodeOutputStream::flush() { ::fflush(f); } -void GCode::GCodeOutputStream::close() { if (f) ::fclose(f); } +bool GCode::GCodeOutputStream::is_error() const +{ + return ::ferror(this->f); +} + +void GCode::GCodeOutputStream::flush() +{ + ::fflush(this->f); +} + +void GCode::GCodeOutputStream::close() +{ + if (this->f) { + ::fclose(this->f); + this->f = nullptr; + } +} void GCode::GCodeOutputStream::write(const char *what) { diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index ec586dbef..60af399c0 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -350,7 +350,12 @@ void GCodeProcessor::TimeProcessor::reset() struct FilePtr { FilePtr(FILE *f) : f(f) {} ~FilePtr() { this->close(); } - void close() { if (f) ::fclose(f); } + void close() { + if (this->f) { + ::fclose(this->f); + this->f = nullptr; + } + } FILE* f = nullptr; }; From 9abebe5fbe6950d809b51926af8772317fe2657f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 13:04:43 +0200 Subject: [PATCH 21/27] Techs ENABLE_SEAMS_USING_MODELS and ENABLE_SEAMS_USING_BATCHED_MODELS - Fixed seams (and other options) zs to match toolpaths zs in preview --- resources/shaders/gouraud_light_instanced.vs | 4 +++- src/slic3r/GUI/GCodeViewer.cpp | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/shaders/gouraud_light_instanced.vs b/resources/shaders/gouraud_light_instanced.vs index a8931361d..997b6a2bf 100644 --- a/resources/shaders/gouraud_light_instanced.vs +++ b/resources/shaders/gouraud_light_instanced.vs @@ -34,7 +34,9 @@ void main() float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - vec4 world_position = vec4(v_position * vec3(vec2(i_scales.x), i_scales.y) + i_offset, 1.0); + float width = 1.5 * i_scales.x; + float height = 1.5 * i_scales.y; + vec4 world_position = vec4(v_position * vec3(vec2(width), height) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0); vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz; intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 7e8e587a6..ac97b8dbc 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1414,9 +1414,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) instances.push_back(curr.position.y()); instances.push_back(curr.position.z()); // append width - instances.push_back(1.5f * curr.width); + instances.push_back(curr.width); // append height - instances.push_back(1.5f * curr.height); + instances.push_back(curr.height); // append id instances_ids.push_back(move_id); @@ -1428,7 +1428,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const double width = static_cast(1.5f * curr.width); const double height = static_cast(1.5f * curr.height); - const Transform3d trafo = Geometry::assemble_transform(curr.position.cast(), Vec3d::Zero(), { width, width, height }); + const Transform3d trafo = Geometry::assemble_transform((curr.position - 0.5f * curr.height * Vec3f::UnitZ()).cast(), Vec3d::Zero(), { width, width, height }); const Eigen::Matrix normal_matrix = trafo.matrix().template block<3, 3>(0, 0).inverse().transpose(); for (const auto& entity : data.entities) { From 6f678c09d1358fdbfbe50452604797d8f03c3056 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 14:30:40 +0200 Subject: [PATCH 22/27] Tech ENABLE_FIX_PREVIEW_OPTIONS_Z - Enable fixing the z position of seams (and other options) in preview --- src/libslic3r/GCode/GCodeProcessor.cpp | 23 ++++++++++++++ src/libslic3r/GCode/GCodeProcessor.hpp | 42 ++++++++++++++++++++++++++ src/libslic3r/Technologies.hpp | 9 ++++++ src/slic3r/GUI/GCodeViewer.cpp | 4 +++ 4 files changed, 78 insertions(+) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 60af399c0..a217fa102 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -828,6 +828,9 @@ bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned i } GCodeProcessor::GCodeProcessor() +#if ENABLE_FIX_PREVIEW_OPTIONS_Z +: m_options_z_corrector(m_result) +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z { reset(); m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n"; @@ -1202,6 +1205,10 @@ void GCodeProcessor::reset() m_last_default_color_id = 0; #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.reset(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z + #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_mm3_per_mm_compare.reset(); m_height_compare.reset(); @@ -1781,6 +1788,9 @@ void GCodeProcessor::process_tags(const std::string_view comment) #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::ColorChange, extruder_id + 1, color, "" }; m_result.custom_gcode_per_print_z.emplace_back(item); +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.set(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z process_custom_gcode_time(CustomGCode::ColorChange); process_filaments(CustomGCode::ColorChange); #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER @@ -1800,6 +1810,9 @@ void GCodeProcessor::process_tags(const std::string_view comment) #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::PausePrint, m_extruder_id + 1, "", "" }; m_result.custom_gcode_per_print_z.emplace_back(item); +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.set(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER process_custom_gcode_time(CustomGCode::PausePrint); return; @@ -1811,6 +1824,9 @@ void GCodeProcessor::process_tags(const std::string_view comment) #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER CustomGCode::Item item = { static_cast(m_end_position[2]), CustomGCode::Custom, m_extruder_id + 1, "", "" }; m_result.custom_gcode_per_print_z.emplace_back(item); +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_options_z_corrector.set(); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER return; } @@ -2391,7 +2407,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) else { if (m_end_position[Z] > m_extruded_last_z + EPSILON) { m_height = m_end_position[Z] - m_extruded_last_z; +#if !ENABLE_FIX_PREVIEW_OPTIONS_Z m_extruded_last_z = m_end_position[Z]; +#endif // !ENABLE_FIX_PREVIEW_OPTIONS_Z } } @@ -2401,6 +2419,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (m_end_position[Z] == 0.0f) m_end_position[Z] = m_height; +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + m_extruded_last_z = m_end_position[Z]; + m_options_z_corrector.update(m_height); +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z + #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_height_compare.update(m_height, m_extrusion_role); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index bb9310888..a1730daf2 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -390,6 +390,45 @@ namespace Slic3r { bool has_first_vertex() const { return m_first_vertex.has_value(); } }; +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + // Helper class used to fix the z for color change, pause print and + // custom gcode markes + class OptionsZCorrector + { + Result& m_result; + std::optional m_move_id; + std::optional m_custom_gcode_per_print_z_id; + + public: + explicit OptionsZCorrector(Result& result) : m_result(result) { + } + + void set() { + m_move_id = m_result.moves.size() - 1; + m_custom_gcode_per_print_z_id = m_result.custom_gcode_per_print_z.size() - 1; + } + + void update(float height) { + if (!m_move_id.has_value() || !m_custom_gcode_per_print_z_id.has_value()) + return; + + const Vec3f position = m_result.moves.back().position; + + MoveVertex& move = m_result.moves.emplace_back(m_result.moves[m_move_id.value()]); + move.position = position; + move.height = height; + m_result.moves.erase(m_result.moves.begin() + m_move_id.value()); + m_result.custom_gcode_per_print_z[m_custom_gcode_per_print_z_id.value()].print_z = position.z(); + reset(); + } + + void reset() { + m_move_id.reset(); + m_custom_gcode_per_print_z_id.reset(); + } + }; +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z + #if ENABLE_GCODE_VIEWER_DATA_CHECKING struct DataChecker { @@ -494,6 +533,9 @@ namespace Slic3r { CpColor m_cp_color; bool m_use_volumetric_e; SeamsDetector m_seams_detector; +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + OptionsZCorrector m_options_z_corrector; +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER size_t m_last_default_color_id; #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 6132430f1..adcde5572 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -57,4 +57,13 @@ #define ENABLE_SAVE_COMMANDS_ALWAYS_ENABLED (1 && ENABLE_2_4_0_ALPHA0) +//==================== +// 2.4.0.alpha2 techs +//==================== +#define ENABLE_2_4_0_ALPHA2 1 + +// Enable fixing the z position of color change, pause print and custom gcode markers in preview +#define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER && ENABLE_2_4_0_ALPHA2) + + #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 946cbb275..9b4e2ef8d 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2370,7 +2370,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (m_sequential_view.current.first <= buffer.model.instances.s_ids.back() && buffer.model.instances.s_ids.front() <= m_sequential_view.current.last) { for (size_t id : buffer.model.instances.s_ids) { if (has_second_range) { +#if ENABLE_FIX_PREVIEW_OPTIONS_Z + if (id < m_sequential_view.endpoints.first) { +#else if (id <= m_sequential_view.endpoints.first) { +#endif // ENABLE_FIX_PREVIEW_OPTIONS_Z ++buffer.model.instances.render_ranges.ranges.front().offset; if (id <= m_sequential_view.current.first) ++buffer.model.instances.render_ranges.ranges.back().offset; From 88d608351d0b5f3d4c678ffe673cb818a1ad6dd5 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 14:34:31 +0200 Subject: [PATCH 23/27] Fix after merge with master --- src/libslic3r/Technologies.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 1183b51df..ac92ecd10 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -64,13 +64,6 @@ // Enable rendering seams (and other options) in preview using batched models on systems not supporting OpenGL 3.3 #define ENABLE_SEAMS_USING_BATCHED_MODELS (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_2_4_0_ALPHA2) - - -//==================== -// 2.4.0.alpha2 techs -//==================== -#define ENABLE_2_4_0_ALPHA2 1 - // Enable fixing the z position of color change, pause print and custom gcode markers in preview #define ENABLE_FIX_PREVIEW_OPTIONS_Z (1 && ENABLE_SEAMS_USING_MODELS && ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER && ENABLE_2_4_0_ALPHA2) From beee18f22991e369b1722a43bbcb692fa0d68af0 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 8 Sep 2021 15:06:05 +0200 Subject: [PATCH 24/27] Follow-up to b5a007a683124ec3b01b61e892ed8eb39c034248 WIP to G-code export parallelization through pipelining: GCodeProcessor is called during the G-code export, the G-code is no more reopened and re-read, but it is pipelined from the G-code generator. --- src/libslic3r/GCode.cpp | 7 +++- src/libslic3r/GCode.hpp | 3 +- src/libslic3r/GCode/GCodeProcessor.cpp | 54 ++++++++++++++++++-------- src/libslic3r/GCode/GCodeProcessor.hpp | 13 ++++--- src/libslic3r/GCodeReader.hpp | 3 +- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 3 +- 7 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index f2deba046..efea240e5 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -744,7 +744,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re std::string path_tmp(path); path_tmp += ".tmp"; - GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb")); + m_processor.initialize(path_tmp); + GCodeOutputStream file(boost::nowide::fopen(path_tmp.c_str(), "wb"), m_processor); if (! file.is_open()) throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); @@ -782,7 +783,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re } BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info(); - m_processor.process_file(path_tmp, true, [print]() { print->throw_if_canceled(); }); + m_processor.finalize(); // DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics); DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics); if (result != nullptr) { @@ -2666,6 +2667,8 @@ void GCode::GCodeOutputStream::write(const char *what) const char* gcode = what; // writes string to file fwrite(gcode, 1, ::strlen(gcode), this->f); + //FIXME don't allocate a string, maybe process a batch of lines? + m_processor.process_buffer(std::string(gcode)); } } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 89e4570a9..1dbc5b70a 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -186,7 +186,7 @@ public: private: class GCodeOutputStream { public: - GCodeOutputStream(FILE *f) : f(f) {} + GCodeOutputStream(FILE *f, GCodeProcessor &processor) : f(f), m_processor(processor) {} ~GCodeOutputStream() { this->close(); } bool is_open() const { return f; } @@ -209,6 +209,7 @@ private: private: FILE *f = nullptr; + GCodeProcessor &m_processor; }; void _do_export(Print &print, GCodeOutputStream &file, ThumbnailsGeneratorCallback thumbnail_cb); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 60af399c0..1891c90b4 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1189,7 +1189,6 @@ void GCodeProcessor::reset() m_cp_color.reset(); m_producer = EProducer::Unknown; - m_producers_enabled = false; m_time_processor.reset(); m_used_filaments.reset(); @@ -1209,7 +1208,7 @@ void GCodeProcessor::reset() #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING } -void GCodeProcessor::process_file(const std::string& filename, bool apply_postprocess, std::function cancel_callback) +void GCodeProcessor::process_file(const std::string& filename, std::function cancel_callback) { CNumericLocalesSetter locales_setter; @@ -1219,7 +1218,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr // pre-processing // parse the gcode file to detect its producer - if (m_producers_enabled) { + { m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { const std::string_view cmd = line.cmd(); if (cmd.empty()) { @@ -1228,6 +1227,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr m_parser.quit_parsing(); } }); + m_parser.reset(); // if the gcode was produced by PrusaSlicer, // extract the config from it @@ -1257,9 +1257,37 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr if (cancel_callback) cancel_callback(); } - this->process_gcode_line(line); + this->process_gcode_line(line, true); }); + this->finalize(); + + // post-process to add M73 lines into the gcode +#if ENABLE_GCODE_VIEWER_STATISTICS + m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS +} + +void GCodeProcessor::initialize(const std::string& filename) +{ + assert(is_decimal_separator_point()); + // process gcode + m_result.filename = filename; + m_result.id = ++s_result_id; + // 1st move must be a dummy move + m_result.moves.emplace_back(MoveVertex()); +} + +void GCodeProcessor::process_buffer(const std::string &buffer) +{ + //FIXME maybe cache GCodeLine gline to be over multiple parse_buffer() invocations. + m_parser.parse_buffer(buffer, [this](GCodeReader&, const GCodeReader::GCodeLine& line) { + this->process_gcode_line(line, false); + }); +} + +void GCodeProcessor::finalize() +{ // update width/height of wipe moves for (MoveVertex& move : m_result.moves) { if (move.type == EMoveType::Wipe) { @@ -1281,10 +1309,6 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr update_estimated_times_stats(); - // post-process to add M73 lines into the gcode - if (apply_postprocess) - m_time_processor.post_process(filename, m_result.moves, m_result.lines_ends); - #if ENABLE_GCODE_VIEWER_DATA_CHECKING std::cout << "\n"; m_mm3_per_mm_compare.output(); @@ -1292,9 +1316,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr m_width_compare.output(); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING -#if ENABLE_GCODE_VIEWER_STATISTICS - m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); -#endif // ENABLE_GCODE_VIEWER_STATISTICS + m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends); } float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const @@ -1432,7 +1454,7 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename) } } -void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) +void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled) { /* std::cout << line.raw() << std::endl; */ @@ -1615,7 +1637,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) if (comment.length() > 2 && comment.front() == ';') // Process tags embedded into comments. Tag comments always start at the start of a line // with a comment and continue with a tag without any whitespace separator. - process_tags(comment.substr(1)); + process_tags(comment.substr(1), producers_enabled); } } @@ -1664,10 +1686,10 @@ template } } -void GCodeProcessor::process_tags(const std::string_view comment) +void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled) { // producers tags - if (m_producers_enabled && process_producers_tags(comment)) + if (producers_enabled && process_producers_tags(comment)) return; // extrusion role tag @@ -1691,7 +1713,7 @@ void GCodeProcessor::process_tags(const std::string_view comment) return; } - if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) { + if (!producers_enabled || m_producer == EProducer::PrusaSlicer) { // height tag if (boost::starts_with(comment, reserved_tag(ETags::Height))) { if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height)) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index bb9310888..1665fb9f2 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -513,7 +513,6 @@ namespace Slic3r { static const std::vector> Producers; EProducer m_producer; - bool m_producers_enabled; TimeProcessor m_time_processor; UsedFilaments m_used_filaments; @@ -536,7 +535,6 @@ namespace Slic3r { return m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled; } void enable_machine_envelope_processing(bool enabled) { m_time_processor.machine_envelope_processing_enabled = enabled; } - void enable_producers(bool enabled) { m_producers_enabled = enabled; } void reset(); const Result& get_result() const { return m_result; } @@ -544,7 +542,12 @@ namespace Slic3r { // Process the gcode contained in the file with the given filename // throws CanceledException through print->throw_if_canceled() (sent by the caller as callback). - void process_file(const std::string& filename, bool apply_postprocess, std::function cancel_callback = nullptr); + void process_file(const std::string& filename, std::function cancel_callback = nullptr); + + // Streaming interface, for processing G-codes just generated by PrusaSlicer in a pipelined fashion. + void initialize(const std::string& filename); + void process_buffer(const std::string& buffer); + void finalize(); float get_time(PrintEstimatedStatistics::ETimeMode mode) const; std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const; @@ -557,10 +560,10 @@ namespace Slic3r { private: void apply_config(const DynamicPrintConfig& config); void apply_config_simplify3d(const std::string& filename); - void process_gcode_line(const GCodeReader::GCodeLine& line); + void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled); // Process tags embedded into comments - void process_tags(const std::string_view comment); + void process_tags(const std::string_view comment, bool producers_enabled); bool process_producers_tags(const std::string_view comment); bool process_prusaslicer_tags(const std::string_view comment); bool process_cura_tags(const std::string_view comment); diff --git a/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp index 8c820b95d..15376c0fc 100644 --- a/src/libslic3r/GCodeReader.hpp +++ b/src/libslic3r/GCodeReader.hpp @@ -77,7 +77,8 @@ public: typedef std::function callback_t; - GCodeReader() : m_verbose(false), m_extrusion_axis('E') { memset(m_position, 0, sizeof(m_position)); } + GCodeReader() : m_verbose(false), m_extrusion_axis('E') { this->reset(); } + void reset() { memset(m_position, 0, sizeof(m_position)); } void apply_config(const GCodeConfig &config); void apply_config(const DynamicPrintConfig &config); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index ac97b8dbc..e61d1356a 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1190,7 +1190,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) }; auto add_indices_as_line = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer, unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) { - if (prev.type != curr.type || !buffer.paths.back().matches(curr)) { + if (buffer.paths.empty() || prev.type != curr.type || !buffer.paths.back().matches(curr)) { // add starting index indices.push_back(static_cast(indices.size())); buffer.add_path(curr, ibuffer_id, indices.size() - 1, move_id - 1); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2c77dcb7a..76612a718 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4871,10 +4871,9 @@ void Plater::load_gcode(const wxString& filename) // process gcode GCodeProcessor processor; - processor.enable_producers(true); try { - processor.process_file(filename.ToUTF8().data(), false); + processor.process_file(filename.ToUTF8().data()); } catch (const std::exception& ex) { From a115da63347d52704fdea659e7b3f1f2438dca38 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 8 Sep 2021 15:30:51 +0200 Subject: [PATCH 25/27] Fix for #6921 - Error while disabling filament overrides in Dutch language --- src/slic3r/GUI/Field.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 1aaac5469..06cfd0a1c 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -230,18 +230,21 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true } double val; + bool is_na_value = m_opt.nullable && str == na_value(); + const char dec_sep = is_decimal_separator_point() ? '.' : ','; const char dec_sep_alt = dec_sep == '.' ? ',' : '.'; - // Replace the first incorrect separator in decimal number. - if (str.Replace(dec_sep_alt, dec_sep, false) != 0) + // Replace the first incorrect separator in decimal number, + // if this value doesn't "N/A" value in some language + // see https://github.com/prusa3d/PrusaSlicer/issues/6921 + if (!is_na_value && str.Replace(dec_sep_alt, dec_sep, false) != 0) set_value(str, false); - if (str == dec_sep) val = 0.0; else { - if (m_opt.nullable && str == na_value()) + if (is_na_value) val = ConfigOptionFloatsNullable::nil_value(); else if (!str.ToDouble(&val)) { From d3382b666fed0fee2067a8c30314e664fce8a8e7 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 8 Sep 2021 15:47:27 +0200 Subject: [PATCH 26/27] Fixed build on MAC --- src/libslic3r/GCode/GCodeProcessor.hpp | 6 +++--- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index a1730daf2..ac0fb0d87 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -414,11 +414,11 @@ namespace Slic3r { const Vec3f position = m_result.moves.back().position; - MoveVertex& move = m_result.moves.emplace_back(m_result.moves[m_move_id.value()]); + MoveVertex& move = m_result.moves.emplace_back(m_result.moves[*m_move_id]); move.position = position; move.height = height; - m_result.moves.erase(m_result.moves.begin() + m_move_id.value()); - m_result.custom_gcode_per_print_z[m_custom_gcode_per_print_z_id.value()].print_z = position.z(); + m_result.moves.erase(m_result.moves.begin() + *m_move_id); + m_result.custom_gcode_per_print_z[*m_custom_gcode_per_print_z_id].print_z = position.z(); reset(); } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 7e8383120..0f019b2bf 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3045,7 +3045,7 @@ void GCodeViewer::render_legend(float& legend_height) bool imperial_units = wxGetApp().app_config->get("use_inches") == "1"; - auto append_item = [this, icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label, + auto append_item = [icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label, bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array& offsets = { 0.0f, 0.0f, 0.0f, 0.0f }, double used_filament_m = 0.0, double used_filament_g = 0.0, std::function callback = nullptr) { From fe8e2ae0d1889127e5df1b504cafc1c259fbf042 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 9 Sep 2021 09:35:58 +0200 Subject: [PATCH 27/27] ENABLE_GCODE_VIEWER_STATISTICS - Fixed calculation of time required by GCodeProcessor --- src/libslic3r/GCode/GCodeProcessor.cpp | 15 +++++++++------ src/libslic3r/GCode/GCodeProcessor.hpp | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 1891c90b4..8ebd82d66 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1213,7 +1213,7 @@ void GCodeProcessor::process_file(const std::string& filename, std::functionfinalize(); - - // post-process to add M73 lines into the gcode -#if ENABLE_GCODE_VIEWER_STATISTICS - m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); -#endif // ENABLE_GCODE_VIEWER_STATISTICS } void GCodeProcessor::initialize(const std::string& filename) { assert(is_decimal_separator_point()); + +#if ENABLE_GCODE_VIEWER_STATISTICS + m_start_time = std::chrono::high_resolution_clock::now(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS + // process gcode m_result.filename = filename; m_result.id = ++s_result_id; @@ -1317,6 +1317,9 @@ void GCodeProcessor::finalize() #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends); +#if ENABLE_GCODE_VIEWER_STATISTICS + m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_start_time).count(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS } float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 1665fb9f2..ea594b3fc 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -497,6 +497,9 @@ namespace Slic3r { #if ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER size_t m_last_default_color_id; #endif // ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER +#if ENABLE_GCODE_VIEWER_STATISTICS + std::chrono::time_point m_start_time; +#endif // ENABLE_GCODE_VIEWER_STATISTICS enum class EProducer {