diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index 9ff3461e0..488938267 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -94,8 +94,9 @@ sub new { $checklist_features->Check($i, 1); } - my $checkbox_travel = Wx::CheckBox->new($self, -1, "Travel"); + my $checkbox_travel = Wx::CheckBox->new($self, -1, "Travel"); my $checkbox_retractions = Wx::CheckBox->new($self, -1, "Retractions"); + my $checkbox_unretractions = Wx::CheckBox->new($self, -1, "Unretractions"); # ===================== ENRICO_GCODE_PREVIEW ================================================== my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); @@ -116,6 +117,7 @@ sub new { $vsizer_outer->Add($checklist_features, 0, wxTOP | wxALL | wxALIGN_CENTER_HORIZONTAL, 5); $vsizer_outer->Add($checkbox_travel, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); $vsizer_outer->Add($checkbox_retractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + $vsizer_outer->Add($checkbox_unretractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); # ===================== ENRICO_GCODE_PREVIEW ================================================== my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); @@ -228,6 +230,11 @@ sub new { $self->auto_zoom(0); $self->reload_print; }); + EVT_CHECKBOX($self, $checkbox_unretractions, sub { + $self->print->set_gcode_preview_unretractions_visible($checkbox_unretractions->IsChecked()); + $self->auto_zoom(0); + $self->reload_print; + }); # ===================== ENRICO_GCODE_PREVIEW ================================================== $self->SetSizer($sizer); diff --git a/xs/src/libslic3r/GCode/Analyzer.cpp b/xs/src/libslic3r/GCode/Analyzer.cpp index 467e2b6ae..e00bd5daf 100644 --- a/xs/src/libslic3r/GCode/Analyzer.cpp +++ b/xs/src/libslic3r/GCode/Analyzer.cpp @@ -567,8 +567,18 @@ void GCodeAnalyzer::PreviewData::Travel::set_default() is_visible = false; } +const GCodeAnalyzer::PreviewData::Color GCodeAnalyzer::PreviewData::Retraction::Default_Color = GCodeAnalyzer::PreviewData::Color(1.0f, 1.0f, 1.0f, 1.0f); + +GCodeAnalyzer::PreviewData::Retraction::Position::Position(const Point3& position, float width, float height) + : position(position) + , width(width) + , height(height) +{ +} + void GCodeAnalyzer::PreviewData::Retraction::set_default() { + color = Default_Color; is_visible = false; }; @@ -582,6 +592,7 @@ void GCodeAnalyzer::PreviewData::set_default() extrusion.set_default(); travel.set_default(); retraction.set_default(); + unretraction.set_default(); } void GCodeAnalyzer::PreviewData::reset() @@ -589,6 +600,7 @@ void GCodeAnalyzer::PreviewData::reset() extrusion.layers.clear(); travel.polylines.clear(); retraction.positions.clear(); + unretraction.positions.clear(); } const GCodeAnalyzer::PreviewData::Color& GCodeAnalyzer::PreviewData::get_extrusion_role_color(ExtrusionRole role) const @@ -658,6 +670,9 @@ void GCodeAnalyzer::calc_gcode_preview_data(Print& print) // calculates retractions _calc_gcode_preview_retractions(print); + + // calculates unretractions + _calc_gcode_preview_unretractions(print); } void GCodeAnalyzer::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line) @@ -1259,10 +1274,24 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(Print& print) for (const GCodeMove& move : retraction_moves->second) { - print.gcode_preview.retraction.positions.emplace_back(scale_(move.start_position.x), scale_(move.start_position.y), scale_(move.start_position.z)); + // store position + Point3 position(scale_(move.start_position.x), scale_(move.start_position.y), scale_(move.start_position.z)); + print.gcode_preview.retraction.positions.emplace_back(position, move.data.width, move.data.height); } +} - int a = 0; +void GCodeAnalyzer::_calc_gcode_preview_unretractions(Print& print) +{ + TypeToMovesMap::iterator unretraction_moves = m_moves_map.find(GCodeMove::Unretract); + if (unretraction_moves == m_moves_map.end()) + return; + + for (const GCodeMove& move : unretraction_moves->second) + { + // store position + Point3 position(scale_(move.start_position.x), scale_(move.start_position.y), scale_(move.start_position.z)); + print.gcode_preview.unretraction.positions.emplace_back(position, move.data.width, move.data.height); + } } GCodeAnalyzer::PreviewData::Color operator + (const GCodeAnalyzer::PreviewData::Color& c1, const GCodeAnalyzer::PreviewData::Color& c2) diff --git a/xs/src/libslic3r/GCode/Analyzer.hpp b/xs/src/libslic3r/GCode/Analyzer.hpp index 8236772fb..afc863998 100644 --- a/xs/src/libslic3r/GCode/Analyzer.hpp +++ b/xs/src/libslic3r/GCode/Analyzer.hpp @@ -375,7 +375,21 @@ public: struct Retraction { - Points3 positions; + static const Color Default_Color; + + struct Position + { + Point3 position; + float width; + float height; + + Position(const Point3& position, float width, float height); + }; + + typedef std::vector PositionsList; + + PositionsList positions; + Color color; bool is_visible; void set_default(); @@ -384,6 +398,7 @@ public: Extrusion extrusion; Travel travel; Retraction retraction; + Retraction unretraction; PreviewData(); @@ -515,6 +530,7 @@ private: void _calc_gcode_preview_extrusion_layers(Print& print); void _calc_gcode_preview_travel(Print& print); void _calc_gcode_preview_retractions(Print& print); + void _calc_gcode_preview_unretractions(Print& print); }; GCodeAnalyzer::PreviewData::Color operator + (const GCodeAnalyzer::PreviewData::Color& c1, const GCodeAnalyzer::PreviewData::Color& c2); diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 0d984d6da..2173ae9b1 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -98,6 +98,11 @@ void Print::set_gcode_preview_retractions_visible(bool visible) { gcode_preview.retraction.is_visible = visible; } + +void Print::set_gcode_preview_unretractions_visible(bool visible) +{ + gcode_preview.unretraction.is_visible = visible; +} #endif // ENRICO_GCODE_PREVIEW //############################################################################################################ diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 7a69973de..2ded86ee9 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -271,6 +271,7 @@ public: bool is_gcode_preview_extrusion_role_enabled(ExtrusionRole role); void set_gcode_preview_travel_visible(bool visible); void set_gcode_preview_retractions_visible(bool visible); + void set_gcode_preview_unretractions_visible(bool visible); #endif // ENRICO_GCODE_PREVIEW //############################################################################################################ diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 85c044db8..4429d7449 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -880,6 +880,56 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, #undef TOP #undef BOTTOM } + +static void point_to_indexed_vertex_array(const Point3& point, + double width, + double height, + GLIndexedVertexArray& volume) +{ + // builds a double piramid, with vertices on the local axes, around the point + + Pointf3 center = Pointf3::new_unscale(point); + + double scale_factor = 1.0; + double w = scale_factor * width; + double h = scale_factor * height; + + // new vertices ids + int idx_last = int(volume.vertices_and_normals_interleaved.size() / 6); + int idxs[6]; + for (int i = 0; i < 6; ++i) + { + idxs[i] = idx_last + i; + } + + Vectorf3 displacement_x(w, 0.0, 0.0); + Vectorf3 displacement_y(0.0, w, 0.0); + Vectorf3 displacement_z(0.0, 0.0, h); + + Vectorf3 unit_x(1.0, 0.0, 0.0); + Vectorf3 unit_y(0.0, 1.0, 0.0); + Vectorf3 unit_z(0.0, 0.0, 1.0); + + // vertices + volume.push_geometry(center - displacement_x, -unit_x); // idxs[0] + volume.push_geometry(center + displacement_x, unit_x); // idxs[1] + volume.push_geometry(center - displacement_y, -unit_y); // idxs[2] + volume.push_geometry(center + displacement_y, unit_y); // idxs[3] + volume.push_geometry(center - displacement_z, -unit_z); // idxs[4] + volume.push_geometry(center + displacement_z, unit_z); // idxs[5] + + // top piramid faces + volume.push_triangle(idxs[0], idxs[2], idxs[5]); + volume.push_triangle(idxs[2], idxs[1], idxs[5]); + volume.push_triangle(idxs[1], idxs[3], idxs[5]); + volume.push_triangle(idxs[3], idxs[0], idxs[5]); + + // bottom piramid faces + volume.push_triangle(idxs[2], idxs[0], idxs[4]); + volume.push_triangle(idxs[1], idxs[2], idxs[4]); + volume.push_triangle(idxs[3], idxs[1], idxs[4]); + volume.push_triangle(idxs[0], idxs[3], idxs[4]); +} #endif // ENRICO_GCODE_PREVIEW //############################################################################################################ @@ -904,6 +954,14 @@ static void thick_lines_to_verts(const Lines3& lines, { thick_lines_to_indexed_vertex_array(lines, widths, heights, closed, volume.indexed_vertex_array); } + +static void point_to_verts(const Point3& point, + double width, + double height, + GLVolume& volume) +{ + point_to_indexed_vertex_array(point, width, height, volume.indexed_vertex_array); +} #endif // ENRICO_GCODE_PREVIEW //############################################################################################################ @@ -1002,6 +1060,13 @@ static void polyline3_to_verts(const Polyline3& polyline, double width, double h std::vector heights(lines.size(), height); thick_lines_to_verts(lines, widths, heights, false, volume); } + +static void point3_to_verts(const Point3& point, double width, double height, const Point& copy, GLVolume& volume) +{ + Point3 p = point; + p.translate(copy); + point_to_verts(p, width, height, volume); +} #endif // ENRICO_GCODE_PREVIEW //############################################################################################################ @@ -1044,6 +1109,7 @@ void _3DScene::load_gcode_preview(const Print* print, GLVolumeCollection* volume _load_gcode_extrusion_paths(*print, *volumes, use_VBOs); _load_gcode_travel_paths(*print, *volumes, use_VBOs); _load_gcode_retractions(*print, *volumes, use_VBOs); + _load_gcode_unretractions(*print, *volumes, use_VBOs); } #endif // ENRICO_GCODE_PREVIEW //############################################################################################################ @@ -1560,6 +1626,55 @@ void _3DScene::_load_gcode_retractions(const Print& print, GLVolumeCollection& v { if (print.gcode_preview.retraction.is_visible) { + volumes.volumes.emplace_back(new GLVolume(print.gcode_preview.retraction.color.rgba)); + GLVolume* volume = volumes.volumes.back(); + + if (volume != nullptr) + { + Point origin(0, 0); + for (const GCodeAnalyzer::PreviewData::Retraction::Position& position : print.gcode_preview.retraction.positions) + { + coordf_t print_z = unscale(position.position.z); + volume->print_zs.push_back(print_z); + volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size()); + volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size()); + + // adds point to volume + point3_to_verts(position.position, position.width, position.height, origin, *volume); + } + + // finalizes volume + volume->bounding_box = volume->indexed_vertex_array.bounding_box(); + volume->indexed_vertex_array.finalize_geometry(use_VBOs); + } + } +} + +void _3DScene::_load_gcode_unretractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs) +{ + if (print.gcode_preview.unretraction.is_visible) + { + volumes.volumes.emplace_back(new GLVolume(print.gcode_preview.unretraction.color.rgba)); + GLVolume* volume = volumes.volumes.back(); + + if (volume != nullptr) + { + Point origin(0, 0); + for (const GCodeAnalyzer::PreviewData::Retraction::Position& position : print.gcode_preview.unretraction.positions) + { + coordf_t print_z = unscale(position.position.z); + volume->print_zs.push_back(print_z); + volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size()); + volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size()); + + // adds point to volume + point3_to_verts(position.position, position.width, position.height, origin, *volume); + } + + // finalizes volume + volume->bounding_box = volume->indexed_vertex_array.bounding_box(); + volume->indexed_vertex_array.finalize_geometry(use_VBOs); + } } } #endif // ENRICO_GCODE_PREVIEW diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index d4fc0ed67..35c41ec2f 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -383,6 +383,7 @@ private: static void _load_gcode_extrusion_paths(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); static void _load_gcode_travel_paths(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); static void _load_gcode_retractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); + static void _load_gcode_unretractions(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); #endif // ENRICO_GCODE_PREVIEW //############################################################################################################ }; diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index e3e1704fe..d29e087c0 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -171,6 +171,7 @@ _constant() void set_gcode_preview_extrusion_flags(unsigned int flags); void set_gcode_preview_travel_visible(bool visible); void set_gcode_preview_retractions_visible(bool visible); + void set_gcode_preview_unretractions_visible(bool visible); // ===================== ENRICO_GCODE_PREVIEW ================================================== PrintRegionPtrs* regions()