diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index e918069f8a..8b7df5e680 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1,9 +1,9 @@ -///|/ Copyright (c) Prusa Research 2020 - 2023 Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Vojtěch Bubník @bubnikv, Filip Sykala @Jony01, Lukáš Hejl @hejllukas -///|/ Copyright (c) BambuStudio 2023 manch1n @manch1n -///|/ Copyright (c) SuperSlicer 2023 Remi Durand @supermerill -///|/ -///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher -///|/ +///|/ Copyright (c) Prusa Research 2020 - 2023 Enrico Turri @enricoturri1966, Oleksandra Iushchenko @YuSanka, Lukáš Matěna @lukasmatena, Vojtěch Bubník @bubnikv, Filip Sykala @Jony01, Lukáš Hejl @hejllukas +///|/ Copyright (c) BambuStudio 2023 manch1n @manch1n +///|/ Copyright (c) SuperSlicer 2023 Remi Durand @supermerill +///|/ +///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher +///|/ #include "libslic3r/libslic3r.h" #include "GCodeViewer.hpp" @@ -200,11 +200,11 @@ void GCodeViewer::TBuffer::add_path(const GCodeProcessorResult::MoveVertex& move //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER -#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS void GCodeViewer::COG::render() #else void GCodeViewer::COG::render(bool fixed_screen_size) -#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS #else //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ void GCodeViewer::COG::render() @@ -217,12 +217,12 @@ void GCodeViewer::COG::render() //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER -#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS init(); #else fixed_screen_size = true; init(fixed_screen_size); -#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS #else //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ init(); @@ -242,11 +242,11 @@ void GCodeViewer::COG::render() Transform3d model_matrix = Geometry::translation_transform(cog()) * Geometry::scale_transform(m_scale_factor); //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER -#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS if (m_fixed_screen_size) { #else if (fixed_screen_size) { -#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS #else //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (m_fixed_screen_size) { @@ -429,8 +429,8 @@ void GCodeViewer::SequentialView::Marker::render() //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER -static std::string to_string(libvgcode::EMoveType type) -{ +static std::string to_string(libvgcode::EMoveType type) +{ switch (type) { case libvgcode::EMoveType::Noop: { return _u8L("Noop"); } @@ -445,13 +445,13 @@ static std::string to_string(libvgcode::EMoveType type) case libvgcode::EMoveType::Wipe: { return _u8L("Wipe"); } case libvgcode::EMoveType::Extrude: { return _u8L("Extrude"); } default: { return _u8L("Unknown"); } - } -} - -static std::string to_string(libvgcode::EGCodeExtrusionRole role) -{ - switch (role) - { + } +} + +static std::string to_string(libvgcode::EGCodeExtrusionRole role) +{ + switch (role) + { case libvgcode::EGCodeExtrusionRole::None: { return _u8L("Unknown"); } case libvgcode::EGCodeExtrusionRole::Perimeter: { return _u8L("Perimeter"); } case libvgcode::EGCodeExtrusionRole::ExternalPerimeter: { return _u8L("External perimeter"); } @@ -468,16 +468,16 @@ static std::string to_string(libvgcode::EGCodeExtrusionRole role) case libvgcode::EGCodeExtrusionRole::WipeTower: { return _u8L("Wipe tower"); } case libvgcode::EGCodeExtrusionRole::Custom: { return _u8L("Custom"); } default: { return _u8L("Unknown"); } - } -} + } +} void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode::Viewer* viewer) { static float last_window_width = 0.0f; static size_t last_text_length = 0; static bool properties_shown = false; - - if (viewer != nullptr) { + + if (viewer != nullptr) { ImGuiWrapper& imgui = *wxGetApp().imgui(); const Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); imgui.set_next_window_pos(0.5f * static_cast(cnv_size.get_width()), static_cast(cnv_size.get_height()), ImGuiCond_Always, 0.5f, 1.0f); @@ -552,8 +552,8 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode imgui.end(); ImGui::PopStyleVar(); - } - else { + } + else { ImGuiWrapper& imgui = *wxGetApp().imgui(); const Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); imgui.set_next_window_pos(0.5f * static_cast(cnv_size.get_width()), static_cast(cnv_size.get_height()), ImGuiCond_Always, 0.5f, 1.0f); @@ -578,7 +578,7 @@ void GCodeViewer::SequentialView::Marker::render_position_window(const libvgcode imgui.end(); ImGui::PopStyleVar(); - } + } } #endif // ENABLE_NEW_GCODE_VIEWER //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -907,10 +907,10 @@ void GCodeViewer::SequentialView::GCodeWindow::render(float top, float bottom, s //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER void GCodeViewer::SequentialView::render(float legend_height, const libvgcode::Viewer* viewer, uint32_t gcode_id) -{ -#if !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +{ +#if !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS if (viewer == nullptr) -#endif // !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#endif // !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS #else //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ void GCodeViewer::SequentialView::render(float legend_height) @@ -1150,28 +1150,28 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const const ColorRGBA default_color = { 1.0f, 0.5f, 0.0f, 1.0f }; // "#FF8000" while (tool_colors.size() < std::max(1, gcode_result.extruders_count)) { tool_colors.push_back(default_color); - } - - std::vector colors; - colors.reserve(tool_colors.size()); - for (const ColorRGBA& color : tool_colors) { - colors.emplace_back(libvgcode::convert(color)); - } - m_viewer.set_tool_colors(colors); - + } + + std::vector colors; + colors.reserve(tool_colors.size()); + for (const ColorRGBA& color : tool_colors) { + colors.emplace_back(libvgcode::convert(color)); + } + m_viewer.set_tool_colors(colors); + // avoid processing if called with the same gcode_result if (m_last_result_id == gcode_result.id) return; - + m_last_result_id = gcode_result.id; - + // release gpu memory, if used reset(); - - // convert data from PrusaSlicer format to libvgcode format - libvgcode::GCodeInputData data = libvgcode::convert(gcode_result, m_viewer.get_travels_radius(), m_viewer.get_wipes_radius()); - - // send data to the viewer + + // convert data from PrusaSlicer format to libvgcode format + libvgcode::GCodeInputData data = libvgcode::convert(gcode_result, m_viewer.get_travels_radius(), m_viewer.get_wipes_radius()); + + // send data to the viewer m_viewer.reset_default_extrusion_roles_colors(); m_viewer.load(std::move(data)); @@ -1339,11 +1339,11 @@ void GCodeViewer::load_as_preview(libvgcode::GCodeInputData&& data, const std::v if (!str_tool_colors.empty()) { std::vector tool_colors; decode_colors(str_tool_colors, tool_colors); - std::vector colors; - colors.reserve(tool_colors.size()); - for (const ColorRGBA& color : tool_colors) { - colors.emplace_back(libvgcode::convert(color)); - } + std::vector colors; + colors.reserve(tool_colors.size()); + for (const ColorRGBA& color : tool_colors) { + colors.emplace_back(libvgcode::convert(color)); + } m_viewer.set_tool_colors(colors); } @@ -1569,40 +1569,40 @@ void GCodeViewer::render() //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER -#if !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS +#if !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS if (is_legend_shown()) { - ImGuiWrapper& imgui = *Slic3r::GUI::wxGetApp().imgui(); + ImGuiWrapper& imgui = *Slic3r::GUI::wxGetApp().imgui(); const Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); imgui.set_next_window_pos(static_cast(cnv_size.get_width()), static_cast(cnv_size.get_height()), ImGuiCond_Always, 1.0f, 1.0f); - imgui.begin(std::string("LibVGCode Viewer Controller"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize); - - imgui.checkbox("Cog marker fixed screen size", m_cog_marker_fixed_screen_size); - if (ImGui::BeginTable("Cog", 2)) { - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - imgui.text_colored(Slic3r::GUI::ImGuiWrapper::COL_ORANGE_LIGHT, "Cog marker size"); - ImGui::TableSetColumnIndex(1); - imgui.slider_float("##CogSize", &m_cog_marker_size, 1.0f, 5.0f); - - ImGui::EndTable(); - } - - imgui.checkbox("Tool marker fixed screen size", m_tool_marker_fixed_screen_size); - if (ImGui::BeginTable("Tool", 2)) { - - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - imgui.text_colored(Slic3r::GUI::ImGuiWrapper::COL_ORANGE_LIGHT, "Tool marker size"); - ImGui::TableSetColumnIndex(1); - imgui.slider_float("##ToolSize", &m_tool_marker_size, 1.0f, 5.0f); - - ImGui::EndTable(); - } - - imgui.end(); - } -#endif // !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS + imgui.begin(std::string("LibVGCode Viewer Controller"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize); + + imgui.checkbox("Cog marker fixed screen size", m_cog_marker_fixed_screen_size); + if (ImGui::BeginTable("Cog", 2)) { + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + imgui.text_colored(Slic3r::GUI::ImGuiWrapper::COL_ORANGE_LIGHT, "Cog marker size"); + ImGui::TableSetColumnIndex(1); + imgui.slider_float("##CogSize", &m_cog_marker_size, 1.0f, 5.0f); + + ImGui::EndTable(); + } + + imgui.checkbox("Tool marker fixed screen size", m_tool_marker_fixed_screen_size); + if (ImGui::BeginTable("Tool", 2)) { + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + imgui.text_colored(Slic3r::GUI::ImGuiWrapper::COL_ORANGE_LIGHT, "Tool marker size"); + ImGui::TableSetColumnIndex(1); + imgui.slider_float("##ToolSize", &m_tool_marker_size, 1.0f, 5.0f); + + ImGui::EndTable(); + } + + imgui.end(); + } +#endif // !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS #endif // ENABLE_NEW_GCODE_VIEWER //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } @@ -1611,7 +1611,11 @@ bool GCodeViewer::can_export_toolpaths() const { //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER - // TODO: Fix the export to obj first + const std::array& visible_range = m_viewer.get_view_visible_range(); + for (size_t i = visible_range[0]; i <= visible_range[1]; ++i) { + if (m_viewer.get_vertex_at(i).is_extrusion()) + return true; + } return false; #else //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -1756,6 +1760,307 @@ void GCodeViewer::set_layers_z_range(const std::array& layers_z //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +#if ENABLE_NEW_GCODE_VIEWER +class ToolpathsObjExporter +{ +public: + explicit ToolpathsObjExporter(const libvgcode::Viewer& viewer) + : m_viewer(viewer) { + } + + void export_to(const std::string& filename) { + CNumericLocalesSetter locales_setter; + + // open geometry file + FilePtr f_geo = boost::nowide::fopen(filename.c_str(), "w"); + if (f_geo.f == nullptr) { + BOOST_LOG_TRIVIAL(error) << "ToolpathsObjExporter: Couldn't open " << filename << " for writing"; + return; + } + + boost::filesystem::path materials_filename(filename); + materials_filename.replace_extension("mtl"); + + // write header to geometry file + fprintf(f_geo.f, "# G-Code Toolpaths\n"); + fprintf(f_geo.f, "# Generated by %s-%s based on Slic3r\n", SLIC3R_APP_NAME, SLIC3R_VERSION); + fprintf(f_geo.f, "\nmtllib ./%s\n", materials_filename.filename().string().c_str()); + + // open material file + FilePtr f_mat = boost::nowide::fopen(materials_filename.string().c_str(), "w"); + if (f_mat.f == nullptr) { + BOOST_LOG_TRIVIAL(error) << "ToolpathsObjExporter: Couldn't open " << materials_filename.string() << " for writing"; + return; + } + + // write header to material file + fprintf(f_mat.f, "# G-Code Toolpaths Materials\n"); + fprintf(f_mat.f, "# Generated by %s-%s based on Slic3r\n", SLIC3R_APP_NAME, SLIC3R_VERSION); + + const std::array& visible_range = m_viewer.get_view_visible_range(); + for (size_t i = visible_range[0]; i <= visible_range[1]; ++i) { + const libvgcode::PathVertex& curr = m_viewer.get_vertex_at(i); + const libvgcode::PathVertex& next = m_viewer.get_vertex_at(i + 1); + if (!curr.is_extrusion() || !next.is_extrusion()) + continue; + const libvgcode::PathVertex& nextnext = m_viewer.get_vertex_at(i + 2); + unsigned char flags = 0; + if (curr.gcode_id == next.gcode_id) + flags |= Flag_First; + if (!nextnext.is_extrusion()) + flags |= Flag_Last; + else + flags |= Flag_Internal; + export_segment(*f_geo.f, flags, curr, next, nextnext); + } + export_materials(*f_mat.f); + } + +private: + const libvgcode::Viewer& m_viewer; + size_t m_vertices_count{ 0 }; + std::vector m_colors; + static const unsigned char Flag_First = 0x01; + static const unsigned char Flag_Last = 0x02; + static const unsigned char Flag_Internal = 0x04; + unsigned char m_flags{ 0 }; + static const float Cap_Rounding_Factor; + + struct SegmentLocalSystem + { + Vec3f forward; + Vec3f right; + Vec3f up; + }; + + SegmentLocalSystem segment_local_system(const Vec3f& v1, const Vec3f& v2) { + SegmentLocalSystem ret; + const Vec3f line = v2 - v1; + const float line_sqlen = line.squaredNorm(); + ret.forward = (line_sqlen < 1e-4) ? Vec3f::UnitX() : line.normalized(); + ret.right = ret.forward.cross(Vec3f::UnitZ()).normalized(); + ret.up = ret.right.cross(ret.forward); + return ret; + } + + struct Vertex + { + Vec3f position; + Vec3f normal; + }; + + struct VertexCrossSection + { + Vertex right; + Vertex top; + Vertex left; + Vertex bottom; + }; + + VertexCrossSection cross_section(const Vec3f& v, const Vec3f& right, const Vec3f& up, float width, float height) { + VertexCrossSection ret; + const Vec3f w_shift = 0.5f * width * right; + const Vec3f h_shift = 0.5f * height * up; + ret.right.position = v + w_shift; + ret.right.normal = right; + ret.top.position = v + h_shift; + ret.top.normal = up; + ret.left.position = v - w_shift; + ret.left.normal = -right; + ret.bottom.position = v - h_shift; + ret.bottom.normal = -up; + return ret; + } + + VertexCrossSection normal_cross_section(const Vec3f& v, const SegmentLocalSystem& axes, float width, float height) { + return cross_section(v, axes.right, axes.up, width, height); + } + + enum CornerType : unsigned char + { + RightTurn, + LeftTurn, + Straight + }; + + VertexCrossSection corner_cross_section(const Vec3f& v, const SegmentLocalSystem& axes1, const SegmentLocalSystem& axes2, + float width, float height, CornerType& corner_type) { + if (std::abs(std::abs(axes1.forward.dot(axes2.forward)) - 1.0f) < EPSILON) + corner_type = CornerType::Straight; + else if (axes1.up.dot(axes1.forward.cross(axes2.forward)) < 0.0f) + corner_type = CornerType::RightTurn; + else + corner_type = CornerType::LeftTurn; + const Vec3f right = (0.5f * (axes1.right + axes2.right)).normalized(); + return cross_section(v, right, axes1.up, width, height); + } + + void export_segment(FILE& f, unsigned char flags, const libvgcode::PathVertex& v1, const libvgcode::PathVertex& v2, const libvgcode::PathVertex& v3) { + const Vec3f v1_pos = libvgcode::convert(v1.position); + const Vec3f v2_pos = libvgcode::convert(v2.position); + const Vec3f v3_pos = libvgcode::convert(v3.position); + const SegmentLocalSystem v1_v2 = segment_local_system(v1_pos, v2_pos); + const SegmentLocalSystem v2_v3 = segment_local_system(v2_pos, v3_pos); + + // starting cap + if ((flags & Flag_First) > 0) { + const Vertex v0 = { v1_pos - Cap_Rounding_Factor * v1.width * v1_v2.forward, -v1_v2.forward }; + const VertexCrossSection ncs = normal_cross_section(v1_pos, v1_v2, v1.width, v1.height); + export_vertex(f, v0); // 0 + export_vertex(f, ncs.right); // 1 + export_vertex(f, ncs.top); // 2 + export_vertex(f, ncs.left); // 3 + export_vertex(f, ncs.bottom); // 4 + export_material(f, color_id(v1)); + export_triangle(f, vertex_id(0), vertex_id(1), vertex_id(2)); + export_triangle(f, vertex_id(0), vertex_id(2), vertex_id(3)); + export_triangle(f, vertex_id(0), vertex_id(3), vertex_id(4)); + export_triangle(f, vertex_id(0), vertex_id(4), vertex_id(1)); + m_vertices_count += 5; + } + // segment body + ending cap + if ((flags & Flag_Last) > 0) { + const Vertex v0 = { v2_pos + Cap_Rounding_Factor * v2.width * v1_v2.forward, v1_v2.forward }; + const VertexCrossSection ncs = normal_cross_section(v2_pos, v1_v2, v2.width, v2.height); + export_vertex(f, v0); // 0 + export_vertex(f, ncs.right); // 1 + export_vertex(f, ncs.top); // 2 + export_vertex(f, ncs.left); // 3 + export_vertex(f, ncs.bottom); // 4 + export_material(f, color_id(v2)); + // segment body + export_triangle(f, vertex_id(-4), vertex_id(1), vertex_id(2)); + export_triangle(f, vertex_id(-4), vertex_id(2), vertex_id(-3)); + export_triangle(f, vertex_id(-3), vertex_id(2), vertex_id(3)); + export_triangle(f, vertex_id(-3), vertex_id(3), vertex_id(-2)); + export_triangle(f, vertex_id(-2), vertex_id(3), vertex_id(4)); + export_triangle(f, vertex_id(-2), vertex_id(4), vertex_id(-1)); + export_triangle(f, vertex_id(-1), vertex_id(4), vertex_id(1)); + export_triangle(f, vertex_id(-1), vertex_id(1), vertex_id(-4)); + // ending cap + export_triangle(f, vertex_id(0), vertex_id(3), vertex_id(2)); + export_triangle(f, vertex_id(0), vertex_id(2), vertex_id(1)); + export_triangle(f, vertex_id(0), vertex_id(1), vertex_id(4)); + export_triangle(f, vertex_id(0), vertex_id(4), vertex_id(3)); + m_vertices_count += 5; + } + else { + CornerType corner_type; + const VertexCrossSection ccs = corner_cross_section(v2_pos, v1_v2, v2_v3, v2.width, v2.height, corner_type); + const VertexCrossSection ncs12 = normal_cross_section(v2_pos, v1_v2, v2.width, v2.height); + const VertexCrossSection ncs23 = normal_cross_section(v2_pos, v2_v3, v2.width, v2.height); + if (corner_type == CornerType::Straight) { + export_vertex(f, ncs12.right); // 0 + export_vertex(f, ncs12.top); // 1 + export_vertex(f, ncs12.left); // 2 + export_vertex(f, ncs12.bottom); // 3 + export_material(f, color_id(v2)); + // segment body + export_triangle(f, vertex_id(-4), vertex_id(0), vertex_id(1)); + export_triangle(f, vertex_id(-4), vertex_id(1), vertex_id(-3)); + export_triangle(f, vertex_id(-3), vertex_id(1), vertex_id(2)); + export_triangle(f, vertex_id(-3), vertex_id(2), vertex_id(-2)); + export_triangle(f, vertex_id(-2), vertex_id(2), vertex_id(3)); + export_triangle(f, vertex_id(-2), vertex_id(3), vertex_id(-1)); + export_triangle(f, vertex_id(-1), vertex_id(3), vertex_id(0)); + export_triangle(f, vertex_id(-1), vertex_id(0), vertex_id(-4)); + m_vertices_count += 4; + } + else if (corner_type == CornerType::RightTurn) { + export_vertex(f, ncs12.left); // 0 + export_vertex(f, ccs.left); // 1 + export_vertex(f, ccs.right); // 2 + export_vertex(f, ncs12.top); // 3 + export_vertex(f, ncs23.left); // 4 + export_vertex(f, ncs12.bottom); // 5 + export_material(f, color_id(v2)); + // segment body + export_triangle(f, vertex_id(-4), vertex_id(2), vertex_id(3)); + export_triangle(f, vertex_id(-4), vertex_id(3), vertex_id(-3)); + export_triangle(f, vertex_id(-3), vertex_id(3), vertex_id(0)); + export_triangle(f, vertex_id(-3), vertex_id(0), vertex_id(-2)); + export_triangle(f, vertex_id(-2), vertex_id(0), vertex_id(5)); + export_triangle(f, vertex_id(-2), vertex_id(5), vertex_id(-1)); + export_triangle(f, vertex_id(-1), vertex_id(5), vertex_id(2)); + export_triangle(f, vertex_id(-1), vertex_id(2), vertex_id(-4)); + // corner + export_triangle(f, vertex_id(1), vertex_id(0), vertex_id(3)); + export_triangle(f, vertex_id(1), vertex_id(3), vertex_id(4)); + export_triangle(f, vertex_id(1), vertex_id(4), vertex_id(5)); + export_triangle(f, vertex_id(1), vertex_id(5), vertex_id(0)); + m_vertices_count += 6; + } + else { + export_vertex(f, ncs12.right); // 0 + export_vertex(f, ccs.right); // 1 + export_vertex(f, ncs23.right); // 2 + export_vertex(f, ncs12.top); // 3 + export_vertex(f, ccs.left); // 4 + export_vertex(f, ncs12.bottom); // 5 + export_material(f, color_id(v2)); + // segment body + export_triangle(f, vertex_id(-4), vertex_id(0), vertex_id(3)); + export_triangle(f, vertex_id(-4), vertex_id(3), vertex_id(-3)); + export_triangle(f, vertex_id(-3), vertex_id(3), vertex_id(4)); + export_triangle(f, vertex_id(-3), vertex_id(4), vertex_id(-2)); + export_triangle(f, vertex_id(-2), vertex_id(4), vertex_id(5)); + export_triangle(f, vertex_id(-2), vertex_id(5), vertex_id(-1)); + export_triangle(f, vertex_id(-1), vertex_id(5), vertex_id(0)); + export_triangle(f, vertex_id(-1), vertex_id(0), vertex_id(-4)); + // corner + export_triangle(f, vertex_id(1), vertex_id(2), vertex_id(3)); + export_triangle(f, vertex_id(1), vertex_id(3), vertex_id(0)); + export_triangle(f, vertex_id(1), vertex_id(0), vertex_id(5)); + export_triangle(f, vertex_id(1), vertex_id(5), vertex_id(2)); + m_vertices_count += 6; + } + } + } + + size_t vertex_id(int id) { return static_cast(1 + static_cast(m_vertices_count) + id); } + + void export_vertex(FILE& f, const Vertex& v) { + fprintf(&f, "v %g %g %g\n", v.position.x(), v.position.y(), v.position.z()); + fprintf(&f, "vn %g %g %g\n", v.normal.x(), v.normal.y(), v.normal.z()); + } + + void export_material(FILE& f, size_t material_id) { + fprintf(&f, "\nusemtl material_%zu\n", material_id + 1); + } + + void export_triangle(FILE& f, size_t v1, size_t v2, size_t v3) { + fprintf(&f, "f %zu//%zu %zu//%zu %zu//%zu\n", v1, v1, v2, v2, v3, v3); + } + + void export_materials(FILE& f) { + static const float inv_255 = 1.0f / 255.0f; + size_t materials_counter = 0; + for (const auto& color : m_colors) { + fprintf(&f, "\nnewmtl material_%zu\n", ++materials_counter); + fprintf(&f, "Ka 1 1 1\n"); + fprintf(&f, "Kd %g %g %g\n", static_cast(color[0]) * inv_255, + static_cast(color[1]) * inv_255, + static_cast(color[2]) * inv_255); + fprintf(&f, "Ks 0 0 0\n"); + } + } + + size_t color_id(const libvgcode::PathVertex& v) { + const libvgcode::Color color = m_viewer.get_vertex_color(v); + auto color_it = std::find_if(m_colors.begin(), m_colors.end(), [&color](const libvgcode::Color& m) { return m == color; }); + if (color_it == m_colors.end()) { + m_colors.emplace_back(color); + color_it = std::prev(m_colors.end()); + } + return std::distance(m_colors.begin(), color_it); + } +}; + +const float ToolpathsObjExporter::Cap_Rounding_Factor = 0.25f; +#endif // ENABLE_NEW_GCODE_VIEWER +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + void GCodeViewer::export_toolpaths_to_obj(const char* filename) const { if (filename == nullptr) @@ -1768,7 +2073,8 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER - // TODO -> new export to obj + ToolpathsObjExporter exporter(m_viewer); + exporter.export_to(filename); #else //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // the data needed is contained into the Extrude TBuffer @@ -4573,8 +4879,8 @@ void GCodeViewer::render_legend(float& legend_height) //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER auto role_time_and_percent = [this, time_mode](libvgcode::EGCodeExtrusionRole role) { - const float time = m_viewer.get_extrusion_role_time(role); - return std::make_pair(time, time / time_mode.time); + const float time = m_viewer.get_extrusion_role_time(role); + return std::make_pair(time, time / time_mode.time); }; #else //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -4608,7 +4914,7 @@ void GCodeViewer::render_legend(float& legend_height) #if ENABLE_NEW_GCODE_VIEWER if (curr_view_type == libvgcode::EViewType::FeatureType) { // calculate offsets to align time/percentage data - const std::vector& roles = m_viewer.get_extrusion_roles(); + const std::vector& roles = m_viewer.get_extrusion_roles(); for (libvgcode::EGCodeExtrusionRole role : roles) { assert(static_cast(role) < libvgcode::GCode_Extrusion_Roles_Count); if (static_cast(role) < libvgcode::GCode_Extrusion_Roles_Count) { @@ -4835,7 +5141,7 @@ void GCodeViewer::render_legend(float& legend_height) #if ENABLE_NEW_GCODE_VIEWER const float travels_time = m_viewer.get_travels_time(); max_time_percent = std::max(max_time_percent, travels_time / time_mode.time); - const std::vector& roles = m_viewer.get_extrusion_roles(); + const std::vector& roles = m_viewer.get_extrusion_roles(); for (size_t i = 0; i < roles.size(); ++i) { libvgcode::EGCodeExtrusionRole role = roles[i]; if (static_cast(role) >= libvgcode::GCode_Extrusion_Roles_Count) @@ -5361,7 +5667,7 @@ void GCodeViewer::render_legend(float& legend_height) //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER if (new_view_type == libvgcode::EViewType::Width || new_view_type == libvgcode::EViewType::VolumetricFlowRate) { - const std::vector& roles = m_viewer.get_extrusion_roles(); + const std::vector& roles = m_viewer.get_extrusion_roles(); const auto custom_it = std::find(roles.begin(), roles.end(), libvgcode::EGCodeExtrusionRole::Custom); if (custom_it != roles.end()) { const bool custom_visible = m_viewer.is_extrusion_role_visible((libvgcode::EGCodeExtrusionRole)GCodeExtrusionRole::Custom); @@ -5457,7 +5763,7 @@ void GCodeViewer::render_legend(float& legend_height) if (ImGui::BeginTable("Times", 2)) { //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #if ENABLE_NEW_GCODE_VIEWER - const std::vector layers_times = get_layers_times(); + const std::vector layers_times = get_layers_times(); if (!layers_times.empty()) add_strings_row_to_table(_u8L("First layer") + ":", ImGuiWrapper::COL_ORANGE_LIGHT, short_time_ui(get_time_dhms(layers_times.front())), ImGuiWrapper::to_ImVec4(ColorRGBA::WHITE())); @@ -5548,13 +5854,13 @@ void GCodeViewer::render_legend(float& legend_height) #if ENABLE_NEW_GCODE_VIEWER bool active = false; #if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS - switch (type) - { - case Preview::OptionType::CenterOfGravity: { active = m_cog.is_visible(); break; } - case Preview::OptionType::ToolMarker: { active = m_sequential_view.marker.is_visible(); break; } - case Preview::OptionType::Shells: { active = m_shells.visible; break; } - default: { active = m_viewer.is_option_visible(libvgcode::convert(type)); break; } - } + switch (type) + { + case Preview::OptionType::CenterOfGravity: { active = m_cog.is_visible(); break; } + case Preview::OptionType::ToolMarker: { active = m_sequential_view.marker.is_visible(); break; } + case Preview::OptionType::Shells: { active = m_shells.visible; break; } + default: { active = m_viewer.is_option_visible(libvgcode::convert(type)); break; } + } #else active = (type == Preview::OptionType::Shells) ? m_shells.visible : m_viewer.is_option_visible(libvgcode::convert(type)); #endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS @@ -5581,28 +5887,28 @@ void GCodeViewer::render_legend(float& legend_height) const std::array view_visible_range = m_viewer.get_view_visible_range(); const std::array view_enabled_range = m_viewer.get_view_enabled_range(); bool keep_visible_range = false; -#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS - switch (type) - { - case Preview::OptionType::CenterOfGravity: { m_cog.set_visible(!active); break; } - case Preview::OptionType::ToolMarker: { m_sequential_view.marker.set_visible(!active); break; } - case Preview::OptionType::Shells: { m_shells.visible = !active; break; } - default: { - m_viewer.toggle_option_visibility(libvgcode::convert(type)); - if (view_visible_range != view_enabled_range) - keep_visible_range = true; - break; - } - } -#else - if (type == Preview::OptionType::Shells) - m_shells.visible = !active; - else { +#if ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS + switch (type) + { + case Preview::OptionType::CenterOfGravity: { m_cog.set_visible(!active); break; } + case Preview::OptionType::ToolMarker: { m_sequential_view.marker.set_visible(!active); break; } + case Preview::OptionType::Shells: { m_shells.visible = !active; break; } + default: { m_viewer.toggle_option_visibility(libvgcode::convert(type)); - if (view_visible_range != view_enabled_range) - keep_visible_range = true; + if (view_visible_range != view_enabled_range) + keep_visible_range = true; + break; } -#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS + } +#else + if (type == Preview::OptionType::Shells) + m_shells.visible = !active; + else { + m_viewer.toggle_option_visibility(libvgcode::convert(type)); + if (view_visible_range != view_enabled_range) + keep_visible_range = true; + } +#endif // ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS std::optional view_visible_range_min; std::optional view_visible_range_max; if (keep_visible_range) { diff --git a/src/slic3r/GUI/LibVGCode/include/Viewer.hpp b/src/slic3r/GUI/LibVGCode/include/Viewer.hpp index c1e6bc2a4f..e89182e75a 100644 --- a/src/slic3r/GUI/LibVGCode/include/Viewer.hpp +++ b/src/slic3r/GUI/LibVGCode/include/Viewer.hpp @@ -89,6 +89,8 @@ public: // PathVertex get_vertex_at(uint32_t id) const; + Color get_vertex_color(const PathVertex& vertex) const; + // // Return the count of path segments enabled for rendering // diff --git a/src/slic3r/GUI/LibVGCode/src/Viewer.cpp b/src/slic3r/GUI/LibVGCode/src/Viewer.cpp index c36e696f9a..6663f129d5 100644 --- a/src/slic3r/GUI/LibVGCode/src/Viewer.cpp +++ b/src/slic3r/GUI/LibVGCode/src/Viewer.cpp @@ -182,6 +182,11 @@ PathVertex Viewer::get_vertex_at(uint32_t id) const return m_impl->get_vertex_at(id); } +Color Viewer::get_vertex_color(const PathVertex& vertex) const +{ + return m_impl->get_vertex_color(vertex); +} + size_t Viewer::get_enabled_segments_count() const { return m_impl->get_enabled_segments_count(); diff --git a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp index d121831251..b28ea83489 100644 --- a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp +++ b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.cpp @@ -703,7 +703,7 @@ void ViewerImpl::update_colors() for (size_t i = 0; i < m_vertices.size(); ++i) { colors[i] = (color_top_layer_only && m_vertices[i].layer_id < top_layer_id && (!m_settings.spiral_vase_mode || i != m_view_range.get_enabled()[0])) ? - encode_color(Dummy_Color) : encode_color(select_color(m_vertices[i])); + encode_color(Dummy_Color) : encode_color(get_vertex_color(m_vertices[i])); } // update gpu buffer for colors @@ -933,6 +933,73 @@ PathVertex ViewerImpl::get_vertex_at(size_t id) const return (id < m_vertices.size()) ? m_vertices[id] : PathVertex(); } +Color ViewerImpl::get_vertex_color(const PathVertex& v) const +{ + if (v.type == EMoveType::Noop) + return Dummy_Color; + + if (v.is_wipe()) + return Wipe_Color; + + if (v.is_option()) + return get_option_color(type_to_option(v.type)); + + switch (m_settings.view_type) + { + case EViewType::FeatureType: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : get_extrusion_role_color(v.role); + } + case EViewType::Height: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_height_range.get_color_at(v.height); + } + case EViewType::Width: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_width_range.get_color_at(v.width); + } + case EViewType::Speed: + { + return m_speed_range.get_color_at(v.feedrate); + } + case EViewType::FanSpeed: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_fan_speed_range.get_color_at(v.fan_speed); + } + case EViewType::Temperature: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_temperature_range.get_color_at(v.temperature); + } + case EViewType::VolumetricFlowRate: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_volumetric_rate_range.get_color_at(v.volumetric_rate); + } + case EViewType::LayerTimeLinear: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : + m_layer_time_range[0].get_color_at(m_layers.get_layer_time(m_settings.time_mode, static_cast(v.layer_id))); + } + case EViewType::LayerTimeLogarithmic: + { + return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : + m_layer_time_range[1].get_color_at(m_layers.get_layer_time(m_settings.time_mode, static_cast(v.layer_id))); + } + case EViewType::Tool: + { + assert(static_cast(v.extruder_id) < m_tool_colors.size()); + return m_tool_colors[v.extruder_id]; + } + case EViewType::ColorPrint: + { + return m_layers.layer_contains_colorprint_options(static_cast(v.layer_id)) ? Dummy_Color : + m_tool_colors[static_cast(v.color_id) % m_tool_colors.size()]; + } + default: { break; } + } + + return Dummy_Color; +} + size_t ViewerImpl::get_enabled_segments_count() const { return m_enabled_segments_count; @@ -1369,73 +1436,6 @@ void ViewerImpl::update_heights_widths() glsafe(glBindBuffer(GL_TEXTURE_BUFFER, 0)); } -Color ViewerImpl::select_color(const PathVertex& v) const -{ - if (v.type == EMoveType::Noop) - return Dummy_Color; - - if (v.is_wipe()) - return Wipe_Color; - - if (v.is_option()) - return get_option_color(type_to_option(v.type)); - - switch (m_settings.view_type) - { - case EViewType::FeatureType: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : get_extrusion_role_color(v.role); - } - case EViewType::Height: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_height_range.get_color_at(v.height); - } - case EViewType::Width: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_width_range.get_color_at(v.width); - } - case EViewType::Speed: - { - return m_speed_range.get_color_at(v.feedrate); - } - case EViewType::FanSpeed: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_fan_speed_range.get_color_at(v.fan_speed); - } - case EViewType::Temperature: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_temperature_range.get_color_at(v.temperature); - } - case EViewType::VolumetricFlowRate: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : m_volumetric_rate_range.get_color_at(v.volumetric_rate); - } - case EViewType::LayerTimeLinear: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : - m_layer_time_range[0].get_color_at(m_layers.get_layer_time(m_settings.time_mode, static_cast(v.layer_id))); - } - case EViewType::LayerTimeLogarithmic: - { - return v.is_travel() ? get_travel_move_color(static_cast(v.role)) : - m_layer_time_range[1].get_color_at(m_layers.get_layer_time(m_settings.time_mode, static_cast(v.layer_id))); - } - case EViewType::Tool: - { - assert(static_cast(v.extruder_id) < m_tool_colors.size()); - return m_tool_colors[v.extruder_id]; - } - case EViewType::ColorPrint: - { - return m_layers.layer_contains_colorprint_options(static_cast(v.layer_id)) ? Dummy_Color : - m_tool_colors[static_cast(v.color_id) % m_tool_colors.size()]; - } - default: { break; } - } - - return Dummy_Color; -} - void ViewerImpl::render_segments(const Mat4x4& view_matrix, const Mat4x4& projection_matrix, const Vec3& camera_position) { if (m_segments_shader_id == 0) diff --git a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp index 50d422f0ed..1d62a8bf5a 100644 --- a/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp +++ b/src/slic3r/GUI/LibVGCode/src/ViewerImpl.hpp @@ -109,6 +109,7 @@ public: size_t get_vertices_count() const; PathVertex get_current_vertex() const; PathVertex get_vertex_at(size_t id) const; + Color get_vertex_color(const PathVertex& vertex) const; size_t get_enabled_segments_count() const; const std::array& get_enabled_segments_range() const; @@ -328,7 +329,6 @@ private: void update_view_full_range(); void update_color_ranges(); void update_heights_widths(); - Color select_color(const PathVertex& vertex) const; void render_segments(const Mat4x4& view_matrix, const Mat4x4& projection_matrix, const Vec3& camera_position); void render_options(const Mat4x4& view_matrix, const Mat4x4& projection_matrix); #if !ENABLE_NEW_GCODE_VIEWER_NO_COG_AND_TOOL_MARKERS