diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index f567c2f72..f63dad079 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -2029,10 +2029,10 @@ sub load_wipe_tower_toolpaths { } sub load_gcode_preview { - my ($self, $print) = @_; + my ($self, $print, $colors) = @_; $self->SetCurrent($self->GetContext) if $self->UseVBOs; - Slic3r::GUI::_3DScene::load_gcode_preview($print, $self->volumes, $self->UseVBOs); + Slic3r::GUI::_3DScene::load_gcode_preview($print, $self->volumes, $colors, $self->UseVBOs); } sub set_toolpaths_range { diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index 9c3c95d1a..2b853dbb3 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -17,7 +17,6 @@ sub new { my $self = $class->SUPER::new($parent, -1, wxDefaultPosition); $self->{config} = $config; $self->{number_extruders} = 1; - $self->{preferred_color_mode} = 'feature'; $self->auto_zoom(1); # init GUI elements @@ -57,9 +56,7 @@ sub new { $z_label_high->SetFont($Slic3r::GUI::small_font); $self->single_layer(0); - $self->{color_by_extruder} = 0; my $checkbox_singlelayer = $self->{checkbox_singlelayer} = Wx::CheckBox->new($self, -1, "1 Layer"); - my $checkbox_color_by_extruder = $self->{checkbox_color_by_extruder} = Wx::CheckBox->new($self, -1, "Tool"); my $label_view_type = $self->{label_view_type} = Wx::StaticText->new($self, -1, "View"); @@ -68,6 +65,7 @@ sub new { $choice_view_type->Append("Height"); $choice_view_type->Append("Width"); $choice_view_type->Append("Speed"); + $choice_view_type->Append("Tool"); $choice_view_type->SetSelection(0); my $label_show_features = $self->{label_show_features} = Wx::StaticText->new($self, -1, "Show"); @@ -96,7 +94,6 @@ sub new { $hsizer->Add($vsizer, 0, wxEXPAND, 0); $vsizer_outer->Add($hsizer, 3, wxALIGN_CENTER_HORIZONTAL, 0); $vsizer_outer->Add($checkbox_singlelayer, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5); - $vsizer_outer->Add($checkbox_color_by_extruder, 0, wxTOP | wxALIGN_CENTER_HORIZONTAL, 5); my $bottom_sizer = Wx::BoxSizer->new(wxHORIZONTAL); $bottom_sizer->Add($label_view_type, 0, wxALIGN_CENTER_VERTICAL, 5); @@ -188,12 +185,6 @@ sub new { $self->set_z_idx_high($slider_high->GetValue); } }); - EVT_CHECKBOX($self, $checkbox_color_by_extruder, sub { - $self->{color_by_extruder} = $checkbox_color_by_extruder->GetValue(); - $self->{preferred_color_mode} = $self->{color_by_extruder} ? 'tool' : 'feature'; - $self->reload_print; - }); - EVT_CHOICE($self, $choice_view_type, sub { my $selection = $choice_view_type->GetCurrentSelection(); $self->print->set_gcode_preview_type($selection); @@ -322,33 +313,19 @@ sub load_print { $self->slider_high->Show; $self->Layout; - my $by_tool = $self->{color_by_extruder}; - if ($self->{preferred_color_mode} eq 'tool_or_feature') { - # It is left to Slic3r to decide whether the print shall be colored by the tool or by the feature. - # Color by feature if it is a single extruder print. - my $extruders = $self->{print}->extruders; - $by_tool = scalar(@{$extruders}) > 1; - $self->{color_by_extruder} = $by_tool; - $self->{checkbox_color_by_extruder}->SetValue($by_tool); - $self->{preferred_color_mode} = 'tool_or_feature'; - } - # Collect colors per extruder. - # Leave it empty, if the print should be colored by a feature. my @colors = (); - if ($by_tool) { - my @extruder_colors = @{$self->{config}->extruder_colour}; - my @filament_colors = @{$self->{config}->filament_colour}; - for (my $i = 0; $i <= $#extruder_colors; $i += 1) { - my $color = $extruder_colors[$i]; - $color = $filament_colors[$i] if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/); - $color = '#FFFFFF' if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/); - push @colors, $color; - } + my @extruder_colors = @{$self->{config}->extruder_colour}; + my @filament_colors = @{$self->{config}->filament_colour}; + for (my $i = 0; $i <= $#extruder_colors; $i += 1) { + my $color = $extruder_colors[$i]; + $color = $filament_colors[$i] if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/); + $color = '#FFFFFF' if (! defined($color) || $color !~ m/^#[[:xdigit:]]{6}/); + push @colors, $color; } if ($self->IsShown) { - $self->canvas->load_gcode_preview($self->print); + $self->canvas->load_gcode_preview($self->print, \@colors); # # load skirt and brim # $self->canvas->load_print_toolpaths($self->print, \@colors); @@ -417,10 +394,6 @@ sub set_number_extruders { my ($self, $number_extruders) = @_; if ($self->{number_extruders} != $number_extruders) { $self->{number_extruders} = $number_extruders; - my $by_tool = $number_extruders > 1; - $self->{color_by_extruder} = $by_tool; - $self->{checkbox_color_by_extruder}->SetValue($by_tool); - $self->{preferred_color_mode} = $by_tool ? 'tool_or_feature' : 'feature'; } } diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp index 650a806f6..f5e243419 100644 --- a/xs/src/libslic3r/ExtrusionEntity.hpp +++ b/xs/src/libslic3r/ExtrusionEntity.hpp @@ -107,15 +107,17 @@ public: float height; // Feedrate of the extrusion, used for visualization purposed. float feedrate; + // Id of the extruder, used for visualization purposed. + unsigned int extruder_id; - ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), m_role(role) {}; - ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), m_role(role) {}; - ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), m_role(rhs.m_role) {} - ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), m_role(rhs.m_role) {} -// ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height), feedrate(0.0f) {}; + ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), m_role(role) {}; + ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), m_role(role) {}; + ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), m_role(rhs.m_role) {} + ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), m_role(rhs.m_role) {} +// ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height), feedrate(0.0f), extruder_id(0) {}; - ExtrusionPath& operator=(const ExtrusionPath &rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->polyline = rhs.polyline; return *this; } - ExtrusionPath& operator=(ExtrusionPath &&rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->polyline = std::move(rhs.polyline); return *this; } + ExtrusionPath& operator=(const ExtrusionPath &rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->polyline = rhs.polyline; return *this; } + ExtrusionPath& operator=(ExtrusionPath &&rhs) { this->m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->polyline = std::move(rhs.polyline); return *this; } ExtrusionPath* clone() const { return new ExtrusionPath (*this); } void reverse() { this->polyline.reverse(); } diff --git a/xs/src/libslic3r/GCode/Analyzer.cpp b/xs/src/libslic3r/GCode/Analyzer.cpp index b4d7f2596..0288770b0 100644 --- a/xs/src/libslic3r/GCode/Analyzer.cpp +++ b/xs/src/libslic3r/GCode/Analyzer.cpp @@ -122,10 +122,11 @@ GCodeAnalyzer::PreviewData::Extrusion::Layer::Layer(float z, const ExtrusionPath { } -GCodeAnalyzer::PreviewData::Travel::Polyline::Polyline(EType type, EDirection direction, float feedrate, const Polyline3& polyline) +GCodeAnalyzer::PreviewData::Travel::Polyline::Polyline(EType type, EDirection direction, float feedrate, unsigned int extruder_id, const Polyline3& polyline) : type(type) , direction(direction) , feedrate(feedrate) + , extruder_id(extruder_id) , polyline(polyline) { } @@ -352,12 +353,14 @@ std::string GCodeAnalyzer::PreviewData::get_legend_title() const return "Width (mm)"; case Extrusion::Feedrate: return "Speed (mm/s)"; + case Extrusion::Tool: + return "Tool"; } return ""; } -GCodeAnalyzer::PreviewData::LegendItemsList GCodeAnalyzer::PreviewData::get_legend_items() const +GCodeAnalyzer::PreviewData::LegendItemsList GCodeAnalyzer::PreviewData::get_legend_items(const std::vector& tool_colors) const { struct Helper { @@ -401,6 +404,23 @@ GCodeAnalyzer::PreviewData::LegendItemsList GCodeAnalyzer::PreviewData::get_lege case Extrusion::Feedrate: { Helper::FillListFromRange(items, extrusion.ranges.feedrate, 0, 1.0f); + break; + } + case Extrusion::Tool: + { + unsigned int tools_colors_count = tool_colors.size() / 4; + items.reserve(tools_colors_count); + for (unsigned int i = 0; i < tools_colors_count; ++i) + { + char buf[32]; + sprintf(buf, "Extruder %d", i + 1); + + GCodeAnalyzer::PreviewData::Color color; + ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + i * 4), 4 * sizeof(float)); + + items.emplace_back(buf, color); + } + break; } } @@ -693,9 +713,8 @@ void GCodeAnalyzer::_processT(const GCodeReader::GCodeLine& line) std::string cmd = line.cmd(); if (cmd.length() > 1) { - int id = (int)::strtol(cmd.substr(1).c_str(), nullptr, 10); - // todo - add id validity check ? - if (_get_extruder_id() != (unsigned int)id) + unsigned int id = (unsigned int)::strtol(cmd.substr(1).c_str(), nullptr, 10); + if (_get_extruder_id() != id) { _set_extruder_id(id); @@ -947,6 +966,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(Print& print) ExtrusionPath path(data.extrusion_role, data.mm3_per_mm, data.width, data.height); path.polyline = polyline; path.feedrate = data.feedrate; + path.extruder_id = data.extruder_id; get_layer_at_z(print.gcode_preview.extrusion.layers, z).paths.push_back(path); } @@ -1010,11 +1030,11 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(Print& print) { struct Helper { - static void store_polyline(const Polyline3& polyline, PreviewData::Travel::EType type, PreviewData::Travel::Polyline::EDirection direction, float feedrate, Print& print) + static void store_polyline(const Polyline3& polyline, PreviewData::Travel::EType type, PreviewData::Travel::Polyline::EDirection direction, float feedrate, unsigned int extruder_id, Print& print) { // if the polyline is valid, store it if (polyline.is_valid()) - print.gcode_preview.travel.polylines.emplace_back(type, direction, feedrate, polyline); + print.gcode_preview.travel.polylines.emplace_back(type, direction, feedrate, extruder_id, polyline); } }; @@ -1027,6 +1047,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(Print& print) PreviewData::Travel::EType type = PreviewData::Travel::Num_Types; PreviewData::Travel::Polyline::EDirection direction = PreviewData::Travel::Polyline::Num_Directions; float feedrate = FLT_MAX; + unsigned int extruder_id = -1; // constructs the polylines while traversing the moves for (const GCodeMove& move : travel_moves->second) @@ -1034,11 +1055,11 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(Print& print) PreviewData::Travel::EType move_type = (move.delta_extruder < 0.0f) ? PreviewData::Travel::Retract : ((move.delta_extruder > 0.0f) ? PreviewData::Travel::Extrude : PreviewData::Travel::Move); PreviewData::Travel::Polyline::EDirection move_direction = ((move.start_position.x != move.end_position.x) || (move.start_position.y != move.end_position.y)) ? PreviewData::Travel::Polyline::Generic : PreviewData::Travel::Polyline::Vertical; - if ((type != move_type) || (direction != move_direction) || (feedrate != move.data.feedrate) || (position != move.start_position)) + if ((type != move_type) || (direction != move_direction) || (feedrate != move.data.feedrate) || (position != move.start_position) || (extruder_id != move.data.extruder_id)) { // store current polyline polyline.remove_duplicate_points(); - Helper::store_polyline(polyline, type, direction, feedrate, print); + Helper::store_polyline(polyline, type, direction, feedrate, extruder_id, print); // reset current polyline polyline = Polyline3(); @@ -1055,11 +1076,12 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(Print& print) position = move.end_position; type = move_type; feedrate = move.data.feedrate; + extruder_id = move.data.extruder_id; } // store last polyline polyline.remove_duplicate_points(); - Helper::store_polyline(polyline, type, direction, feedrate, print); + Helper::store_polyline(polyline, type, direction, feedrate, extruder_id, print); } void GCodeAnalyzer::_calc_gcode_preview_retractions(Print& print) diff --git a/xs/src/libslic3r/GCode/Analyzer.hpp b/xs/src/libslic3r/GCode/Analyzer.hpp index 1671c35ca..34f1537af 100644 --- a/xs/src/libslic3r/GCode/Analyzer.hpp +++ b/xs/src/libslic3r/GCode/Analyzer.hpp @@ -152,6 +152,7 @@ public: Height, Width, Feedrate, + Tool, Num_View_Types }; @@ -216,9 +217,10 @@ public: EType type; EDirection direction; float feedrate; + unsigned int extruder_id; Polyline3 polyline; - Polyline(EType type, EDirection direction, float feedrate, const Polyline3& polyline); + Polyline(EType type, EDirection direction, float feedrate, unsigned int extruder_id, const Polyline3& polyline); }; typedef std::vector PolylinesList; @@ -270,7 +272,7 @@ public: const Color& get_extrusion_feedrate_color(float feedrate) const; std::string get_legend_title() const; - LegendItemsList get_legend_items() const; + LegendItemsList get_legend_items(const std::vector& tool_colors) const; }; private: diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 15e905ee4..96cbabbe9 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -1099,13 +1099,13 @@ _3DScene::LegendTexture::~LegendTexture() _destroy_texture(); } -bool _3DScene::LegendTexture::generate_texture(const Print& print) +bool _3DScene::LegendTexture::generate_texture(const Print& print, const std::vector& tool_colors) { _destroy_texture(); // collects items to render const std::string& title = print.gcode_preview.get_legend_title(); - const GCodeAnalyzer::PreviewData::LegendItemsList& items = print.gcode_preview.get_legend_items(); + const GCodeAnalyzer::PreviewData::LegendItemsList& items = print.gcode_preview.get_legend_items(tool_colors); unsigned int items_count = (unsigned int)items.size(); if (items_count == 0) @@ -1312,21 +1312,23 @@ static inline std::vector parse_colors(const std::vector &sc return output; } -void _3DScene::load_gcode_preview(const Print* print, GLVolumeCollection* volumes, bool use_VBOs) +void _3DScene::load_gcode_preview(const Print* print, GLVolumeCollection* volumes, const std::vector& str_tool_colors, bool use_VBOs) { if (volumes->empty()) { + std::vector tool_colors = parse_colors(str_tool_colors); + s_gcode_preview_data.reset(); - _load_gcode_extrusion_paths(*print, *volumes, use_VBOs); - _load_gcode_travel_paths(*print, *volumes, use_VBOs); + _load_gcode_extrusion_paths(*print, *volumes, tool_colors, use_VBOs); + _load_gcode_travel_paths(*print, *volumes, tool_colors, use_VBOs); _load_gcode_retractions(*print, *volumes, use_VBOs); _load_gcode_unretractions(*print, *volumes, use_VBOs); if (volumes->empty()) reset_legend_texture(); else - _generate_legend_texture(*print); + _generate_legend_texture(*print, tool_colors); } _update_gcode_volumes_visibility(*print, *volumes); @@ -1709,7 +1711,7 @@ void _3DScene::_load_wipe_tower_toolpaths( BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end"; } -void _3DScene::_load_gcode_extrusion_paths(const Print& print, GLVolumeCollection& volumes, bool use_VBOs) +void _3DScene::_load_gcode_extrusion_paths(const Print& print, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs) { // helper functions to select data in dependence of the extrusion view type struct Helper @@ -1726,12 +1728,14 @@ void _3DScene::_load_gcode_extrusion_paths(const Print& print, GLVolumeCollectio return path.width; case GCodeAnalyzer::PreviewData::Extrusion::Feedrate: return path.feedrate; + case GCodeAnalyzer::PreviewData::Extrusion::Tool: + return (float)path.extruder_id; } return 0.0f; } - static const GCodeAnalyzer::PreviewData::Color& path_color(const GCodeAnalyzer::PreviewData& data, float value) + static const GCodeAnalyzer::PreviewData::Color& path_color(const GCodeAnalyzer::PreviewData& data, const std::vector& tool_colors, float value) { switch (data.extrusion.view_type) { @@ -1743,6 +1747,12 @@ void _3DScene::_load_gcode_extrusion_paths(const Print& print, GLVolumeCollectio return data.get_extrusion_width_color(value); case GCodeAnalyzer::PreviewData::Extrusion::Feedrate: return data.get_extrusion_feedrate_color(value); + case GCodeAnalyzer::PreviewData::Extrusion::Tool: + { + static GCodeAnalyzer::PreviewData::Color color; + ::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + (unsigned int)value * 4), 4 * sizeof(float)); + return color; + } } return GCodeAnalyzer::PreviewData::Color::Dummy; @@ -1801,7 +1811,7 @@ void _3DScene::_load_gcode_extrusion_paths(const Print& print, GLVolumeCollectio { s_gcode_preview_data.first_volumes.emplace_back(GCodePreviewData::Extrusion, (unsigned int)filter.role, (unsigned int)volumes.volumes.size()); - GLVolume* volume = new GLVolume(Helper::path_color(print.gcode_preview, filter.value).rgba); + GLVolume* volume = new GLVolume(Helper::path_color(print.gcode_preview, tool_colors, filter.value).rgba); if (volume != nullptr) { filter.volume = volume; @@ -1856,7 +1866,62 @@ void _3DScene::_load_gcode_extrusion_paths(const Print& print, GLVolumeCollectio } } -void _3DScene::_load_gcode_travel_paths(const Print& print, GLVolumeCollection& volumes, bool use_VBOs) +void _3DScene::_load_gcode_travel_paths(const Print& print, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs) +{ + size_t initial_volumes_count = volumes.volumes.size(); + s_gcode_preview_data.first_volumes.emplace_back(GCodePreviewData::Travel, 0, (unsigned int)initial_volumes_count); + + bool res = true; + switch (print.gcode_preview.extrusion.view_type) + { + case GCodeAnalyzer::PreviewData::Extrusion::Feedrate: + { + res = _travel_paths_by_feedrate(print, volumes); + break; + } + case GCodeAnalyzer::PreviewData::Extrusion::Tool: + { + res = _travel_paths_by_tool(print, volumes, tool_colors); + break; + } + default: + { + res = _travel_paths_by_type(print, volumes); + break; + } + } + + if (!res) + { + // an error occourred - restore to previous state and return + if (initial_volumes_count != volumes.volumes.size()) + { + std::vector::iterator begin = volumes.volumes.begin() + initial_volumes_count; + std::vector::iterator end = volumes.volumes.end(); + for (std::vector::iterator it = begin; it < end; ++it) + { + GLVolume* volume = *it; + delete volume; + } + volumes.volumes.erase(begin, end); + } + + return; + } + + // finalize volumes and sends geometry to gpu + if (volumes.volumes.size() > initial_volumes_count) + { + for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i) + { + GLVolume* volume = volumes.volumes[i]; + volume->bounding_box = volume->indexed_vertex_array.bounding_box(); + volume->indexed_vertex_array.finalize_geometry(use_VBOs); + } + } +} + +bool _3DScene::_travel_paths_by_type(const Print& print, GLVolumeCollection& volumes) { // Helper structure for types struct Type @@ -1878,6 +1943,52 @@ void _3DScene::_load_gcode_travel_paths(const Print& print, GLVolumeCollection& typedef std::vector TypesList; + // colors travels by travel type + + // detects types + TypesList types; + for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) + { + if (std::find(types.begin(), types.end(), Type(polyline.type)) == types.end()) + types.emplace_back(polyline.type); + } + + // nothing to render, return + if (types.empty()) + return true; + + // creates a new volume for each type + for (Type& type : types) + { + GLVolume* volume = new GLVolume(print.gcode_preview.travel.type_colors[type.value].rgba); + if (volume == nullptr) + return false; + else + { + type.volume = volume; + volumes.volumes.emplace_back(volume); + } + } + + // populates volumes + for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) + { + TypesList::iterator type = std::find(types.begin(), types.end(), Type(polyline.type)); + if (type != types.end()) + { + type->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().max.z)); + type->volume->offsets.push_back(type->volume->indexed_vertex_array.quad_indices.size()); + type->volume->offsets.push_back(type->volume->indexed_vertex_array.triangle_indices.size()); + + polyline3_to_verts(polyline.polyline, print.gcode_preview.travel.width, print.gcode_preview.travel.height, *type->volume); + } + } + + return true; +} + +bool _3DScene::_travel_paths_by_feedrate(const Print& print, GLVolumeCollection& volumes) +{ // Helper structure for feedrate struct Feedrate { @@ -1898,134 +2009,114 @@ void _3DScene::_load_gcode_travel_paths(const Print& print, GLVolumeCollection& typedef std::vector FeedratesList; - size_t initial_volumes_count = volumes.volumes.size(); - s_gcode_preview_data.first_volumes.emplace_back(GCodePreviewData::Travel, 0, (unsigned int)initial_volumes_count); + // colors travels by feedrate - if (print.gcode_preview.extrusion.view_type == GCodeAnalyzer::PreviewData::Extrusion::Feedrate) + // detects feedrates + FeedratesList feedrates; + for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) { - // colors travels by feedrate - - // detects feedrates - FeedratesList feedrates; - for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) - { - if (std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate)) == feedrates.end()) - feedrates.emplace_back(polyline.feedrate); - } - - // nothing to render, return - if (feedrates.empty()) - return; - - // creates a new volume for each feedrate - for (Feedrate& feedrate : feedrates) - { - GLVolume* volume = new GLVolume(print.gcode_preview.get_extrusion_feedrate_color(feedrate.value).rgba); - if (volume != nullptr) - { - feedrate.volume = volume; - volumes.volumes.emplace_back(volume); - } - else - { - // an error occourred - restore to previous state and return - if (initial_volumes_count != volumes.volumes.size()) - { - std::vector::iterator begin = volumes.volumes.begin() + initial_volumes_count; - std::vector::iterator end = volumes.volumes.end(); - for (std::vector::iterator it = begin; it < end; ++it) - { - GLVolume* volume = *it; - delete volume; - } - volumes.volumes.erase(begin, end); - return; - } - } - } - - // populates volumes - for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) - { - FeedratesList::iterator feedrate = std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate)); - if (feedrate != feedrates.end()) - { - feedrate->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().max.z)); - feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.quad_indices.size()); - feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.triangle_indices.size()); - - polyline3_to_verts(polyline.polyline, print.gcode_preview.travel.width, print.gcode_preview.travel.height, *feedrate->volume); - } - } + if (std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate)) == feedrates.end()) + feedrates.emplace_back(polyline.feedrate); } - else + + // nothing to render, return + if (feedrates.empty()) + return true; + + // creates a new volume for each feedrate + for (Feedrate& feedrate : feedrates) { - // colors travels by travel type - - // detects types - TypesList types; - for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) + GLVolume* volume = new GLVolume(print.gcode_preview.get_extrusion_feedrate_color(feedrate.value).rgba); + if (volume == nullptr) + return false; + else { - if (std::find(types.begin(), types.end(), Type(polyline.type)) == types.end()) - types.emplace_back(polyline.type); - } - - // nothing to render, return - if (types.empty()) - return; - - // creates a new volume for each type - for (Type& type : types) - { - GLVolume* volume = new GLVolume(print.gcode_preview.travel.type_colors[type.value].rgba); - if (volume != nullptr) - { - type.volume = volume; - volumes.volumes.emplace_back(volume); - } - else - { - // an error occourred - restore to previous state and return - if (initial_volumes_count != volumes.volumes.size()) - { - std::vector::iterator begin = volumes.volumes.begin() + initial_volumes_count; - std::vector::iterator end = volumes.volumes.end(); - for (std::vector::iterator it = begin; it < end; ++it) - { - GLVolume* volume = *it; - delete volume; - } - volumes.volumes.erase(begin, end); - return; - } - } - } - - // populates volumes - for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) - { - TypesList::iterator type = std::find(types.begin(), types.end(), Type(polyline.type)); - if (type != types.end()) - { - type->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().max.z)); - type->volume->offsets.push_back(type->volume->indexed_vertex_array.quad_indices.size()); - type->volume->offsets.push_back(type->volume->indexed_vertex_array.triangle_indices.size()); - - polyline3_to_verts(polyline.polyline, print.gcode_preview.travel.width, print.gcode_preview.travel.height, *type->volume); - } + feedrate.volume = volume; + volumes.volumes.emplace_back(volume); } } - // finalize volumes and sends geometry to gpu - if (volumes.volumes.size() > initial_volumes_count) + // populates volumes + for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) { - for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i) + FeedratesList::iterator feedrate = std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate)); + if (feedrate != feedrates.end()) { - GLVolume* volume = volumes.volumes[i]; - volume->bounding_box = volume->indexed_vertex_array.bounding_box(); - volume->indexed_vertex_array.finalize_geometry(use_VBOs); + feedrate->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().max.z)); + feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.quad_indices.size()); + feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.triangle_indices.size()); + + polyline3_to_verts(polyline.polyline, print.gcode_preview.travel.width, print.gcode_preview.travel.height, *feedrate->volume); } } + + return true; +} + +bool _3DScene::_travel_paths_by_tool(const Print& print, GLVolumeCollection& volumes, const std::vector& tool_colors) +{ + // Helper structure for tool + struct Tool + { + unsigned int value; + GLVolume* volume; + + explicit Tool(unsigned int value) + : value(value) + , volume(nullptr) + { + } + + bool operator == (const Tool& other) const + { + return value == other.value; + } + }; + + typedef std::vector ToolsList; + + // colors travels by tool + + // detects tools + ToolsList tools; + for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) + { + if (std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id)) == tools.end()) + tools.emplace_back(polyline.extruder_id); + } + + // nothing to render, return + if (tools.empty()) + return true; + + // creates a new volume for each tool + for (Tool& tool : tools) + { + GLVolume* volume = new GLVolume(tool_colors.data() + tool.value * 4); + if (volume == nullptr) + return false; + else + { + tool.volume = volume; + volumes.volumes.emplace_back(volume); + } + } + + // populates volumes + for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines) + { + ToolsList::iterator tool = std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id)); + if (tool != tools.end()) + { + tool->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().max.z)); + tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.quad_indices.size()); + tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.triangle_indices.size()); + + polyline3_to_verts(polyline.polyline, print.gcode_preview.travel.width, print.gcode_preview.travel.height, *tool->volume); + } + } + + return true; } void _3DScene::_load_gcode_retractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs) @@ -2128,9 +2219,9 @@ void _3DScene::_update_gcode_volumes_visibility(const Print& print, GLVolumeColl } } -void _3DScene::_generate_legend_texture(const Print& print) +void _3DScene::_generate_legend_texture(const Print& print, const std::vector& tool_colors) { - s_legend_texture.generate_texture(print); + s_legend_texture.generate_texture(print, tool_colors); } } diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 4c73bdb7d..2b7f2de47 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -397,7 +397,7 @@ class _3DScene LegendTexture(); ~LegendTexture(); - bool generate_texture(const Print& print); + bool generate_texture(const Print& print, const std::vector& tool_colors); unsigned int get_texture_id() const; unsigned int get_texture_width() const; @@ -415,7 +415,7 @@ class _3DScene public: static void _glew_init(); - static void load_gcode_preview(const Print* print, GLVolumeCollection* volumes, bool use_VBOs); + static void load_gcode_preview(const Print* print, GLVolumeCollection* volumes, const std::vector& str_tool_colors, bool use_VBOs); static unsigned int get_legend_texture_id(); static unsigned int get_legend_texture_width(); @@ -443,9 +443,12 @@ public: private: // generates gcode extrusion paths geometry - static void _load_gcode_extrusion_paths(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); + static void _load_gcode_extrusion_paths(const Print& print, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs); // generates gcode travel paths geometry - static void _load_gcode_travel_paths(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); + static void _load_gcode_travel_paths(const Print& print, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs); + static bool _travel_paths_by_type(const Print& print, GLVolumeCollection& volumes); + static bool _travel_paths_by_feedrate(const Print& print, GLVolumeCollection& volumes); + static bool _travel_paths_by_tool(const Print& print, GLVolumeCollection& volumes, const std::vector& tool_colors); // generates gcode retractions geometry static void _load_gcode_retractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); // generates gcode unretractions geometry @@ -453,7 +456,7 @@ private: // sets gcode geometry visibility according to user selection static void _update_gcode_volumes_visibility(const Print& print, GLVolumeCollection& volumes); // generates the legend texture in dependence of the current shown view type - static void _generate_legend_texture(const Print& print); + static void _generate_legend_texture(const Print& print, const std::vector& tool_colors); }; } diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 6c56a06d9..7520ce6c2 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -195,11 +195,12 @@ _load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs) _3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0); void -load_gcode_preview(print, volumes, use_VBOs) - Print *print; - GLVolumeCollection *volumes; - int use_VBOs; +load_gcode_preview(print, volumes, str_tool_colors, use_VBOs) + Print *print; + GLVolumeCollection *volumes; + std::vector str_tool_colors; + int use_VBOs; CODE: - _3DScene::load_gcode_preview(print, volumes, use_VBOs != 0); + _3DScene::load_gcode_preview(print, volumes, str_tool_colors, use_VBOs != 0); %}