diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 36ae514bcf..e7ef65e83b 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -4626,16 +4626,19 @@ void GCodeProcessor::calculate_time(GCodeProcessorResult& result, size_t keep_la actual_speed_moves = std::move(machine.actual_speed_moves); } - // insert actual speed moves into the move list - unsigned int inserted_actual_speed_moves_count = 0; - std::vector new_moves; + // insert actual speed moves into the move list. We will do this in two stages (to avoid inserting in the middle of + // result.moves repeatedly). First, we create individual vectors of MoveVertices, and store them along with their + // required index in the result.moves vector after they are all inserted. Then we go through the destination + // vector once and move all the elements where we want them in one go. + std::vector>> moves_to_insert = {std::make_pair(0, std::vector{})}; + size_t inserted_count = 0; std::map id_map; for (auto it = actual_speed_moves.begin(); it != actual_speed_moves.end(); ++it) { - const unsigned int base_id = it->move_id + inserted_actual_speed_moves_count; + const unsigned int base_id_old = it->move_id; if (it->position.has_value()) { // insert actual speed move into the move list // clone from existing move - GCodeProcessorResult::MoveVertex new_move = result.moves[base_id]; + GCodeProcessorResult::MoveVertex new_move = result.moves[base_id_old]; // override modified parameters new_move.time = { 0.0f, 0.0f }; new_move.position = *it->position; @@ -4648,29 +4651,47 @@ void GCodeProcessor::calculate_time(GCodeProcessorResult& result, size_t keep_la new_move.fan_speed = *it->fan_speed; new_move.temperature = *it->temperature; new_move.internal_only = true; - new_moves.push_back(new_move); + moves_to_insert.back().second.emplace_back(new_move); } else { - result.moves.insert(result.moves.begin() + base_id, new_moves.begin(), new_moves.end()); - id_map[it->move_id] = base_id + new_moves.size(); - // update move actual speed - result.moves[base_id + new_moves.size()].actual_feedrate = it->actual_feedrate; - inserted_actual_speed_moves_count += new_moves.size(); + moves_to_insert.back().first = base_id_old + inserted_count; // Save required position of this range in the NEW vector. + id_map[base_id_old] = base_id_old + inserted_count; // Remember where the old element will end up. + inserted_count += moves_to_insert.back().second.size(); // Increase the number of moves that are already planned to be added. + + result.moves[base_id_old].actual_feedrate = it->actual_feedrate; // update move actual speed + // synchronize seams actual speed - if (base_id + new_moves.size() + 1 < result.moves.size()) { - GCodeProcessorResult::MoveVertex& move = result.moves[base_id + new_moves.size() + 1]; + if (base_id_old + 1 < result.moves.size()) { + GCodeProcessorResult::MoveVertex& move = result.moves[base_id_old + 1]; if (move.type == EMoveType::Seam) move.actual_feedrate = it->actual_feedrate; } - new_moves.clear(); + moves_to_insert.emplace_back(std::make_pair(0, std::vector{})); } } + // Now actually do the insertion of the ranges into the destination vector. + std::vector& m = result.moves; + size_t offset = inserted_count; + m.resize(m.size() + offset); // grow the vector to its final size + size_t last_pos = m.size() - 1; // index of the last element that still needs to be moved + for (auto it = moves_to_insert.rbegin(); it != moves_to_insert.rend(); ++it) { + const auto& [new_pos, new_moves] = *it; + if (new_moves.empty()) + continue; + for (int i = last_pos; i >= new_pos + new_moves.size(); --i) // Move the elements to their final place. + m[i] = m[i - offset]; + std::copy(new_moves.begin(), new_moves.end(), m.begin() + new_pos); + last_pos = new_pos - 1; + offset -= new_moves.size(); + } + assert(offset == 0); + // synchronize blocks' move_ids with after moves for actual speed insertion for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { for (GCodeProcessor::TimeBlock& block : m_time_processor.machines[i].blocks) { auto it = id_map.find(block.move_id); - block.move_id = (it != id_map.end()) ? it->second : block.move_id + inserted_actual_speed_moves_count; + block.move_id = (it != id_map.end()) ? it->second : block.move_id + inserted_count; } } } diff --git a/src/libvgcode/include/Types.hpp b/src/libvgcode/include/Types.hpp index 53ceff7581..a18712f7ba 100644 --- a/src/libvgcode/include/Types.hpp +++ b/src/libvgcode/include/Types.hpp @@ -123,6 +123,8 @@ static constexpr std::size_t MOVE_TYPES_COUNT = static_cast(EMoveTy // enum class EGCodeExtrusionRole : uint8_t { + // This enum is used as in index into extrusion_roles_visibility. + // Better only add things to the end. None, Perimeter, ExternalPerimeter, @@ -148,6 +150,8 @@ static constexpr std::size_t GCODE_EXTRUSION_ROLES_COUNT = static_cast options_visibility{ { - { EOptionType::Travels, false }, - { EOptionType::Wipes, false }, - { EOptionType::Retractions, false }, - { EOptionType::Unretractions, false }, - { EOptionType::Seams, false }, - { EOptionType::ToolChanges, false }, - { EOptionType::ColorChanges, false }, - { EOptionType::PausePrints, false }, - { EOptionType::CustomGCodes, false }, + std::array options_visibility{ + false, // Travels + false, // Wipes + false, // Retractions + false, // Unretractions + false, // Seams + false, // ToolChanges + false, // ColorChanges + false, // PausePrints + false, // CustomGCodes #if VGCODE_ENABLE_COG_AND_TOOL_MARKERS - { EOptionType::CenterOfGravity, false }, - { EOptionType::ToolMarker, true } + false, // CenterOfGravity + true // ToolMarker #endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS - } }; + }; - std::map extrusion_roles_visibility{ { - { EGCodeExtrusionRole::None, true }, - { EGCodeExtrusionRole::Perimeter, true }, - { EGCodeExtrusionRole::ExternalPerimeter, true }, - { EGCodeExtrusionRole::OverhangPerimeter, true }, - { EGCodeExtrusionRole::InternalInfill, true }, - { EGCodeExtrusionRole::SolidInfill, true }, - { EGCodeExtrusionRole::TopSolidInfill, true }, - { EGCodeExtrusionRole::Ironing, true }, - { EGCodeExtrusionRole::BridgeInfill, true }, - { EGCodeExtrusionRole::GapFill, true }, - { EGCodeExtrusionRole::Skirt, true }, - { EGCodeExtrusionRole::SupportMaterial, true }, - { EGCodeExtrusionRole::SupportMaterialInterface, true }, - { EGCodeExtrusionRole::WipeTower, true }, - { EGCodeExtrusionRole::Custom, true } - } }; + std::array extrusion_roles_visibility{ + true, // None + true, // Perimeter + true, // ExternalPerimeter + true, // OverhangPerimeter + true, // InternalInfill + true, // SolidInfill + true, // TopSolidInfill + true, // Ironing + true, // BridgeInfill + true, // GapFill + true, // Skirt + true, // SupportMaterial + true, // SupportMaterialInterface + true, // WipeTower + true // Custom + }; }; } // namespace libvgcode diff --git a/src/libvgcode/src/ViewerImpl.cpp b/src/libvgcode/src/ViewerImpl.cpp index f607304147..bf09add366 100644 --- a/src/libvgcode/src/ViewerImpl.cpp +++ b/src/libvgcode/src/ViewerImpl.cpp @@ -280,34 +280,34 @@ static void delete_buffers(unsigned int& id) } } -static const std::map DEFAULT_EXTRUSION_ROLES_COLORS{ { - { EGCodeExtrusionRole::None, { 230, 179, 179 } }, - { EGCodeExtrusionRole::Perimeter, { 255, 230, 77 } }, - { EGCodeExtrusionRole::ExternalPerimeter, { 255, 125, 56 } }, - { EGCodeExtrusionRole::OverhangPerimeter, { 31, 31, 255 } }, - { EGCodeExtrusionRole::InternalInfill, { 176, 48, 41 } }, - { EGCodeExtrusionRole::SolidInfill, { 150, 84, 204 } }, - { EGCodeExtrusionRole::TopSolidInfill, { 240, 64, 64 } }, - { EGCodeExtrusionRole::Ironing, { 255, 140, 105 } }, - { EGCodeExtrusionRole::BridgeInfill, { 77, 128, 186 } }, - { EGCodeExtrusionRole::GapFill, { 255, 255, 255 } }, - { EGCodeExtrusionRole::Skirt, { 0, 135, 110 } }, - { EGCodeExtrusionRole::SupportMaterial, { 0, 255, 0 } }, - { EGCodeExtrusionRole::SupportMaterialInterface, { 0, 128, 0 } }, - { EGCodeExtrusionRole::WipeTower, { 179, 227, 171 } }, - { EGCodeExtrusionRole::Custom, { 94, 209, 148 } } +static const std::array DEFAULT_EXTRUSION_ROLES_COLORS = { { + { 230, 179, 179 }, // None + { 255, 230, 77 }, // Perimeter + { 255, 125, 56 }, // ExternalPerimeter + { 31, 31, 255 }, // OverhangPerimeter + { 176, 48, 41 }, // InternalInfill + { 150, 84, 204 }, // SolidInfill + { 240, 64, 64 }, // TopSolidInfill + { 255, 140, 105 }, // Ironing + { 77, 128, 186 }, // BridgeInfill + { 255, 255, 255 }, // GapFill + { 0, 135, 110 }, // Skirt + { 0, 255, 0 }, // SupportMaterial + { 0, 128, 0 }, // SupportMaterialInterface + { 179, 227, 171 }, // WipeTower + { 94, 209, 148 } // Custom } }; -static const std::map DEFAULT_OPTIONS_COLORS{ { - { EOptionType::Travels, { 56, 72, 155 } }, - { EOptionType::Wipes, { 255, 255, 0 } }, - { EOptionType::Retractions, { 205, 34, 214 } }, - { EOptionType::Unretractions, { 73, 173, 207 } }, - { EOptionType::Seams, { 230, 230, 230 } }, - { EOptionType::ToolChanges, { 193, 190, 99 } }, - { EOptionType::ColorChanges, { 218, 148, 139 } }, - { EOptionType::PausePrints, { 82, 240, 131 } }, - { EOptionType::CustomGCodes, { 226, 210, 67 } } +static const std::array DEFAULT_OPTIONS_COLORS{ { + { 56, 72, 155 }, // Travels + { 255, 255, 0 }, // Wipes + { 205, 34, 214 }, // Retractions + { 73, 173, 207 }, // Unretractions + { 230, 230, 230 }, // Seams + { 193, 190, 99 }, // ToolChanges + { 218, 148, 139 }, // ColorChanges + { 82, 240, 131 }, // PausePrints + { 226, 210, 67 } // CustomGCodes } }; #ifdef ENABLE_OPENGL_ES @@ -868,6 +868,7 @@ void ViewerImpl::reset() m_total_time = { 0.0f, 0.0f }; m_travels_time = { 0.0f, 0.0f }; m_vertices.clear(); + m_vertices_colors.clear(); m_valid_lines_bitset.clear(); #if VGCODE_ENABLE_COG_AND_TOOL_MARKERS m_cog_marker.reset(); @@ -879,6 +880,8 @@ void ViewerImpl::reset() m_enabled_segments_count = 0; m_enabled_options_count = 0; + m_settings_used_for_ranges = std::nullopt; + delete_textures(m_enabled_options_tex_id); delete_buffers(m_enabled_options_buf_id); delete_textures(m_enabled_segments_tex_id); @@ -966,11 +969,10 @@ void ViewerImpl::load(GCodeInputData&& gcode_data) reset(); - m_loading = true; - m_vertices = std::move(gcode_data.vertices); m_tool_colors = std::move(gcode_data.tools_colors); m_color_print_colors = std::move(gcode_data.color_print_colors); + m_vertices_colors.resize(m_vertices.size()); m_settings.spiral_vase_mode = gcode_data.spiral_vase_mode; @@ -1092,8 +1094,6 @@ void ViewerImpl::load(GCodeInputData&& gcode_data) m_view_range.set_visible(m_view_range.get_enabled()); update_enabled_entities(); update_colors(); - - m_loading = false; } void ViewerImpl::update_enabled_entities() @@ -1128,19 +1128,19 @@ void ViewerImpl::update_enabled_entities() if (!m_valid_lines_bitset[i] && !v.is_option()) continue; if (v.is_travel()) { - if (!m_settings.options_visibility.at(EOptionType::Travels)) + if (!m_settings.options_visibility[size_t(EOptionType::Travels)]) continue; } else if (v.is_wipe()) { - if (!m_settings.options_visibility.at(EOptionType::Wipes)) + if (!m_settings.options_visibility[size_t(EOptionType::Wipes)]) continue; } else if (v.is_option()) { - if (!m_settings.options_visibility.at(move_type_to_option(v.type))) + if (!m_settings.options_visibility[size_t(move_type_to_option(v.type))]) continue; } else if (v.is_extrusion()) { - if (!m_settings.extrusion_roles_visibility.at(v.role)) + if (!m_settings.extrusion_roles_visibility[size_t(v.role)]) continue; } else @@ -1192,13 +1192,45 @@ static float encode_color(const Color& color) { return static_cast(i_color); } -void ViewerImpl::update_colors() + +void ViewerImpl::update_colors_texture() { #if !defined(ENABLE_OPENGL_ES) if (m_colors_buf_id == 0) return; #endif // ENABLE_OPENGL_ES + const size_t top_layer_id = m_settings.top_layer_only_view_range ? m_layers.get_view_range()[1] : 0; + const bool color_top_layer_only = m_view_range.get_full()[1] != m_view_range.get_visible()[1]; + + // Based on current settings and slider position, we might want to render some + // vertices as dark grey. Use either that or the normal color (from the cache). + std::vector colors(m_vertices_colors.size()); + assert(colors.size() == m_vertices.size() && m_vertices_colors.size() == m_vertices.size()); + for (size_t i=0; i(m_used_extruders.rbegin()->first); @@ -1211,38 +1243,20 @@ void ViewerImpl::update_colors() } update_color_ranges(); - - const size_t top_layer_id = m_settings.top_layer_only_view_range ? m_layers.get_view_range()[1] : 0; - const bool color_top_layer_only = m_view_range.get_full()[1] != m_view_range.get_visible()[1]; - std::vector colors(m_vertices.size()); - 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(get_vertex_color(m_vertices[i])); - } - -#ifdef ENABLE_OPENGL_ES - if (!colors.empty()) - // update gpu buffer for colors - m_texture_data.set_colors(colors); -#else - m_colors_tex_size = colors.size() * sizeof(float); - - // update gpu buffer for colors - glsafe(glBindBuffer(GL_TEXTURE_BUFFER, m_colors_buf_id)); - glsafe(glBufferData(GL_TEXTURE_BUFFER, colors.size() * sizeof(float), colors.data(), GL_STATIC_DRAW)); - glsafe(glBindBuffer(GL_TEXTURE_BUFFER, 0)); -#endif // ENABLE_OPENGL_ES - + + // Recalculate "normal" colors of all the vertices for current view settings. + // If some part of the preview should be rendered in dark grey, it is taken + // care of in update_colors_texture. That is to avoid the need to recalculate + // the "normal" color on every slider move. + for (size_t i = 0; i < m_vertices.size(); ++i) + m_vertices_colors[i] = encode_color(get_vertex_color(m_vertices[i])); + + update_colors_texture(); m_settings.update_colors = false; } void ViewerImpl::render(const Mat4x4& view_matrix, const Mat4x4& projection_matrix) { - // ensure that the render does take place while loading the data - if (m_loading) - return; - if (m_settings.update_view_full_range) update_view_full_range(); @@ -1258,9 +1272,9 @@ void ViewerImpl::render(const Mat4x4& view_matrix, const Mat4x4& projection_matr render_options(view_matrix, projection_matrix); #if VGCODE_ENABLE_COG_AND_TOOL_MARKERS - if (m_settings.options_visibility.at(EOptionType::ToolMarker)) + if (m_settings.options_visibility[size_t(EOptionType::ToolMarker)]) render_tool_marker(view_matrix, projection_matrix); - if (m_settings.options_visibility.at(EOptionType::CenterOfGravity)) + if (m_settings.options_visibility[size_t(EOptionType::CenterOfGravity)]) render_cog_marker(view_matrix, projection_matrix); #endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS } @@ -1286,7 +1300,8 @@ void ViewerImpl::set_layers_view_range(Interval::value_type min, Interval::value update_view_full_range(); m_view_range.set_visible(m_view_range.get_enabled()); m_settings.update_enabled_entities = true; - m_settings.update_colors = true; + //m_settings.update_colors = true; + update_colors_texture(); } void ViewerImpl::toggle_top_layer_only_view_range() @@ -1295,7 +1310,8 @@ void ViewerImpl::toggle_top_layer_only_view_range() update_view_full_range(); m_view_range.set_visible(m_view_range.get_enabled()); m_settings.update_enabled_entities = true; - m_settings.update_colors = true; + //m_settings.update_colors = true; + update_colors_texture(); } std::vector ViewerImpl::get_time_modes() const @@ -1363,45 +1379,37 @@ AABox ViewerImpl::get_extrusion_bounding_box(const std::vectorsecond; + return m_settings.options_visibility[size_t(type)]; } void ViewerImpl::toggle_option_visibility(EOptionType type) { - auto it = m_settings.options_visibility.find(type); - if (it != m_settings.options_visibility.end()) { - it->second = !it->second; - const Interval old_enabled_range = m_view_range.get_enabled(); - update_view_full_range(); - const Interval& new_enabled_range = m_view_range.get_enabled(); - if (old_enabled_range != new_enabled_range) { - const Interval& visible_range = m_view_range.get_visible(); - if (old_enabled_range == visible_range) - m_view_range.set_visible(new_enabled_range); - else if (m_settings.top_layer_only_view_range && new_enabled_range[0] < visible_range[0]) - m_view_range.set_visible(new_enabled_range[0], visible_range[1]); - } - m_settings.update_enabled_entities = true; - m_settings.update_colors = true; + m_settings.options_visibility[size_t(type)] = ! m_settings.options_visibility[size_t(type)]; + const Interval old_enabled_range = m_view_range.get_enabled(); + update_view_full_range(); + const Interval& new_enabled_range = m_view_range.get_enabled(); + if (old_enabled_range != new_enabled_range) { + const Interval& visible_range = m_view_range.get_visible(); + if (old_enabled_range == visible_range) + m_view_range.set_visible(new_enabled_range); + else if (m_settings.top_layer_only_view_range && new_enabled_range[0] < visible_range[0]) + m_view_range.set_visible(new_enabled_range[0], visible_range[1]); } + m_settings.update_enabled_entities = true; + m_settings.update_colors = true; } bool ViewerImpl::is_extrusion_role_visible(EGCodeExtrusionRole role) const { - const auto it = m_settings.extrusion_roles_visibility.find(role); - return (it == m_settings.extrusion_roles_visibility.end()) ? false : it->second; + return m_settings.extrusion_roles_visibility[size_t(role)]; } void ViewerImpl::toggle_extrusion_role_visibility(EGCodeExtrusionRole role) { - auto it = m_settings.extrusion_roles_visibility.find(role); - if (it != m_settings.extrusion_roles_visibility.end()) { - it->second = !it->second; - update_view_full_range(); - m_settings.update_enabled_entities = true; - m_settings.update_colors = true; - } + m_settings.extrusion_roles_visibility[size_t(role)] = ! m_settings.extrusion_roles_visibility[size_t(role)]; + update_view_full_range(); + m_settings.update_enabled_entities = true; + m_settings.update_colors = true; } void ViewerImpl::set_view_visible_range(Interval::value_type min, Interval::value_type max) @@ -1411,7 +1419,8 @@ void ViewerImpl::set_view_visible_range(Interval::value_type min, Interval::valu update_view_full_range(); m_view_range.set_visible(min, max); update_enabled_entities(); - m_settings.update_colors = true; + //m_settings.update_colors = true; + update_colors_texture(); } float ViewerImpl::get_estimated_time_at(size_t id) const @@ -1506,17 +1515,13 @@ void ViewerImpl::set_color_print_colors(const Palette& colors) const Color& ViewerImpl::get_extrusion_role_color(EGCodeExtrusionRole role) const { - const auto it = m_extrusion_roles_colors.find(role); - return (it == m_extrusion_roles_colors.end()) ? DUMMY_COLOR : it->second; + return m_extrusion_roles_colors[size_t(role)]; } void ViewerImpl::set_extrusion_role_color(EGCodeExtrusionRole role, const Color& color) { - auto it = m_extrusion_roles_colors.find(role); - if (it != m_extrusion_roles_colors.end()) { - it->second = color; - m_settings.update_colors = true; - } + m_extrusion_roles_colors[size_t(role)] = color; + m_settings.update_colors = true; } void ViewerImpl::reset_default_extrusion_roles_colors() @@ -1526,17 +1531,13 @@ void ViewerImpl::reset_default_extrusion_roles_colors() const Color& ViewerImpl::get_option_color(EOptionType type) const { - const auto it = m_options_colors.find(type); - return (it == m_options_colors.end()) ? DUMMY_COLOR : it->second; + return m_options_colors[size_t(type)]; } void ViewerImpl::set_option_color(EOptionType type, const Color& color) { - auto it = m_options_colors.find(type); - if (it != m_options_colors.end()) { - it->second = color; - m_settings.update_colors = true; - } + m_options_colors[size_t(type)] = color; + m_settings.update_colors = true; } void ViewerImpl::reset_default_options_colors() @@ -1566,16 +1567,16 @@ void ViewerImpl::set_color_range_palette(EViewType type, const Palette& palette) { switch (type) { - case EViewType::Height: { m_height_range.set_palette(palette); } - case EViewType::Width: { m_width_range.set_palette(palette); } - case EViewType::Speed: { m_speed_range.set_palette(palette); } - case EViewType::ActualSpeed: { m_actual_speed_range.set_palette(palette); } - case EViewType::FanSpeed: { m_fan_speed_range.set_palette(palette); } - case EViewType::Temperature: { m_temperature_range.set_palette(palette); } - case EViewType::VolumetricFlowRate: { m_volumetric_rate_range.set_palette(palette); } - case EViewType::ActualVolumetricFlowRate: { m_actual_volumetric_rate_range.set_palette(palette); } - case EViewType::LayerTimeLinear: { m_layer_time_range[0].set_palette(palette); } - case EViewType::LayerTimeLogarithmic: { m_layer_time_range[1].set_palette(palette); } + case EViewType::Height: { m_height_range.set_palette(palette); break; } + case EViewType::Width: { m_width_range.set_palette(palette); break; } + case EViewType::Speed: { m_speed_range.set_palette(palette); break; } + case EViewType::ActualSpeed: { m_actual_speed_range.set_palette(palette); break; } + case EViewType::FanSpeed: { m_fan_speed_range.set_palette(palette); break; } + case EViewType::Temperature: { m_temperature_range.set_palette(palette); break; } + case EViewType::VolumetricFlowRate: { m_volumetric_rate_range.set_palette(palette); break; } + case EViewType::ActualVolumetricFlowRate: { m_actual_volumetric_rate_range.set_palette(palette); break; } + case EViewType::LayerTimeLinear: { m_layer_time_range[0].set_palette(palette); break; } + case EViewType::LayerTimeLogarithmic: { m_layer_time_range[1].set_palette(palette); break; } default: { break; } } m_settings.update_colors = true; @@ -1599,8 +1600,8 @@ size_t ViewerImpl::get_used_cpu_memory() const ret += m_layers.size_in_bytes_cpu(); ret += STDVEC_MEMSIZE(m_options, EOptionType); ret += m_used_extruders.size() * sizeof(std::map::value_type); - ret += m_extrusion_roles_colors.size() * sizeof(std::map::value_type); - ret += m_options_colors.size() * sizeof(std::map::value_type); + ret += sizeof(m_extrusion_roles_colors); + ret += sizeof(m_options_colors); ret += STDVEC_MEMSIZE(m_vertices, PathVertex); ret += m_valid_lines_bitset.size_in_bytes_cpu(); ret += m_height_range.size_in_bytes_cpu(); @@ -1646,8 +1647,8 @@ static bool is_visible(const PathVertex& v, const Settings& settings) try { return (option_type == EOptionType::COUNT) ? - (v.type == EMoveType::Extrude) ? settings.extrusion_roles_visibility.at(v.role) : false : - settings.options_visibility.at(option_type); + (v.type == EMoveType::Extrude) ? settings.extrusion_roles_visibility[size_t(v.role)] : false : + settings.options_visibility[size_t(option_type)]; } catch (...) { @@ -1658,8 +1659,8 @@ static bool is_visible(const PathVertex& v, const Settings& settings) void ViewerImpl::update_view_full_range() { const Interval& layers_range = m_layers.get_view_range(); - const bool travels_visible = m_settings.options_visibility.at(EOptionType::Travels); - const bool wipes_visible = m_settings.options_visibility.at(EOptionType::Wipes); + const bool travels_visible = m_settings.options_visibility[size_t(EOptionType::Travels)]; + const bool wipes_visible = m_settings.options_visibility[size_t(EOptionType::Wipes)]; auto first_it = m_vertices.begin(); while (first_it != m_vertices.end() && @@ -1746,6 +1747,13 @@ void ViewerImpl::update_view_full_range() void ViewerImpl::update_color_ranges() { + // Color ranges do not need to be recalculated that often. If the following settings are the same + // as last time, the current ranges are still valid. The recalculation is quite expensive. + if (m_settings_used_for_ranges.has_value() && + m_settings.extrusion_roles_visibility == m_settings_used_for_ranges->extrusion_roles_visibility && + m_settings.options_visibility == m_settings_used_for_ranges->options_visibility) + return; + m_width_range.reset(); m_height_range.reset(); m_speed_range.reset(); @@ -1761,7 +1769,7 @@ void ViewerImpl::update_color_ranges() const PathVertex& v = m_vertices[i]; if (v.is_extrusion()) { m_height_range.update(round_to_bin(v.height)); - if (!v.is_custom_gcode() || m_settings.extrusion_roles_visibility.at(EGCodeExtrusionRole::Custom)) { + if (!v.is_custom_gcode() || m_settings.extrusion_roles_visibility[size_t(EGCodeExtrusionRole::Custom)]) { m_width_range.update(round_to_bin(v.width)); m_volumetric_rate_range.update(round_to_bin(v.volumetric_rate())); m_actual_volumetric_rate_range.update(round_to_bin(v.actual_volumetric_rate())); @@ -1769,8 +1777,8 @@ void ViewerImpl::update_color_ranges() m_fan_speed_range.update(round_to_bin(v.fan_speed)); m_temperature_range.update(round_to_bin(v.temperature)); } - if ((v.is_travel() && m_settings.options_visibility.at(EOptionType::Travels)) || - (v.is_wipe() && m_settings.options_visibility.at(EOptionType::Wipes)) || + if ((v.is_travel() && m_settings.options_visibility[size_t(EOptionType::Travels)]) || + (v.is_wipe() && m_settings.options_visibility[size_t(EOptionType::Wipes)]) || v.is_extrusion()) { m_speed_range.update(v.feedrate); m_actual_speed_range.update(v.actual_feedrate); @@ -1783,6 +1791,8 @@ void ViewerImpl::update_color_ranges() m_layer_time_range[i].update(t); } } + + m_settings_used_for_ranges = m_settings; } void ViewerImpl::update_heights_widths() diff --git a/src/libvgcode/src/ViewerImpl.hpp b/src/libvgcode/src/ViewerImpl.hpp index 665de8fc93..8e112dcb0a 100644 --- a/src/libvgcode/src/ViewerImpl.hpp +++ b/src/libvgcode/src/ViewerImpl.hpp @@ -21,6 +21,7 @@ #include "ExtrusionRoles.hpp" #include +#include namespace libvgcode { @@ -64,6 +65,7 @@ public: // view type and settings // void update_colors(); + void update_colors_texture(); // // Render the toolpaths @@ -233,14 +235,13 @@ private: // // Palette used to render extrusion roles // - std::map m_extrusion_roles_colors; + std::array m_extrusion_roles_colors; // // Palette used to render options // - std::map m_options_colors; + std::array m_options_colors; bool m_initialized{ false }; - bool m_loading{ false }; // // The OpenGL element used to represent all toolpath segments @@ -266,6 +267,10 @@ private: // cpu buffer to store vertices // std::vector m_vertices; + + // Cache for the colors to reduce the need to recalculate colors of all the vertices. + std::vector m_vertices_colors; + // // Variables used for toolpaths visibiliity // @@ -273,6 +278,7 @@ private: // // Variables used for toolpaths coloring // + std::optional m_settings_used_for_ranges; ColorRange m_height_range; ColorRange m_width_range; ColorRange m_speed_range; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index c36e780c4e..f927171927 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -195,8 +195,8 @@ Preview::Preview( void Preview::set_layers_slider_values_range(int bottom, int top) { - m_layers_slider->SetHigherPos(std::min(top, m_layers_slider->GetMaxPos())); - m_layers_slider->SetLowerPos(std::max(bottom, m_layers_slider->GetMinPos())); + m_layers_slider->SetSelectionSpan(std::min(top, m_layers_slider->GetMaxPos()), + std::max(bottom, m_layers_slider->GetMinPos())); } bool Preview::init(wxWindow* parent, Bed3D& bed, Model* model) @@ -606,6 +606,9 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result)); m_layers_slider->SetSliderValues(layers_z); assert(m_layers_slider->GetMinPos() == 0); + + m_layers_slider->Freeze(); + m_layers_slider->SetMaxPos(layers_z.empty() ? 0 : layers_z.size() - 1); int idx_low = 0; @@ -633,6 +636,8 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee else m_layers_slider->SetLayersTimes(m_canvas->get_gcode_layers_times_cache(), m_gcode_result->print_statistics.modes.front().time); + m_layers_slider->Thaw(); + // check if ticks_info_from_model contains ColorChange g-code bool color_change_already_exists = false; for (const CustomGCode::Item& gcode: ticks_info_from_model.gcodes) @@ -768,8 +773,7 @@ void Preview::update_layers_slider_mode() void Preview::reset_layers_slider() { - m_layers_slider->SetHigherPos(0); - m_layers_slider->SetLowerPos(0); + m_layers_slider->SetSelectionSpan(0, 0); } void Preview::update_sliders_from_canvas(wxKeyEvent& event) @@ -871,8 +875,11 @@ void Preview::update_moves_slider(std::optional visible_range_min, std::opt m_moves_slider->SetSliderValues(values); m_moves_slider->SetSliderAlternateValues(alternate_values); + + m_moves_slider->Freeze(); m_moves_slider->SetMaxPos(static_cast(values.size()) - 1); m_moves_slider->SetSelectionSpan(span_min_id, span_max_id); + m_moves_slider->Thaw(); m_moves_slider->ShowLowerThumb(get_app_config()->get("seq_top_layer_only") == "0"); } diff --git a/src/slic3r/GUI/ImGuiDoubleSlider.hpp b/src/slic3r/GUI/ImGuiDoubleSlider.hpp index 058dbc9c80..0185d8aec9 100644 --- a/src/slic3r/GUI/ImGuiDoubleSlider.hpp +++ b/src/slic3r/GUI/ImGuiDoubleSlider.hpp @@ -136,7 +136,7 @@ private: int m_lower_pos; int m_higher_pos; // slider's position of the mouse cursor - int m_mouse_pos; + int m_mouse_pos { 0 }; bool m_rclick_on_selected_thumb{ false }; bool m_lclick_on_selected_thumb{ false }; @@ -230,6 +230,13 @@ public: m_ctrl.SetMaxPos(max_pos); process_thumb_move(); } + void Freeze() { + m_allow_process_thumb_move = false; + } + void Thaw() { + m_allow_process_thumb_move = true; + process_thumb_move(); + } void SetSliderValues(const std::vector& values) { m_values = values; } // values used to show thumb labels @@ -274,14 +281,14 @@ protected: } void process_thumb_move() { - if (m_cb_thumb_move) + if (m_cb_thumb_move && m_allow_process_thumb_move) m_cb_thumb_move(); } private: - std::function m_cb_thumb_move{ nullptr }; - + std::function m_cb_thumb_move { nullptr }; + bool m_allow_process_thumb_move { true }; }; } // DoubleSlider diff --git a/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp b/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp index e3ceaee030..23af823103 100644 --- a/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp +++ b/src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp @@ -714,16 +714,30 @@ GCodeInputData convert(const Slic3r::Print& print, const std::vector vert_indices(data.size(), 0); + for (size_t layer_id = 0; layer_id < layers.size(); ++layer_id) { + const float layer_z = layers[layer_id]; + for (size_t obj_idx = 0; obj_idx < data.size(); ++obj_idx) { + // d contains PathVertices for one object. Let's stuff everything below this layer_z into ret.vertices. + const size_t start_idx = vert_indices[obj_idx]; + size_t idx = start_idx; + while (idx < data[obj_idx].vertices.size() && data[obj_idx].vertices[idx].position[2] <= layer_z) + ++idx; + // We have found a vertex above current layer_z. Let's copy the vertices into the output + // and remember where to start when we process another layer. + ret.vertices.insert(ret.vertices.end(), + data[obj_idx].vertices.begin() + start_idx, + data[obj_idx].vertices.begin() + idx); + vert_indices[obj_idx] = idx; } - min_z = z; } + // collect tool colors ret.tools_colors.reserve(str_tool_colors.size()); for (const std::string& color : str_tool_colors) {