From 0c4df47bd095e571ed8609b4c8d1820e47f5c9bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 16 Mar 2022 10:57:18 +0100 Subject: [PATCH 01/46] Fixed various issues in the ported Lightning infill. Added export to SVG for TreeNode. Also was finalized integration of Lightning infill and Lightning infill was enabled. --- src/libslic3r/Fill/Fill.cpp | 6 +- src/libslic3r/Fill/FillBase.cpp | 2 - src/libslic3r/Fill/FillRectilinear.cpp | 8 +- .../Fill/Lightning/DistanceField.cpp | 67 ++++++++++++---- .../Fill/Lightning/DistanceField.hpp | 26 ++++++- src/libslic3r/Fill/Lightning/Generator.cpp | 42 +++++----- src/libslic3r/Fill/Lightning/Generator.hpp | 2 +- src/libslic3r/Fill/Lightning/Layer.cpp | 77 ++++++++++++------- src/libslic3r/Fill/Lightning/Layer.hpp | 19 +++-- src/libslic3r/Fill/Lightning/TreeNode.cpp | 50 ++++++++---- src/libslic3r/Fill/Lightning/TreeNode.hpp | 33 +++++--- src/libslic3r/Layer.hpp | 8 +- src/libslic3r/Point.hpp | 5 ++ src/libslic3r/Print.hpp | 9 ++- src/libslic3r/PrintConfig.cpp | 6 -- src/libslic3r/PrintConfig.hpp | 8 +- src/libslic3r/PrintObject.cpp | 18 ++++- 17 files changed, 265 insertions(+), 121 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index a3e4aee311..e6b8201885 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -11,6 +11,7 @@ #include "FillBase.hpp" #include "FillRectilinear.hpp" +#include "FillLightning.hpp" namespace Slic3r { @@ -318,7 +319,7 @@ void export_group_fills_to_svg(const char *path, const std::vector #endif // friend to Layer -void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree) +void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator) { for (LayerRegion *layerm : m_regions) layerm->fills.clear(); @@ -348,6 +349,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: f->angle = surface_fill.params.angle; f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree; + if (surface_fill.params.pattern == ipLightning) + dynamic_cast(f.get())->generator = lightning_generator; + // calculate flow spacing for infill pattern generation bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge; double link_max_length = 0.; diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 7ca0699c0f..c4f8d6f08f 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -46,9 +46,7 @@ Fill* Fill::new_from_type(const InfillPattern type) case ipAdaptiveCubic: return new FillAdaptive::Filler(); case ipSupportCubic: return new FillAdaptive::Filler(); case ipSupportBase: return new FillSupportBase(); -#if HAS_LIGHTNING_INFILL case ipLightning: return new FillLightning::Filler(); -#endif // HAS_LIGHTNING_INFILL default: throw Slic3r::InvalidArgument("unknown type"); } } diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 7d868860a7..264ae8a599 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -406,13 +406,15 @@ public: // for the infill pattern, don't cut the corners. // default miterLimt = 3 //double miterLimit = 10.; - assert(aoffset1 < 0); + // FIXME: Resolve properly the cases when it is constructed with aoffset1 = 0 and aoffset2 = 0, + // that is used in sample_grid_pattern() for Lightning infill. + // assert(aoffset1 < 0); assert(aoffset2 <= 0); - assert(aoffset2 == 0 || aoffset2 < aoffset1); + // assert(aoffset2 == 0 || aoffset2 < aoffset1); // bool sticks_removed = remove_sticks(polygons_src); // if (sticks_removed) BOOST_LOG_TRIVIAL(error) << "Sticks removed!"; - polygons_outer = offset(polygons_src, float(aoffset1), ClipperLib::jtMiter, miterLimit); + polygons_outer = aoffset1 == 0 ? polygons_src : offset(polygons_src, float(aoffset1), ClipperLib::jtMiter, miterLimit); if (aoffset2 < 0) polygons_inner = shrink(polygons_outer, float(aoffset1 - aoffset2), ClipperLib::jtMiter, miterLimit); // Filter out contours with zero area or small area, contours with 2 points only. diff --git a/src/libslic3r/Fill/Lightning/DistanceField.cpp b/src/libslic3r/Fill/Lightning/DistanceField.cpp index 6df1d043ca..308ca41c60 100644 --- a/src/libslic3r/Fill/Lightning/DistanceField.cpp +++ b/src/libslic3r/Fill/Lightning/DistanceField.cpp @@ -10,27 +10,29 @@ namespace Slic3r::FillLightning constexpr coord_t radius_per_cell_size = 6; // The cell-size should be small compared to the radius, but not so small as to be inefficient. -DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outline, const Polygons& current_overhang) : - m_cell_size(radius / radius_per_cell_size), - m_supporting_radius(radius) +DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outline, const BoundingBox& current_outlines_bbox, const Polygons& current_overhang) : + m_cell_size(radius / radius_per_cell_size), + m_supporting_radius(radius), + m_unsupported_points_bbox(current_outlines_bbox) { - m_supporting_radius2 = double(radius) * double(radius); + m_supporting_radius2 = Slic3r::sqr(int64_t(radius)); // Sample source polygons with a regular grid sampling pattern. - for (const ExPolygon &expoly : union_ex(current_outline)) { + for (const ExPolygon &expoly : union_ex(current_overhang)) { for (const Point &p : sample_grid_pattern(expoly, m_cell_size)) { // Find a squared distance to the source expolygon boundary. double d2 = std::numeric_limits::max(); - for (size_t icontour = 0; icontour <= expoly.holes.size(); ++ icontour) { + for (size_t icontour = 0; icontour <= expoly.holes.size(); ++icontour) { const Polygon &contour = icontour == 0 ? expoly.contour : expoly.holes[icontour - 1]; if (contour.size() > 2) { Point prev = contour.points.back(); for (const Point &p2 : contour.points) { - d2 = std::min(d2, Line::distance_to_squared(p, prev, p2)); + d2 = std::min(d2, Line::distance_to_squared(p, prev, p2)); prev = p2; } } } m_unsupported_points.emplace_back(p, sqrt(d2)); + assert(m_unsupported_points_bbox.contains(p)); } } m_unsupported_points.sort([&radius](const UnsupportedCell &a, const UnsupportedCell &b) { @@ -41,8 +43,11 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl }); for (auto it = m_unsupported_points.begin(); it != m_unsupported_points.end(); ++it) { UnsupportedCell& cell = *it; - m_unsupported_points_grid.emplace(Point{ cell.loc.x() / m_cell_size, cell.loc.y() / m_cell_size }, it); + m_unsupported_points_grid.emplace(this->to_grid_point(cell.loc), it); } + // Because the distance between two points is at least one axis equal to m_cell_size, every cell + // in m_unsupported_points_grid contains exactly one point. + assert(m_unsupported_points.size() == m_unsupported_points_grid.size()); } void DistanceField::update(const Point& to_node, const Point& added_leaf) @@ -60,17 +65,24 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf) grid.merge(to_node + iextent); grid.merge(added_leaf - iextent); grid.merge(added_leaf + iextent); - grid.min /= m_cell_size; - grid.max /= m_cell_size; + + // Clip grid by m_unsupported_points_bbox. Mainly to ensure that grid.min is a non-negative value. + grid.min.x() = std::max(grid.min.x(), m_unsupported_points_bbox.min.x()); + grid.min.y() = std::max(grid.min.y(), m_unsupported_points_bbox.min.y()); + grid.max.x() = std::min(grid.max.x(), m_unsupported_points_bbox.max.x()); + grid.max.y() = std::min(grid.max.y(), m_unsupported_points_bbox.max.y()); + + grid.min = this->to_grid_point(grid.min); + grid.max = this->to_grid_point(grid.max); } + Point grid_addr; Point grid_loc; - for (coord_t row = grid.min.y(); row <= grid.max.y(); ++ row) { - grid_loc.y() = row * m_cell_size; - for (coord_t col = grid.min.x(); col <= grid.max.y(); ++ col) { - grid_loc.x() = col * m_cell_size; + for (grid_addr.y() = grid.min.y(); grid_addr.y() <= grid.max.y(); ++grid_addr.y()) { + for (grid_addr.x() = grid.min.x(); grid_addr.x() <= grid.max.x(); ++grid_addr.x()) { + grid_loc = this->from_grid_point(grid_addr); // Test inside a circle at the new leaf. - if ((grid_loc - added_leaf).cast().squaredNorm() > m_supporting_radius2) { + if ((grid_loc - added_leaf).cast().squaredNorm() > m_supporting_radius2) { // Not inside a circle at the end of the new leaf. // Test inside a rotated rectangle. Vec2d vx = (grid_loc - to_node).cast(); @@ -84,10 +96,10 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf) } // Inside a circle at the end of the new leaf, or inside a rotated rectangle. // Remove unsupported leafs at this grid location. - if (auto it = m_unsupported_points_grid.find(grid_loc); it != m_unsupported_points_grid.end()) { + if (auto it = m_unsupported_points_grid.find(grid_addr); it != m_unsupported_points_grid.end()) { std::list::iterator& list_it = it->second; UnsupportedCell& cell = *list_it; - if ((cell.loc - added_leaf).cast().squaredNorm() <= m_supporting_radius2) { + if ((cell.loc - added_leaf).cast().squaredNorm() <= m_supporting_radius2) { m_unsupported_points.erase(list_it); m_unsupported_points_grid.erase(it); } @@ -96,4 +108,25 @@ void DistanceField::update(const Point& to_node, const Point& added_leaf) } } +#if 0 +void DistanceField::update(const Point &to_node, const Point &added_leaf) +{ + const Point supporting_radius_point(m_supporting_radius, m_supporting_radius); + const BoundingBox grid(this->to_grid_point(added_leaf - supporting_radius_point), this->to_grid_point(added_leaf + supporting_radius_point)); + + for (coord_t grid_y = grid.min.y(); grid_y <= grid.max.y(); ++grid_y) { + for (coord_t grid_x = grid.min.x(); grid_x <= grid.max.x(); ++grid_x) { + if (auto it = m_unsupported_points_grid.find({grid_x, grid_y}); it != m_unsupported_points_grid.end()) { + std::list::iterator &list_it = it->second; + UnsupportedCell &cell = *list_it; + if ((cell.loc - added_leaf).cast().squaredNorm() <= m_supporting_radius2) { + m_unsupported_points.erase(list_it); + m_unsupported_points_grid.erase(it); + } + } + } + } +} +#endif + } // namespace Slic3r::FillLightning diff --git a/src/libslic3r/Fill/Lightning/DistanceField.hpp b/src/libslic3r/Fill/Lightning/DistanceField.hpp index 7fdce434ce..beb46c5c57 100644 --- a/src/libslic3r/Fill/Lightning/DistanceField.hpp +++ b/src/libslic3r/Fill/Lightning/DistanceField.hpp @@ -4,6 +4,7 @@ #ifndef LIGHTNING_DISTANCE_FIELD_H #define LIGHTNING_DISTANCE_FIELD_H +#include "../../BoundingBox.hpp" #include "../../Point.hpp" #include "../../Polygon.hpp" @@ -29,7 +30,7 @@ public: * \param current_overhang The overhang that needs to be supported on this * layer. */ - DistanceField(const coord_t& radius, const Polygons& current_outline, const Polygons& current_overhang); + DistanceField(const coord_t& radius, const Polygons& current_outline, const BoundingBox& current_outlines_bbox, const Polygons& current_overhang); /*! * Gets the next unsupported location to be supported by a new branch. @@ -69,14 +70,14 @@ protected: * branch of a tree. */ coord_t m_supporting_radius; - double m_supporting_radius2; + int64_t m_supporting_radius2; /*! * Represents a small discrete area of infill that needs to be supported. */ struct UnsupportedCell { - UnsupportedCell(Point loc, coord_t dist_to_boundary) : loc(loc), dist_to_boundary(dist_to_boundary) {} + UnsupportedCell(const Point &loc, coord_t dist_to_boundary) : loc(loc), dist_to_boundary(dist_to_boundary) {} // The position of the center of this cell. Point loc; // How far this cell is removed from the ``current_outline`` polygon, the edge of the infill area. @@ -88,11 +89,30 @@ protected: */ std::list m_unsupported_points; + /*! + * BoundingBox of all points in m_unsupported_points. Used for mapping of sign integer numbers to positive integer numbers. + */ + const BoundingBox m_unsupported_points_bbox; + /*! * Links the unsupported points to a grid point, so that we can quickly look * up the cell belonging to a certain position in the grid. */ std::unordered_map::iterator, PointHash> m_unsupported_points_grid; + + /*! + * Maps the point to the grid coordinates. + */ + Point to_grid_point(const Point &point) const { + return (point - m_unsupported_points_bbox.min) / m_cell_size; + } + + /*! + * Maps the point to the grid coordinates. + */ + Point from_grid_point(const Point &point) const { + return point * m_cell_size + m_unsupported_points_bbox.min; + } }; } // namespace Slic3r::FillLightning diff --git a/src/libslic3r/Fill/Lightning/Generator.cpp b/src/libslic3r/Fill/Lightning/Generator.cpp index 87b593f89b..6a4a675cbe 100644 --- a/src/libslic3r/Fill/Lightning/Generator.cpp +++ b/src/libslic3r/Fill/Lightning/Generator.cpp @@ -35,17 +35,17 @@ Generator::Generator(const PrintObject &print_object) // const int infill_extruder = region_config.infill_extruder.value; const double default_infill_extrusion_width = Flow::auto_extrusion_width(FlowRole::frInfill, float(max_nozzle_diameter)); // Note: There's not going to be a layer below the first one, so the 'initial layer height' doesn't have to be taken into account. - const double layer_thickness = object_config.layer_height; + const double layer_thickness = scaled(object_config.layer_height.value); m_infill_extrusion_width = scaled(region_config.infill_extrusion_width.percent ? default_infill_extrusion_width * 0.01 * region_config.infill_extrusion_width : region_config.infill_extrusion_width); - m_supporting_radius = scaled(m_infill_extrusion_width * 0.001 / region_config.fill_density); + m_supporting_radius = coord_t(m_infill_extrusion_width) * 100 / coord_t(region_config.fill_density.value); - const double lightning_infill_overhang_angle = M_PI / 4; // 45 degrees - const double lightning_infill_prune_angle = M_PI / 4; // 45 degrees + const double lightning_infill_overhang_angle = M_PI / 4; // 45 degrees + const double lightning_infill_prune_angle = M_PI / 4; // 45 degrees const double lightning_infill_straightening_angle = M_PI / 4; // 45 degrees - m_wall_supporting_radius = layer_thickness * std::tan(lightning_infill_overhang_angle); - m_prune_length = layer_thickness * std::tan(lightning_infill_prune_angle); - m_straightening_max_distance = layer_thickness * std::tan(lightning_infill_straightening_angle); + m_wall_supporting_radius = coord_t(layer_thickness * std::tan(lightning_infill_overhang_angle)); + m_prune_length = coord_t(layer_thickness * std::tan(lightning_infill_prune_angle)); + m_straightening_max_distance = coord_t(layer_thickness * std::tan(lightning_infill_straightening_angle)); generateInitialInternalOverhangs(print_object); generateTrees(print_object); @@ -54,19 +54,20 @@ Generator::Generator(const PrintObject &print_object) void Generator::generateInitialInternalOverhangs(const PrintObject &print_object) { m_overhang_per_layer.resize(print_object.layers().size()); - const float infill_wall_offset = - m_infill_extrusion_width; + // FIXME: It can be adjusted to improve bonding between infill and perimeters. + const float infill_wall_offset = 0;// m_infill_extrusion_width; Polygons infill_area_above; //Iterate from top to bottom, to subtract the overhang areas above from the overhang areas on the layer below, to get only overhang in the top layer where it is overhanging. - for (int layer_nr = print_object.layers().size() - 1; layer_nr >= 0; layer_nr--) { + for (int layer_nr = int(print_object.layers().size()) - 1; layer_nr >= 0; layer_nr--) { Polygons infill_area_here; for (const LayerRegion* layerm : print_object.get_layer(layer_nr)->regions()) for (const Surface& surface : layerm->fill_surfaces.surfaces) if (surface.surface_type == stInternal) - append(infill_area_here, offset(surface.expolygon, infill_wall_offset)); + append(infill_area_here, infill_wall_offset == 0 ? surface.expolygon : offset(surface.expolygon, infill_wall_offset)); //Remove the part of the infill area that is already supported by the walls. - Polygons overhang = diff(offset(infill_area_here, -m_wall_supporting_radius), infill_area_above); + Polygons overhang = diff(offset(infill_area_here, -float(m_wall_supporting_radius)), infill_area_above); m_overhang_per_layer[layer_nr] = overhang; infill_area_above = std::move(infill_area_here); @@ -82,16 +83,17 @@ const Layer& Generator::getTreesForLayer(const size_t& layer_id) const void Generator::generateTrees(const PrintObject &print_object) { m_lightning_layers.resize(print_object.layers().size()); - const coord_t infill_wall_offset = - m_infill_extrusion_width; + // FIXME: It can be adjusted to improve bonding between infill and perimeters. + const coord_t infill_wall_offset = 0;// m_infill_extrusion_width; std::vector infill_outlines(print_object.layers().size(), Polygons()); // For-each layer from top to bottom: - for (int layer_id = print_object.layers().size() - 1; layer_id >= 0; layer_id--) + for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--) for (const LayerRegion *layerm : print_object.get_layer(layer_id)->regions()) for (const Surface &surface : layerm->fill_surfaces.surfaces) if (surface.surface_type == stInternal) - append(infill_outlines[layer_id], offset(surface.expolygon, infill_wall_offset)); + append(infill_outlines[layer_id], infill_wall_offset == 0 ? surface.expolygon : offset(surface.expolygon, infill_wall_offset)); // For various operations its beneficial to quickly locate nearby features on the polygon: const size_t top_layer_id = print_object.layers().size() - 1; @@ -99,16 +101,16 @@ void Generator::generateTrees(const PrintObject &print_object) outlines_locator.create(infill_outlines[top_layer_id], locator_cell_size); // For-each layer from top to bottom: - for (int layer_id = top_layer_id; layer_id >= 0; layer_id--) - { - Layer& current_lightning_layer = m_lightning_layers[layer_id]; - Polygons& current_outlines = infill_outlines[layer_id]; + for (int layer_id = int(top_layer_id); layer_id >= 0; layer_id--) { + Layer ¤t_lightning_layer = m_lightning_layers[layer_id]; + const Polygons ¤t_outlines = infill_outlines[layer_id]; + const BoundingBox ¤t_outlines_bbox = get_extents(current_outlines); // register all trees propagated from the previous layer as to-be-reconnected std::vector to_be_reconnected_tree_roots = current_lightning_layer.tree_roots; - current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, outlines_locator, m_supporting_radius, m_wall_supporting_radius); - current_lightning_layer.reconnectRoots(to_be_reconnected_tree_roots, current_outlines, outlines_locator, m_supporting_radius, m_wall_supporting_radius); + current_lightning_layer.generateNewTrees(m_overhang_per_layer[layer_id], current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius); + current_lightning_layer.reconnectRoots(to_be_reconnected_tree_roots, current_outlines, current_outlines_bbox, outlines_locator, m_supporting_radius, m_wall_supporting_radius); // Initialize trees for next lower layer from the current one. if (layer_id == 0) diff --git a/src/libslic3r/Fill/Lightning/Generator.hpp b/src/libslic3r/Fill/Lightning/Generator.hpp index c44ecfe7a2..b538c4dbe2 100644 --- a/src/libslic3r/Fill/Lightning/Generator.hpp +++ b/src/libslic3r/Fill/Lightning/Generator.hpp @@ -45,7 +45,7 @@ public: * already be calculated at this point. * \param mesh The mesh to generate infill for. */ - Generator(const PrintObject &print_object); + explicit Generator(const PrintObject &print_object); /*! * Get a tree of paths generated for a certain layer of the mesh. diff --git a/src/libslic3r/Fill/Lightning/Layer.cpp b/src/libslic3r/Fill/Lightning/Layer.cpp index 1b3936e340..1e1127a792 100644 --- a/src/libslic3r/Fill/Lightning/Layer.cpp +++ b/src/libslic3r/Fill/Lightning/Layer.cpp @@ -3,12 +3,11 @@ #include "Layer.hpp" //The class we're implementing. -#include // advance - #include "DistanceField.hpp" #include "TreeNode.hpp" #include "../../Geometry.hpp" +#include "Utils.hpp" namespace Slic3r::FillLightning { @@ -23,10 +22,15 @@ Point GroundingLocation::p() const return tree_node ? tree_node->getLocation() : *boundary_location; } -void Layer::fillLocator(SparseNodeGrid &tree_node_locator) +inline static Point to_grid_point(const Point &point, const BoundingBox &bbox) { - std::function add_node_to_locator_func = [&tree_node_locator](NodeSPtr node) { - tree_node_locator.insert(std::make_pair(Point(node->getLocation().x() / locator_cell_size, node->getLocation().y() / locator_cell_size), node)); + return (point - bbox.min) / locator_cell_size; +} + +void Layer::fillLocator(SparseNodeGrid &tree_node_locator, const BoundingBox& current_outlines_bbox) +{ + std::function add_node_to_locator_func = [&tree_node_locator, ¤t_outlines_bbox](const NodeSPtr &node) { + tree_node_locator.insert(std::make_pair(to_grid_point(node->getLocation(), current_outlines_bbox), node)); }; for (auto& tree : tree_roots) tree->visitNodes(add_node_to_locator_func); @@ -36,38 +40,46 @@ void Layer::generateNewTrees ( const Polygons& current_overhang, const Polygons& current_outlines, + const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outlines_locator, const coord_t supporting_radius, const coord_t wall_supporting_radius ) { - DistanceField distance_field(supporting_radius, current_outlines, current_overhang); + DistanceField distance_field(supporting_radius, current_outlines, current_outlines_bbox, current_overhang); SparseNodeGrid tree_node_locator; - fillLocator(tree_node_locator); + fillLocator(tree_node_locator, current_outlines_bbox); // Until no more points need to be added to support all: // Determine next point from tree/outline areas via distance-field Point unsupported_location; while (distance_field.tryGetNextPoint(&unsupported_location)) { GroundingLocation grounding_loc = getBestGroundingLocation( - unsupported_location, current_outlines, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator); + unsupported_location, current_outlines, current_outlines_bbox, outlines_locator, supporting_radius, wall_supporting_radius, tree_node_locator); NodeSPtr new_parent; NodeSPtr new_child; this->attach(unsupported_location, grounding_loc, new_child, new_parent); - tree_node_locator.insert(std::make_pair(Point(new_child->getLocation().x() / locator_cell_size, new_child->getLocation().y() / locator_cell_size), new_child)); + tree_node_locator.insert(std::make_pair(to_grid_point(new_child->getLocation(), current_outlines_bbox), new_child)); if (new_parent) - tree_node_locator.insert(std::make_pair(Point(new_parent->getLocation().x() / locator_cell_size, new_parent->getLocation().y() / locator_cell_size), new_parent)); + tree_node_locator.insert(std::make_pair(to_grid_point(new_parent->getLocation(), current_outlines_bbox), new_parent)); // update distance field distance_field.update(grounding_loc.p(), unsupported_location); } + +#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT + { + static int iRun = 0; + export_to_svg(debug_out_path("FillLightning-TreeNodes-%d.svg", iRun++), current_outlines, this->tree_roots); + } +#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */ } -static bool polygonCollidesWithLineSegment(const Point from, const Point to, const EdgeGrid::Grid &loc_to_line) +static bool polygonCollidesWithLineSegment(const Point &from, const Point &to, const EdgeGrid::Grid &loc_to_line) { struct Visitor { - explicit Visitor(const EdgeGrid::Grid &grid) : grid(grid) {} + explicit Visitor(const EdgeGrid::Grid &grid, const Line &line) : grid(grid), line(line) {} bool operator()(coord_t iy, coord_t ix) { // Called with a row and colum of the grid cell, which is intersected by a line. @@ -87,7 +99,7 @@ static bool polygonCollidesWithLineSegment(const Point from, const Point to, con const EdgeGrid::Grid& grid; Line line; bool intersect = false; - } visitor(loc_to_line); + } visitor(loc_to_line, {from, to}); loc_to_line.visit_cells_intersecting_line(from, to, visitor); return visitor.intersect; @@ -97,6 +109,7 @@ GroundingLocation Layer::getBestGroundingLocation ( const Point& unsupported_location, const Polygons& current_outlines, + const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outline_locator, const coord_t supporting_radius, const coord_t wall_supporting_radius, @@ -128,8 +141,8 @@ GroundingLocation Layer::getBestGroundingLocation if (current_dist >= wall_supporting_radius) { // Only reconnect tree roots to other trees if they are not already close to the outlines. const coord_t search_radius = std::min(current_dist, within_dist); BoundingBox region(unsupported_location - Point(search_radius, search_radius), unsupported_location + Point(search_radius + locator_cell_size, search_radius + locator_cell_size)); - region.min /= locator_cell_size; - region.max /= locator_cell_size; + region.min = to_grid_point(region.min, current_outlines_bbox); + region.max = to_grid_point(region.max, current_outlines_bbox); Point grid_addr; for (grid_addr.y() = region.min.y(); grid_addr.y() < region.max.y(); ++ grid_addr.y()) for (grid_addr.x() = region.min.x(); grid_addr.x() < region.max.x(); ++ grid_addr.x()) { @@ -176,6 +189,7 @@ void Layer::reconnectRoots ( std::vector& to_be_reconnected_tree_roots, const Polygons& current_outlines, + const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outline_locator, const coord_t supporting_radius, const coord_t wall_supporting_radius @@ -184,10 +198,10 @@ void Layer::reconnectRoots constexpr coord_t tree_connecting_ignore_offset = 100; SparseNodeGrid tree_node_locator; - fillLocator(tree_node_locator); + fillLocator(tree_node_locator, current_outlines_bbox); const coord_t within_max_dist = outline_locator.resolution() * 2; - for (auto root_ptr : to_be_reconnected_tree_roots) + for (const auto &root_ptr : to_be_reconnected_tree_roots) { auto old_root_it = std::find(tree_roots.begin(), tree_roots.end(), root_ptr); @@ -203,7 +217,7 @@ void Layer::reconnectRoots root_ptr->addChild(new_root); new_root->reroot(); - tree_node_locator.insert(std::make_pair(Point(new_root->getLocation().x() / locator_cell_size, new_root->getLocation().y() / locator_cell_size), new_root)); + tree_node_locator.insert(std::make_pair(to_grid_point(new_root->getLocation(), current_outlines_bbox), new_root)); *old_root_it = std::move(new_root); // replace old root with new root continue; @@ -217,6 +231,7 @@ void Layer::reconnectRoots ( root_ptr->getLocation(), current_outlines, + current_outlines_bbox, outline_locator, supporting_radius, tree_connecting_ignore_width, @@ -233,7 +248,7 @@ void Layer::reconnectRoots attach_ptr->reroot(); new_root->addChild(attach_ptr); - tree_node_locator.insert(std::make_pair(new_root->getLocation(), new_root)); + tree_node_locator.insert(std::make_pair(to_grid_point(new_root->getLocation(), current_outlines_bbox), new_root)); *old_root_it = std::move(new_root); // replace old root with new root } @@ -256,15 +271,25 @@ void Layer::reconnectRoots } } -/* - * Implementation assumes moving inside, but moving outside should just as well be possible. +/*! + * Moves the point \p from onto the nearest polygon or leaves the point as-is, when the comb boundary is not within the root of \p max_dist2 distance. + * Given a \p distance more than zero, the point will end up inside, and conversely outside. + * When the point is already in/outside by more than \p distance, \p from is unaltered, but the polygon is returned. + * When the point is in/outside by less than \p distance, \p from is moved to the correct place. + * Implementation assumes moving inside, but moving outside should just as well be possible. + * + * \param polygons The polygons onto which to move the point + * \param from[in,out] The point to move. + * \param distance The distance by which to move the point. + * \param max_dist2 The squared maximal allowed distance from the point to the nearest polygon. + * \return The index to the polygon onto which we have moved the point. */ static unsigned int moveInside(const Polygons& polygons, Point& from, int distance, int64_t maxDist2) { - Point ret = from; - int64_t bestDist2 = std::numeric_limits::max(); - unsigned int bestPoly = static_cast(-1); - bool is_already_on_correct_side_of_boundary = false; // whether [from] is already on the right side of the boundary + Point ret = from; + int64_t bestDist2 = std::numeric_limits::max(); + auto bestPoly = static_cast(-1); + bool is_already_on_correct_side_of_boundary = false; // whether [from] is already on the right side of the boundary for (unsigned int poly_idx = 0; poly_idx < polygons.size(); poly_idx++) { const Polygon &poly = polygons[poly_idx]; @@ -333,7 +358,7 @@ static unsigned int moveInside(const Polygons& polygons, Point& from, int distan else { // x is projected to a point properly on the line segment (not onto a vertex). The case which looks like | . projected_p_beyond_prev_segment = false; - Point x = a + ab * dot_prod / ab_length2; + Point x = (a.cast() + ab.cast() * dot_prod / ab_length2).cast(); int64_t dist2 = (p - x).cast().squaredNorm(); if (dist2 < bestDist2) diff --git a/src/libslic3r/Fill/Lightning/Layer.hpp b/src/libslic3r/Fill/Lightning/Layer.hpp index 853c634f27..cc79c15b51 100644 --- a/src/libslic3r/Fill/Lightning/Layer.hpp +++ b/src/libslic3r/Fill/Lightning/Layer.hpp @@ -41,9 +41,10 @@ public: ( const Polygons& current_overhang, const Polygons& current_outlines, + const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outline_locator, - const coord_t supporting_radius, - const coord_t wall_supporting_radius + coord_t supporting_radius, + coord_t wall_supporting_radius ); /*! Determine & connect to connection point in tree/outline. @@ -53,9 +54,10 @@ public: ( const Point& unsupported_location, const Polygons& current_outlines, + const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outline_locator, - const coord_t supporting_radius, - const coord_t wall_supporting_radius, + coord_t supporting_radius, + coord_t wall_supporting_radius, const SparseNodeGrid& tree_node_locator, const NodeSPtr& exclude_tree = nullptr ); @@ -71,16 +73,17 @@ public: ( std::vector& to_be_reconnected_tree_roots, const Polygons& current_outlines, + const BoundingBox& current_outlines_bbox, const EdgeGrid::Grid& outline_locator, - const coord_t supporting_radius, - const coord_t wall_supporting_radius + coord_t supporting_radius, + coord_t wall_supporting_radius ); - Polylines convertToLines(const Polygons& limit_to_outline, const coord_t line_width) const; + Polylines convertToLines(const Polygons& limit_to_outline, coord_t line_width) const; coord_t getWeightedDistance(const Point& boundary_loc, const Point& unsupported_location); - void fillLocator(SparseNodeGrid& tree_node_locator); + void fillLocator(SparseNodeGrid& tree_node_locator, const BoundingBox& current_outlines_bbox); }; } // namespace Slic3r::FillLightning diff --git a/src/libslic3r/Fill/Lightning/TreeNode.cpp b/src/libslic3r/Fill/Lightning/TreeNode.cpp index 8ab11bd6d4..b36a66dbb7 100644 --- a/src/libslic3r/Fill/Lightning/TreeNode.cpp +++ b/src/libslic3r/Fill/Lightning/TreeNode.cpp @@ -4,7 +4,6 @@ #include "TreeNode.hpp" #include "../../Geometry.hpp" -#include "../../ClipperUtils.hpp" namespace Slic3r::FillLightning { @@ -107,7 +106,7 @@ NodeSPtr Node::deepCopy() const return local_root; } -void Node::reroot(NodeSPtr new_parent /*= nullptr*/) +void Node::reroot(const NodeSPtr &new_parent) { if (! m_is_root) { auto old_parent = m_parent.lock(); @@ -142,7 +141,7 @@ NodeSPtr Node::closestNode(const Point& loc) return result; } -bool inside(const Polygons &polygons, const Point p) +bool inside(const Polygons &polygons, const Point &p) { int poly_count_inside = 0; for (const Polygon &poly : polygons) { @@ -181,7 +180,7 @@ bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeG } visitor { outline_locator, a.cast(), b.cast() }; outline_locator.visit_cells_intersecting_line(a, b, visitor); - return visitor.d2min < within_max_dist * within_max_dist; + return visitor.d2min < double(within_max_dist) * double(within_max_dist); } bool Node::realign(const Polygons& outlines, const EdgeGrid::Grid& outline_locator, std::vector& rerooted_parts) @@ -226,14 +225,14 @@ bool Node::realign(const Polygons& outlines, const EdgeGrid::Grid& outline_locat void Node::straighten(const coord_t magnitude, const coord_t max_remove_colinear_dist) { - straighten(magnitude, m_p, 0, max_remove_colinear_dist * max_remove_colinear_dist); + straighten(magnitude, m_p, 0, int64_t(max_remove_colinear_dist) * int64_t(max_remove_colinear_dist)); } Node::RectilinearJunction Node::straighten( const coord_t magnitude, const Point& junction_above, const coord_t accumulated_dist, - const coord_t max_remove_colinear_dist2) + const int64_t max_remove_colinear_dist2) { constexpr coord_t junction_magnitude_factor_numerator = 3; constexpr coord_t junction_magnitude_factor_denominator = 4; @@ -245,13 +244,13 @@ Node::RectilinearJunction Node::straighten( auto child_dist = coord_t((m_p - child_p->m_p).cast().norm()); RectilinearJunction junction_below = child_p->straighten(magnitude, junction_above, accumulated_dist + child_dist, max_remove_colinear_dist2); coord_t total_dist_to_junction_below = junction_below.total_recti_dist; - Point a = junction_above; - Point b = junction_below.junction_loc; + const Point& a = junction_above; + Point b = junction_below.junction_loc; if (a != b) // should always be true! { Point ab = b - a; - Point destination = a + ab * accumulated_dist / std::max(coord_t(1), total_dist_to_junction_below); - if ((destination - m_p).cast().squaredNorm() <= magnitude * magnitude) + Point destination = (a.cast() + ab.cast() * int64_t(accumulated_dist) / std::max(int64_t(1), int64_t(total_dist_to_junction_below))).cast(); + if ((destination - m_p).cast().squaredNorm() <= int64_t(magnitude) * int64_t(magnitude)) m_p = destination; else m_p += ((destination - m_p).cast().normalized() * magnitude).cast(); @@ -262,7 +261,7 @@ Node::RectilinearJunction Node::straighten( child_p = m_children.front(); //recursive call to straighten might have removed the child const NodeSPtr& parent_node = m_parent.lock(); if (parent_node && - (child_p->m_p - parent_node->m_p).cast().squaredNorm() < max_remove_colinear_dist2 && + (child_p->m_p - parent_node->m_p).cast().squaredNorm() < max_remove_colinear_dist2 && Line::distance_to_squared(m_p, parent_node->m_p, child_p->m_p) < close_enough * close_enough) { child_p->m_parent = m_parent; for (auto& sibling : parent_node->m_children) @@ -347,7 +346,7 @@ coord_t Node::prune(const coord_t& pruning_distance) void Node::convertToPolylines(Polygons& output, const coord_t line_width) const { Polygons result; - output.emplace_back(); + result.emplace_back(); convertToPolylines(0, result); removeJunctionOverlap(result, line_width); append(output, std::move(result)); @@ -386,7 +385,7 @@ void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_widt coord_t to_be_reduced = reduction; Point a = polyline.back(); - for (int point_idx = polyline.size() - 2; point_idx >= 0; point_idx--) { + for (int point_idx = int(polyline.size()) - 2; point_idx >= 0; point_idx--) { const Point b = polyline[point_idx]; const Point ab = b - a; const auto ab_len = coord_t(ab.cast().norm()); @@ -408,4 +407,29 @@ void Node::removeJunctionOverlap(Polygons& result_lines, const coord_t line_widt } } +#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT +void export_to_svg(const NodeSPtr &root_node, SVG &svg) +{ + for (const NodeSPtr &children : root_node->m_children) { + svg.draw(Line(root_node->getLocation(), children->getLocation()), "red"); + export_to_svg(children, svg); + } +} + +void export_to_svg(const std::string &path, const Polygons &contour, const std::vector &root_nodes) { + BoundingBox bbox = get_extents(contour); + + bbox.offset(SCALED_EPSILON); + SVG svg(path, bbox); + svg.draw_outline(contour, "blue"); + + for (const NodeSPtr &root_node: root_nodes) { + for (const NodeSPtr &children: root_node->m_children) { + svg.draw(Line(root_node->getLocation(), children->getLocation()), "red"); + export_to_svg(children, svg); + } + } +} +#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */ + } // namespace Slic3r::FillLightning diff --git a/src/libslic3r/Fill/Lightning/TreeNode.hpp b/src/libslic3r/Fill/Lightning/TreeNode.hpp index bc2e76dc2f..55ef35e0a8 100644 --- a/src/libslic3r/Fill/Lightning/TreeNode.hpp +++ b/src/libslic3r/Fill/Lightning/TreeNode.hpp @@ -11,6 +11,9 @@ #include "../../EdgeGrid.hpp" #include "../../Polygon.hpp" +#include "SVG.hpp" + +//#define LIGHTNING_TREE_NODE_DEBUG_OUTPUT namespace Slic3r::FillLightning { @@ -99,9 +102,9 @@ public: std::vector& next_trees, const Polygons& next_outlines, const EdgeGrid::Grid& outline_locator, - const coord_t prune_distance, - const coord_t smooth_magnitude, - const coord_t max_remove_colinear_dist + coord_t prune_distance, + coord_t smooth_magnitude, + coord_t max_remove_colinear_dist ) const; /*! @@ -156,7 +159,7 @@ public: * This is then recursively bubbled up until it reaches the (former) root, which then will become a leaf. * \param new_parent The (new) parent-node of the root, useful for recursing or immediately attaching the node to another tree. */ - void reroot(NodeSPtr new_parent = nullptr); + void reroot(const NodeSPtr &new_parent = nullptr); /*! * Retrieves the closest node to the specified location. @@ -211,7 +214,7 @@ protected: * \param magnitude The maximum allowed distance to move the node. * \param max_remove_colinear_dist Maximum distance of the (compound) line-segment from which a co-linear point may be removed. */ - void straighten(const coord_t magnitude, const coord_t max_remove_colinear_dist); + void straighten(coord_t magnitude, coord_t max_remove_colinear_dist); /*! Recursive part of \ref straighten(.) * \param junction_above The last seen junction with multiple children above @@ -219,7 +222,7 @@ protected: * \param max_remove_colinear_dist2 Maximum distance _squared_ of the (compound) line-segment from which a co-linear point may be removed. * \return the total distance along the tree from the last junction above to the first next junction below and the location of the next junction below */ - RectilinearJunction straighten(const coord_t magnitude, const Point& junction_above, const coord_t accumulated_dist, const coord_t max_remove_colinear_dist2); + RectilinearJunction straighten(coord_t magnitude, const Point& junction_above, coord_t accumulated_dist, int64_t max_remove_colinear_dist2); /*! Prune the tree from the extremeties (leaf-nodes) until the pruning distance is reached. * \return The distance that has been pruned. If less than \p distance, then the whole tree was puned away. @@ -236,7 +239,7 @@ public: * * \param output all branches in this tree connected into polylines */ - void convertToPolylines(Polygons& output, const coord_t line_width) const; + void convertToPolylines(Polygons& output, coord_t line_width) const; /*! If this was ever a direct child of the root, it'll have a previous grounding location. * @@ -257,7 +260,7 @@ protected: */ void convertToPolylines(size_t long_line_idx, Polygons& output) const; - void removeJunctionOverlap(Polygons& polylines, const coord_t line_width) const; + void removeJunctionOverlap(Polygons& polylines, coord_t line_width) const; bool m_is_root; Point m_p; @@ -265,10 +268,20 @@ protected: std::vector m_children; std::optional m_last_grounding_location; // &root_nodes); +#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */ }; -bool inside(const Polygons &polygons, const Point p); -bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeGrid::Grid& outline_locator, Point& result, const coord_t within_max_dist); +bool inside(const Polygons &polygons, const Point &p); +bool lineSegmentPolygonsIntersection(const Point& a, const Point& b, const EdgeGrid::Grid& outline_locator, Point& result, coord_t within_max_dist); + +#ifdef LIGHTNING_TREE_NODE_DEBUG_OUTPUT +void export_to_svg(const NodeSPtr &root_node, SVG &svg); +void export_to_svg(const std::string &path, const Polygons &contour, const std::vector &root_nodes); +#endif /* LIGHTNING_TREE_NODE_DEBUG_OUTPUT */ } // namespace Slic3r::FillLightning diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 0071c7f6e1..a308ac0b62 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -20,6 +20,10 @@ namespace FillAdaptive { struct Octree; }; +namespace FillLightning { + class Generator; +}; + class LayerRegion { public: @@ -151,8 +155,8 @@ public: } void make_perimeters(); // Phony version of make_fills() without parameters for Perl integration only. - void make_fills() { this->make_fills(nullptr, nullptr); } - void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree); + void make_fills() { this->make_fills(nullptr, nullptr, nullptr); } + void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator); void make_ironing(); void export_region_slices_to_svg(const char *path) const; diff --git a/src/libslic3r/Point.hpp b/src/libslic3r/Point.hpp index e5dc334f59..6b430c2fef 100644 --- a/src/libslic3r/Point.hpp +++ b/src/libslic3r/Point.hpp @@ -177,6 +177,11 @@ inline bool operator<(const Point &l, const Point &r) return l.x() < r.x() || (l.x() == r.x() && l.y() < r.y()); } +inline Point operator* (const Point& l, const double &r) +{ + return {coord_t(l.x() * r), coord_t(l.y() * r)}; +} + inline bool is_approx(const Point &p1, const Point &p2, coord_t epsilon = coord_t(SCALED_EPSILON)) { Point d = (p2 - p1).cwiseAbs(); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index c5e312a2bf..d99e24ca70 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -35,7 +35,13 @@ namespace FillAdaptive { struct Octree; struct OctreeDeleter; using OctreePtr = std::unique_ptr; -}; +}; // namespace FillAdaptive + +namespace FillLightning { + class Generator; + struct GeneratorDeleter; + using GeneratorPtr = std::unique_ptr; +}; // namespace FillLightning // Print step IDs for keeping track of the print state. // The Print steps are applied in this order. @@ -387,6 +393,7 @@ private: void combine_infill(); void _generate_support_material(); std::pair prepare_adaptive_infill_data(); + FillLightning::GeneratorPtr prepare_lightning_infill_data(); // XYZ in scaled coordinates Vec3crd m_size; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 5a674da846..b21ed56318 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -108,9 +108,7 @@ static const t_config_enum_values s_keys_map_InfillPattern { { "octagramspiral", ipOctagramSpiral }, { "adaptivecubic", ipAdaptiveCubic }, { "supportcubic", ipSupportCubic }, -#if HAS_LIGHTNING_INFILL { "lightning", ipLightning } -#endif // HAS_LIGHTNING_INFILL }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InfillPattern) @@ -1155,9 +1153,7 @@ void PrintConfigDef::init_fff_params() def->enum_values.push_back("octagramspiral"); def->enum_values.push_back("adaptivecubic"); def->enum_values.push_back("supportcubic"); -#if HAS_LIGHTNING_INFILL def->enum_values.push_back("lightning"); -#endif // HAS_LIGHTNING_INFILL def->enum_labels.push_back(L("Rectilinear")); def->enum_labels.push_back(L("Aligned Rectilinear")); def->enum_labels.push_back(L("Grid")); @@ -1174,9 +1170,7 @@ void PrintConfigDef::init_fff_params() def->enum_labels.push_back(L("Octagram Spiral")); def->enum_labels.push_back(L("Adaptive Cubic")); def->enum_labels.push_back(L("Support Cubic")); -#if HAS_LIGHTNING_INFILL def->enum_labels.push_back(L("Lightning")); -#endif // HAS_LIGHTNING_INFILL def->set_default_value(new ConfigOptionEnum(ipStars)); def = this->add("first_layer_acceleration", coFloat); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b97168e84e..950816fa91 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -57,14 +57,10 @@ enum class FuzzySkinType { All, }; -#define HAS_LIGHTNING_INFILL 0 - enum InfillPattern : int { ipRectilinear, ipMonotonic, ipAlignedRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb, - ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipSupportBase, -#if HAS_LIGHTNING_INFILL - ipLightning, -#endif // HAS_LIGHTNING_INFILL + ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipSupportBase, + ipLightning, ipCount, }; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 31d948db9d..9c6178f8b5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -14,6 +14,7 @@ #include "TriangleMeshSlicer.hpp" #include "Utils.hpp" #include "Fill/FillAdaptive.hpp" +#include "Fill/FillLightning.hpp" #include "Format/STL.hpp" #include @@ -353,14 +354,15 @@ void PrintObject::infill() if (this->set_started(posInfill)) { auto [adaptive_fill_octree, support_fill_octree] = this->prepare_adaptive_infill_data(); + auto lightning_generator = this->prepare_lightning_infill_data(); BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start"; tbb::parallel_for( tbb::blocked_range(0, m_layers.size()), - [this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree](const tbb::blocked_range& range) { + [this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree, &lightning_generator](const tbb::blocked_range& range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { m_print->throw_if_canceled(); - m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get()); + m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get(), lightning_generator.get()); } } ); @@ -453,6 +455,18 @@ std::pair PrintObject::prepare support_line_spacing ? build_octree(mesh, overhangs.front(), support_line_spacing, true) : OctreePtr()); } +FillLightning::GeneratorPtr PrintObject::prepare_lightning_infill_data() +{ + bool has_lightning_infill = false; + for (size_t region_id = 0; region_id < this->num_printing_regions(); ++region_id) + if (const PrintRegionConfig &config = this->printing_region(region_id).config(); config.fill_density > 0 && config.fill_pattern == ipLightning) { + has_lightning_infill = true; + break; + } + + return has_lightning_infill ? FillLightning::build_generator(std::as_const(*this)) : FillLightning::GeneratorPtr(); +} + void PrintObject::clear_layers() { for (Layer *l : m_layers) From 5de93c87843a8f5354077fb2a0424f3dab75a55b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 28 Feb 2022 10:53:39 +0100 Subject: [PATCH 02/46] Fixed incorrect handling of 3rd party 3MFs in SLA mode (#6100 and others) --- src/libslic3r/SLAPrint.cpp | 9 ++++++--- src/slic3r/GUI/GLCanvas3D.cpp | 8 +++++++- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 12 +++++++----- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 13 ++++++------- src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 2 +- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 72cb96dd04..81ce0d6cb0 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1174,7 +1174,8 @@ sla::SupportPoints SLAPrintObject::transformed_support_points() const { assert(m_model_object != nullptr); auto spts = m_model_object->sla_support_points; - auto tr = trafo().cast(); + const Transform3d& vol_trafo = m_model_object->volumes.front()->get_transformation().get_matrix(); + const Transform3f& tr = (trafo() * vol_trafo).cast(); for (sla::SupportPoint& suppt : spts) { suppt.pos = tr * suppt.pos; } @@ -1186,8 +1187,10 @@ sla::DrainHoles SLAPrintObject::transformed_drainhole_points() const { assert(m_model_object != nullptr); auto pts = m_model_object->sla_drain_holes; - auto tr = trafo().cast(); - auto sc = m_model_object->instances.front()->get_scaling_factor().cast(); + const Transform3d& vol_trafo = m_model_object->volumes.front()->get_transformation().get_matrix(); + const Geometry::Transformation trans(trafo() * vol_trafo); + const Transform3f& tr = trans.get_matrix().cast(); + const Vec3f sc = trans.get_scaling_factor().cast(); for (sla::DrainHole &hl : pts) { hl.pos = tr * hl.pos; hl.normal = tr * hl.normal - tr.translation(); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ea08f98711..91add7c567 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2232,7 +2232,13 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (state.step[istep].state == PrintStateBase::DONE) { TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles); assert(! mesh.empty()); - mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse()); + + // sla_trafo does not contain volume trafo. To get a mesh to create + // a new volume from, we have to apply vol trafo inverse separately. + const ModelObject& mo = *m_model->objects[volume.object_idx()]; + Transform3d trafo = sla_print->sla_trafo(mo) + * mo.volumes.front()->get_transformation().get_matrix(); + mesh.transform(trafo.inverse()); #if ENABLE_SMOOTH_NORMALS #if ENABLE_LEGACY_OPENGL_REMOVAL volume.model.init_from(mesh, true); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index ebf8aa21b5..e979297df7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -122,9 +122,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) #endif // ENABLE_LEGACY_OPENGL_REMOVAL const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); + Geometry::Transformation trafo = vol->get_instance_transformation() * vol->get_volume_transformation(); + #if ENABLE_GL_SHADERS_ATTRIBUTES const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix(); + const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * trafo.get_matrix(); const Camera& camera = wxGetApp().plater()->get_camera(); const Transform3d& view_matrix = camera.get_view_matrix(); @@ -132,8 +134,8 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) shader->set_uniform("projection_matrix", projection_matrix); #else - const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); + const Transform3d& instance_scaling_matrix_inverse = trafo.get_matrix(true, true, false, true).inverse(); + const Transform3d& instance_matrix = trafo.get_matrix(); glsafe(::glPushMatrix()); glsafe(::glTranslated(0.0, 0.0, m_c->selection_info()->get_sla_shift())); @@ -222,7 +224,7 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const auto sel_info = m_c->selection_info(); int active_inst = m_c->selection_info()->get_active_instance(); const ModelInstance* mi = sel_info->model_object()->instances[active_inst]; - const Transform3d& trafo = mi->get_transformation().get_matrix(); + const Transform3d& trafo = mi->get_transformation().get_matrix() * sel_info->model_object()->volumes.front()->get_matrix(); Vec3d transformed_point = trafo * point; transformed_point(2) += sel_info->get_sla_shift(); @@ -241,7 +243,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera(); const Selection& selection = m_parent.get_selection(); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Geometry::Transformation trafo = volume->get_instance_transformation(); + Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation(); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); double clp_dist = m_c->object_clipper()->get_position(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 3173cb10dd..e8c2055f63 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -151,18 +151,17 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) #endif // ENABLE_LEGACY_OPENGL_REMOVAL const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); - const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); + Geometry::Transformation transformation(vol->get_instance_transformation().get_matrix() * vol->get_volume_transformation().get_matrix()); + const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse(); #if ENABLE_GL_SHADERS_ATTRIBUTES const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix(); - const Camera& camera = wxGetApp().plater()->get_camera(); const Transform3d& view_matrix = camera.get_view_matrix(); const Transform3d& projection_matrix = camera.get_projection_matrix(); shader->set_uniform("projection_matrix", projection_matrix); #else - const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); - + const Transform3d& instance_matrix = transformation.get_matrix(); const float z_shift = m_c->selection_info()->get_sla_shift(); glsafe(::glPushMatrix()); glsafe(::glTranslated(0.0, 0.0, z_shift)); @@ -344,7 +343,7 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const auto sel_info = m_c->selection_info(); int active_inst = m_c->selection_info()->get_active_instance(); const ModelInstance* mi = sel_info->model_object()->instances[active_inst]; - const Transform3d& trafo = mi->get_transformation().get_matrix(); + const Transform3d& trafo = mi->get_transformation().get_matrix() * sel_info->model_object()->volumes.front()->get_matrix(); Vec3d transformed_point = trafo * point; transformed_point(2) += sel_info->get_sla_shift(); @@ -363,7 +362,7 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairget_camera(); const Selection& selection = m_parent.get_selection(); const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - Geometry::Transformation trafo = volume->get_instance_transformation(); + Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation(); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift())); double clp_dist = m_c->object_clipper()->get_position(); @@ -1238,7 +1237,7 @@ void GLGizmoSlaSupports::get_data_from_backend() if (po->model_object()->id() == mo->id()) { m_normal_cache.clear(); const std::vector& points = po->get_support_points(); - auto mat = po->trafo().inverse().cast(); + auto mat = (po->trafo() * po->model_object()->volumes.front()->get_transformation().get_matrix()).inverse().cast(); for (unsigned int i=0; iget_mesh_to_slice(); if (! backend_mesh.empty()) { m_hollowed_mesh_transformed.reset(new TriangleMesh(backend_mesh)); - Transform3d trafo_inv = canvas->sla_print()->sla_trafo(*mo).inverse(); + Transform3d trafo_inv = (canvas->sla_print()->sla_trafo(*mo) * print_object->model_object()->volumes.front()->get_transformation().get_matrix()).inverse(); m_hollowed_mesh_transformed->transform(trafo_inv); m_drainholes = print_object->model_object()->sla_drain_holes; m_old_hollowing_timestamp = timestamp; From ff2b8da8dc731854b9bceca15c71ee72054b4333 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 17 Mar 2022 11:39:58 +0100 Subject: [PATCH 03/46] Fixed crash when pressing 'Reset rotation' button while editing SLA support points (mentioned in #7359) --- src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 42bb0e58c6..f1156f9377 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -251,7 +251,7 @@ void HollowedMesh::on_update() const GLCanvas3D* canvas = get_pool()->get_canvas(); const PrintObjects& print_objects = canvas->sla_print()->objects(); - const SLAPrintObject* print_object = m_print_object_idx != -1 + const SLAPrintObject* print_object = (m_print_object_idx >= 0 && m_print_object_idx < int(print_objects.size())) ? print_objects[m_print_object_idx] : nullptr; @@ -474,7 +474,7 @@ void SupportsClipper::on_update() const GLCanvas3D* canvas = get_pool()->get_canvas(); const PrintObjects& print_objects = canvas->sla_print()->objects(); - const SLAPrintObject* print_object = m_print_object_idx != -1 + const SLAPrintObject* print_object = (m_print_object_idx >= 0 && m_print_object_idx < int(print_objects.size())) ? print_objects[m_print_object_idx] : nullptr; From dfd6ca899a37fabd2ed8f6ed526fd8e60575e01a Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Thu, 17 Mar 2022 13:41:08 +0100 Subject: [PATCH 04/46] Sync with PrusaSlicer-settings --- resources/profiles/Ultimaker.idx | 1 + resources/profiles/Ultimaker.ini | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/profiles/Ultimaker.idx b/resources/profiles/Ultimaker.idx index a593d2fb4b..8e119931c1 100644 --- a/resources/profiles/Ultimaker.idx +++ b/resources/profiles/Ultimaker.idx @@ -1,2 +1,3 @@ min_slic3r_version = 2.4.0-beta0 +1.0.1 Updated start g-code. 1.0.0 Initial version diff --git a/resources/profiles/Ultimaker.ini b/resources/profiles/Ultimaker.ini index 363e0dec8a..1aeeab0a15 100644 --- a/resources/profiles/Ultimaker.ini +++ b/resources/profiles/Ultimaker.ini @@ -9,7 +9,7 @@ name = Ultimaker # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.0.0 +config_version = 1.0.1 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Ultimaker/ @@ -396,5 +396,5 @@ printer_notes = Dont remove the following keywords! These keywords are used in t nozzle_diameter = 0.4 default_print_profile = 0.20mm NORMAL @ULTIMAKER2 default_filament_profile = Generic PLA @ULTIMAKER2 -start_gcode = ; Printer_Settings_ID: [printer_settings_id]\n\n; # # # # # # START Header\nG21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM107 ; start with the fan off\n\nG28 X0 Y0 Z0 ; move X/Y/Z to endstops\nG1 X1 Y6 F15000 ; move X/Y to start position\nG1 Z35 F9000 ; move Z to start position\n\n; Heat up bed and nozzle\nM190 S{first_layer_bed_temperature[0] - 5} ; wait for bed temperature - 5\nM140 S[first_layer_bed_temperature] ; continue bed heating\nM109 S[first_layer_temperature] ; wait for nozzle temperature\n\nG92 E0 ; zero the extruded length\nG1 F150 E22 ; purge nozzle with filament\nG92 E0 ; zero the extruded length again\nG1 F75 E7 ; additional priming\nG92 E0 ; zero the extruded length again\n\n; # # # # # # END Header +start_gcode = start_gcode = ; Printer_Settings_ID: [printer_settings_id]\n\n; # # # # # # START Header\nG21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM107 ; start with the fan off\n\nM140 S[first_layer_bed_temperature] ; start bed heating\n\nG28 X0 Y0 Z0 ; move X/Y/Z to endstops\nG1 X1 Y6 F15000 ; move X/Y to start position\nG1 Z35 F9000 ; move Z to start position\n\n; Wait for bed and nozzle temperatures\nM190 S{first_layer_bed_temperature[0] - 5} ; wait for bed temperature - 5\nM140 S[first_layer_bed_temperature] ; continue bed heating\nM109 S[first_layer_temperature] ; wait for nozzle temperature\n\n; Purge and prime\nM83 ; set extruder to relative mode\nG92 E0 ; reset extrusion distance\nG0 X0 Y1 F10000\nG1 F150 E20 Y10 ; compress the bowden tube\nG1 E-8 F1200\nG0 X30 Y1 F5000 \nG0 F1200 Z{first_layer_height/2} ; Cut the connection to priming blob\nG0 X100 F10000 ; disconnect with the prime blob\nG0 X50 ; Avoid the metal clip holding the Ultimaker glass plate\nG0 Z0.2 F720\nG1 E8 F1200\nG1 X80 E3 F1000 ; intro line 1\nG1 X110 E4 F1000 ; intro line 2\nG1 X140 F600 ; drag filament to decompress bowden tube\nG1 X100 F3200 ; wipe backwards a bit\nG1 X150 F3200 ; back to where there is no plastic: avoid dragging\nG92 E0 ; reset extruder reference\nM82 ; set extruder to absolute mode\n\n; # # # # # # END Header end_gcode = ; # # # # # # START Footer\nG91 ; relative coordinates\n;G1 E-1 F1200 ; retract the filament\nG1 Z+15 X-10 Y-10 E-7 F6000 ; move Z a bit\n; G1 X-10 Y-10 F6000 ; move XY a bit\nG1 E-5.5 F300 ; retract the filament\nG28 X0 Y0 ; move X/Y to min endstops, so the head is out of the way\nM104 S0 ; extruder heater off\nM140 S0 ; heated bed heater off (if you have it)\nM84 ; disable motors\n; # # # # # # END Footer\n From 99861f1b6ec3793025d528f0badb63e837f8c808 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 17 Mar 2022 14:20:35 +0100 Subject: [PATCH 05/46] SPE-1207 - Extensions in Open/Save/Export dialogs - alternative implementation for file_wildcards() --- src/libslic3r/Technologies.hpp | 2 ++ src/slic3r/GUI/GUI_App.cpp | 40 ++++++++++++++++++++++++++++++++++ src/slic3r/GUI/GUI_App.hpp | 4 ++++ src/slic3r/GUI/Plater.cpp | 8 ++++++- 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 635fc49943..2ce7079fe1 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -84,6 +84,8 @@ #define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1) // Enable modified rectangle selection #define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1) +// Enable alternative version of file_wildcards() +#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_5_0_ALPHA1) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 87913fb812..ee91994252 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -499,6 +499,44 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = { /* FT_SL1 */ { "Masked SLA files"sv, { ".sl1"sv, ".sl1s"sv, ".pwmx"sv } }, }; +#if ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR +wxString file_wildcards(FileType file_type) +{ + const FileWildcards& data = file_wildcards_by_type[file_type]; + std::string title; + std::string mask; + + // Generate cumulative first item + for (const std::string_view& ext : data.file_extensions) { + if (title.empty()) { + title = "*"; + title += ext; + mask = title; + } + else { + title += ", *"; + title += ext; + mask += ";*"; + mask += ext; + } + mask += ";*"; + mask += boost::to_upper_copy(std::string(ext)); + } + + wxString ret = GUI::format_wxstr("%s (%s)|%s", data.title, title, mask); + + // Adds an item for each of the extensions + if (data.file_extensions.size() > 1) { + for (const std::string_view& ext : data.file_extensions) { + title = "*"; + title += ext; + ret += GUI::format_wxstr("|%s (%s)|%s", data.title, title, title); + } + } + + return ret; +} +#else // This function produces a Win32 file dialog file template mask to be consumed by wxWidgets on all platforms. // The function accepts a custom extension parameter. If the parameter is provided, the custom extension // will be added as a fist to the list. This is important for a "file save" dialog on OSX, which strips @@ -551,8 +589,10 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension) mask += ";*"; mask += boost::to_upper_copy(std::string(ext)); } + return GUI::format_wxstr("%s (%s)|%s", data.title, title, mask); } +#endif // ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 8b4177a8d7..f93728d2e3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -71,7 +71,11 @@ enum FileType FT_SIZE, }; +#if ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR +extern wxString file_wildcards(FileType file_type); +#else extern wxString file_wildcards(FileType file_type, const std::string &custom_extension = std::string{}); +#endif // ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR enum ConfigMenuIDs { ConfigMenuWizard, diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fc8ba23c51..daee3b0533 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5919,11 +5919,17 @@ void Plater::export_gcode(bool prefer_removable) fs::path output_path; { - std::string ext = default_output_file.extension().string(); +#if !ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR + std::string ext = default_output_file.extension().string(); +#endif // !ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _L("Save G-code file as:") : _L("Save SL1 / SL1S file as:"), start_dir, from_path(default_output_file.filename()), +#if ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR + GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_SL1), +#else GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_SL1, ext), +#endif // ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if (dlg.ShowModal() == wxID_OK) { From 8d5dd759ada887ca733f2cb689eccd6df1a6c88c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 17 Mar 2022 14:31:14 +0100 Subject: [PATCH 06/46] SPE-1208 - Fix for 3mf from another SW is loaded as a project and not as geometry --- src/slic3r/GUI/Plater.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index daee3b0533..df593f1300 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5566,7 +5566,7 @@ bool Plater::load_files(const wxArrayString& filenames) if (!model().objects.empty()) { if ((boost::algorithm::iends_with(filename, ".3mf") && !is_project_3mf(it->string())) || (boost::algorithm::iends_with(filename, ".amf") && !boost::algorithm::iends_with(filename, ".zip.amf"))) - load_type = LoadType::OpenProject; + load_type = LoadType::LoadGeometry; else { if (wxGetApp().app_config->get("show_drop_project_dialog") == "1") { ProjectDropDialog dlg(filename); From fb22612d0d422c6dfe88610a40fa207b7ad3ab1c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 17 Mar 2022 15:12:03 +0100 Subject: [PATCH 07/46] Tech ENABLE_SPIRAL_VASE_LAYERS set as default --- src/libslic3r/GCode/GCodeProcessor.cpp | 14 -------------- src/libslic3r/GCode/GCodeProcessor.hpp | 4 ---- src/libslic3r/Technologies.hpp | 2 -- src/slic3r/GUI/GCodeViewer.cpp | 2 -- 4 files changed, 22 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 3bf7c4ffd3..0c9d495446 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -737,9 +737,7 @@ void GCodeProcessorResult::reset() { filament_diameters = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER); filament_densities = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY); custom_gcode_per_print_z = std::vector(); -#if ENABLE_SPIRAL_VASE_LAYERS spiral_vase_layers = std::vector>>(); -#endif // ENABLE_SPIRAL_VASE_LAYERS time = 0; } #else @@ -755,9 +753,7 @@ void GCodeProcessorResult::reset() { filament_diameters = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER); filament_densities = std::vector(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY); custom_gcode_per_print_z = std::vector(); -#if ENABLE_SPIRAL_VASE_LAYERS spiral_vase_layers = std::vector>>(); -#endif // ENABLE_SPIRAL_VASE_LAYERS } #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -905,11 +901,9 @@ void GCodeProcessor::apply_config(const PrintConfig& config) m_result.max_print_height = config.max_print_height; -#if ENABLE_SPIRAL_VASE_LAYERS const ConfigOptionBool* spiral_vase = config.option("spiral_vase"); if (spiral_vase != nullptr) m_spiral_vase_active = spiral_vase->value; -#endif // ENABLE_SPIRAL_VASE_LAYERS #if ENABLE_Z_OFFSET_CORRECTION const ConfigOptionFloat* z_offset = config.option("z_offset"); @@ -1160,11 +1154,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config) if (max_print_height != nullptr) m_result.max_print_height = max_print_height->value; -#if ENABLE_SPIRAL_VASE_LAYERS const ConfigOptionBool* spiral_vase = config.option("spiral_vase"); if (spiral_vase != nullptr) m_spiral_vase_active = spiral_vase->value; -#endif // ENABLE_SPIRAL_VASE_LAYERS #if ENABLE_Z_OFFSET_CORRECTION const ConfigOptionFloat* z_offset = config.option("z_offset"); @@ -1238,9 +1230,7 @@ void GCodeProcessor::reset() m_options_z_corrector.reset(); -#if ENABLE_SPIRAL_VASE_LAYERS m_spiral_vase_active = false; -#endif // ENABLE_SPIRAL_VASE_LAYERS #if ENABLE_GCODE_VIEWER_DATA_CHECKING m_mm3_per_mm_compare.reset(); @@ -1950,7 +1940,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers // layer change tag if (comment == reserved_tag(ETags::Layer_Change)) { ++m_layer_id; -#if ENABLE_SPIRAL_VASE_LAYERS if (m_spiral_vase_active) { if (m_result.moves.empty()) m_result.spiral_vase_layers.push_back({ m_first_layer_height, { 0, 0 } }); @@ -1962,7 +1951,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers m_result.spiral_vase_layers.push_back({ static_cast(m_end_position[Z]), { move_id, move_id } }); } } -#endif // ENABLE_SPIRAL_VASE_LAYERS return; } @@ -2772,10 +2760,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]); } -#if ENABLE_SPIRAL_VASE_LAYERS if (m_spiral_vase_active && !m_result.spiral_vase_layers.empty() && !m_result.moves.empty()) m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1; -#endif // ENABLE_SPIRAL_VASE_LAYERS // store move store_move_vertex(type); diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 25375f61b6..e04caa6e22 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -131,9 +131,7 @@ namespace Slic3r { std::vector filament_densities; PrintEstimatedStatistics print_statistics; std::vector custom_gcode_per_print_z; -#if ENABLE_SPIRAL_VASE_LAYERS std::vector>> spiral_vase_layers; -#endif // ENABLE_SPIRAL_VASE_LAYERS #if ENABLE_GCODE_VIEWER_STATISTICS int64_t time{ 0 }; @@ -559,9 +557,7 @@ namespace Slic3r { SeamsDetector m_seams_detector; OptionsZCorrector m_options_z_corrector; size_t m_last_default_color_id; -#if ENABLE_SPIRAL_VASE_LAYERS bool m_spiral_vase_active; -#endif // ENABLE_SPIRAL_VASE_LAYERS #if ENABLE_GCODE_VIEWER_STATISTICS std::chrono::time_point m_start_time; #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 2ce7079fe1..de54e65091 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -41,8 +41,6 @@ //================ #define ENABLE_2_4_1_RC 1 -// Enable detection of layers for spiral vase prints -#define ENABLE_SPIRAL_VASE_LAYERS (1 && ENABLE_2_4_1_RC) // Enable correction of toolpaths when z offset is set #define ENABLE_Z_OFFSET_CORRECTION (1 && ENABLE_2_4_1_RC) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index d33004f494..5372d4565b 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2313,7 +2313,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) sort_remove_duplicates(m_extruder_ids); m_extruder_ids.shrink_to_fit(); -#if ENABLE_SPIRAL_VASE_LAYERS // replace layers for spiral vase mode if (!gcode_result.spiral_vase_layers.empty()) { m_layers.reset(); @@ -2321,7 +2320,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) m_layers.append(layer.first, { layer.second.first, layer.second.second }); } } -#endif // ENABLE_SPIRAL_VASE_LAYERS // set layers z range if (!m_layers.empty()) From 493050a279038ef5d70273b352131e6eadd90a3d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 17 Mar 2022 15:29:18 +0100 Subject: [PATCH 08/46] Removed redundant line of code --- src/slic3r/GUI/GUI_Preview.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 2cac5e3566..1488ffb2e5 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -1040,7 +1040,6 @@ void Preview::load_print_as_sla() if (IsShown()) { m_canvas->load_sla_preview(); m_left_sizer->Hide(m_bottom_toolbar_panel); - m_left_sizer->Hide(m_bottom_toolbar_panel); m_left_sizer->Layout(); Refresh(); From 45e4d905043b2321fed005e40e37b7527dd644a3 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 17 Mar 2022 15:44:03 +0100 Subject: [PATCH 09/46] GCodeViewer - Hide bottom toolbar when loading a new gcode file --- src/slic3r/GUI/GUI_Preview.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 1488ffb2e5..3eec8f823e 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -966,6 +966,11 @@ void Preview::load_print_as_fff(bool keep_z_range) Refresh(); zs = m_canvas->get_volumes_print_zs(true); } + else { + m_left_sizer->Hide(m_bottom_toolbar_panel); + m_left_sizer->Layout(); + Refresh(); + } if (!zs.empty() && !m_keep_current_preview_type) { unsigned int number_extruders = wxGetApp().is_editor() ? From b56874e9fe322ffc8a5029644bf889b3ca47a43f Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Thu, 17 Mar 2022 23:07:01 +0100 Subject: [PATCH 10/46] Sync with PrusaSlicer-settings 1.0.2 --- resources/profiles/Ultimaker.idx | 1 + resources/profiles/Ultimaker.ini | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/profiles/Ultimaker.idx b/resources/profiles/Ultimaker.idx index 8e119931c1..605b87e071 100644 --- a/resources/profiles/Ultimaker.idx +++ b/resources/profiles/Ultimaker.idx @@ -1,3 +1,4 @@ min_slic3r_version = 2.4.0-beta0 +1.0.2 Fixed start g-code. 1.0.1 Updated start g-code. 1.0.0 Initial version diff --git a/resources/profiles/Ultimaker.ini b/resources/profiles/Ultimaker.ini index 1aeeab0a15..f3e30db400 100644 --- a/resources/profiles/Ultimaker.ini +++ b/resources/profiles/Ultimaker.ini @@ -9,7 +9,7 @@ name = Ultimaker # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.0.1 +config_version = 1.0.2 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Ultimaker/ @@ -396,5 +396,5 @@ printer_notes = Dont remove the following keywords! These keywords are used in t nozzle_diameter = 0.4 default_print_profile = 0.20mm NORMAL @ULTIMAKER2 default_filament_profile = Generic PLA @ULTIMAKER2 -start_gcode = start_gcode = ; Printer_Settings_ID: [printer_settings_id]\n\n; # # # # # # START Header\nG21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM107 ; start with the fan off\n\nM140 S[first_layer_bed_temperature] ; start bed heating\n\nG28 X0 Y0 Z0 ; move X/Y/Z to endstops\nG1 X1 Y6 F15000 ; move X/Y to start position\nG1 Z35 F9000 ; move Z to start position\n\n; Wait for bed and nozzle temperatures\nM190 S{first_layer_bed_temperature[0] - 5} ; wait for bed temperature - 5\nM140 S[first_layer_bed_temperature] ; continue bed heating\nM109 S[first_layer_temperature] ; wait for nozzle temperature\n\n; Purge and prime\nM83 ; set extruder to relative mode\nG92 E0 ; reset extrusion distance\nG0 X0 Y1 F10000\nG1 F150 E20 Y10 ; compress the bowden tube\nG1 E-8 F1200\nG0 X30 Y1 F5000 \nG0 F1200 Z{first_layer_height/2} ; Cut the connection to priming blob\nG0 X100 F10000 ; disconnect with the prime blob\nG0 X50 ; Avoid the metal clip holding the Ultimaker glass plate\nG0 Z0.2 F720\nG1 E8 F1200\nG1 X80 E3 F1000 ; intro line 1\nG1 X110 E4 F1000 ; intro line 2\nG1 X140 F600 ; drag filament to decompress bowden tube\nG1 X100 F3200 ; wipe backwards a bit\nG1 X150 F3200 ; back to where there is no plastic: avoid dragging\nG92 E0 ; reset extruder reference\nM82 ; set extruder to absolute mode\n\n; # # # # # # END Header +start_gcode = ; Printer_Settings_ID: [printer_settings_id]\n\n; # # # # # # START Header\nG21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM107 ; start with the fan off\n\nM140 S[first_layer_bed_temperature] ; start bed heating\n\nG28 X0 Y0 Z0 ; move X/Y/Z to endstops\nG1 X1 Y6 F15000 ; move X/Y to start position\nG1 Z35 F9000 ; move Z to start position\n\n; Wait for bed and nozzle temperatures\nM190 S{first_layer_bed_temperature[0] - 5} ; wait for bed temperature - 5\nM140 S[first_layer_bed_temperature] ; continue bed heating\nM109 S[first_layer_temperature] ; wait for nozzle temperature\n\n; Purge and prime\nM83 ; set extruder to relative mode\nG92 E0 ; reset extrusion distance\nG0 X0 Y1 F10000\nG1 F150 E20 ; compress the bowden tube\nG1 E-8 F1200\nG0 X30 Y1 F5000 \nG0 F1200 Z{first_layer_height/2} ; Cut the connection to priming blob\nG0 X100 F10000 ; disconnect with the prime blob\nG0 X50 ; Avoid the metal clip holding the Ultimaker glass plate\nG0 Z0.2 F720\nG1 E8 F1200\nG1 X80 E3 F1000 ; intro line 1\nG1 X110 E4 F1000 ; intro line 2\nG1 X140 F600 ; drag filament to decompress bowden tube\nG1 X100 F3200 ; wipe backwards a bit\nG1 X150 F3200 ; back to where there is no plastic: avoid dragging\nG92 E0 ; reset extruder reference\nM82 ; set extruder to absolute mode\n\n; # # # # # # END Header end_gcode = ; # # # # # # START Footer\nG91 ; relative coordinates\n;G1 E-1 F1200 ; retract the filament\nG1 Z+15 X-10 Y-10 E-7 F6000 ; move Z a bit\n; G1 X-10 Y-10 F6000 ; move XY a bit\nG1 E-5.5 F300 ; retract the filament\nG28 X0 Y0 ; move X/Y to min endstops, so the head is out of the way\nM104 S0 ; extruder heater off\nM140 S0 ; heated bed heater off (if you have it)\nM84 ; disable motors\n; # # # # # # END Footer\n From a7d466dc7cb4da8cd3c5b6869b560fa8efc54fa8 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 18 Mar 2022 08:32:35 +0100 Subject: [PATCH 11/46] Tech ENABLE_Z_OFFSET_CORRECTION set as default --- src/libslic3r/GCode/GCodeProcessor.cpp | 14 -------------- src/libslic3r/GCode/GCodeProcessor.hpp | 2 -- src/libslic3r/Technologies.hpp | 9 --------- 3 files changed, 25 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 0c9d495446..43a5f1eb0a 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -905,11 +905,9 @@ void GCodeProcessor::apply_config(const PrintConfig& config) if (spiral_vase != nullptr) m_spiral_vase_active = spiral_vase->value; -#if ENABLE_Z_OFFSET_CORRECTION const ConfigOptionFloat* z_offset = config.option("z_offset"); if (z_offset != nullptr) m_z_offset = z_offset->value; -#endif // ENABLE_Z_OFFSET_CORRECTION } void GCodeProcessor::apply_config(const DynamicPrintConfig& config) @@ -1158,11 +1156,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config) if (spiral_vase != nullptr) m_spiral_vase_active = spiral_vase->value; -#if ENABLE_Z_OFFSET_CORRECTION const ConfigOptionFloat* z_offset = config.option("z_offset"); if (z_offset != nullptr) m_z_offset = z_offset->value; -#endif // ENABLE_Z_OFFSET_CORRECTION } void GCodeProcessor::enable_stealth_time_estimator(bool enabled) @@ -1195,9 +1191,7 @@ void GCodeProcessor::reset() m_forced_height = 0.0f; m_mm3_per_mm = 0.0f; m_fan_speed = 0.0f; -#if ENABLE_Z_OFFSET_CORRECTION m_z_offset = 0.0f; -#endif // ENABLE_Z_OFFSET_CORRECTION m_extrusion_role = erNone; m_extruder_id = 0; @@ -2743,11 +2737,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) // the threshold value = 0.0625f == 0.25 * 0.25 is arbitrary, we may find some smarter condition later if ((new_pos - *first_vertex).squaredNorm() < 0.0625f) { -#if ENABLE_Z_OFFSET_CORRECTION set_end_position(0.5f * (new_pos + *first_vertex) + m_z_offset * Vec3f::UnitZ()); -#else - set_end_position(0.5f * (new_pos + *first_vertex)); -#endif // ENABLE_Z_OFFSET_CORRECTION store_move_vertex(EMoveType::Seam); set_end_position(curr_pos); } @@ -3279,11 +3269,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type) m_extrusion_role, m_extruder_id, m_cp_color.current, -#if ENABLE_Z_OFFSET_CORRECTION Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z] - m_z_offset) + m_extruder_offsets[m_extruder_id], -#else - Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id], -#endif // ENABLE_Z_OFFSET_CORRECTION static_cast(m_end_position[E] - m_start_position[E]), m_feedrate, m_width, diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index e04caa6e22..5ca8f0b026 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -540,9 +540,7 @@ namespace Slic3r { float m_forced_height; // mm float m_mm3_per_mm; float m_fan_speed; // percentage -#if ENABLE_Z_OFFSET_CORRECTION float m_z_offset; // mm -#endif // ENABLE_Z_OFFSET_CORRECTION ExtrusionRole m_extrusion_role; unsigned char m_extruder_id; ExtruderColors m_extruder_colors; diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index de54e65091..8e6a3cb86c 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -36,15 +36,6 @@ #define ENABLE_SMOOTH_NORMALS 0 -//================ -// 2.4.1.rc techs -//================ -#define ENABLE_2_4_1_RC 1 - -// Enable correction of toolpaths when z offset is set -#define ENABLE_Z_OFFSET_CORRECTION (1 && ENABLE_2_4_1_RC) - - //==================== // 2.5.0.alpha1 techs //==================== From f3d92bdeff0cb6f5c1685e9910a26418cef1e45e Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 18 Mar 2022 10:25:00 +0100 Subject: [PATCH 12/46] Fixup of 5de93c8 (incorrectly solved merge conflict) --- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index e8c2055f63..4007f0cb0b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -154,7 +154,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) Geometry::Transformation transformation(vol->get_instance_transformation().get_matrix() * vol->get_volume_transformation().get_matrix()); const Transform3d& instance_scaling_matrix_inverse = transformation.get_matrix(true, true, false, true).inverse(); #if ENABLE_GL_SHADERS_ATTRIBUTES - const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * vol->get_instance_transformation().get_matrix(); + const Transform3d instance_matrix = Geometry::assemble_transform(m_c->selection_info()->get_sla_shift() * Vec3d::UnitZ()) * transformation.get_matrix(); const Camera& camera = wxGetApp().plater()->get_camera(); const Transform3d& view_matrix = camera.get_view_matrix(); const Transform3d& projection_matrix = camera.get_projection_matrix(); From b094ea3c9aca7d91a505d3811c430f1861fe052b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 18 Mar 2022 12:52:14 +0100 Subject: [PATCH 13/46] Added github issue template form --- .github/ISSUE_TEMPLATE/bug_report_form.yml | 65 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 9 +++ .github/ISSUE_TEMPLATE/feature_request.md | 20 +++++++ 3 files changed, 94 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report_form.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report_form.yml b/.github/ISSUE_TEMPLATE/bug_report_form.yml new file mode 100644 index 0000000000..7cbaddc49f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_form.yml @@ -0,0 +1,65 @@ +name: Bug Report +description: File a bug report +body: + - type: markdown + attributes: + value: | + Before filing, please check if the issue already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment. + - type: textarea + id: what-happened + attributes: + label: Description of the bug + description: What happened? Please, enclose a screenshot whenever possible (even when you think the description is clear). What did you expect to happen? In case of 3D rendering issues, please attach the content of menu Help -> System Info dialog. + placeholder: | + What is the problem? + What did you expect? + You paste or drop screenshots here + validations: + required: true + - type: textarea + id: to_reproduce + attributes: + label: Project file & How to reproduce + description: "*Please* upload a ZIP archive containing the project file used when the problem arise. Please export it just before the problem occurs. Even if you did nothing and/or there is no object, export it! (it contains your current configuration)." + placeholder: | + `File`->`Export project as...` then zip it & drop it here + Also, if needed include the steps to reproduce the bug: + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + - type: checkboxes + attributes: + label: Checklist of files included above + options: + - label: Project file + - label: Screenshot + validations: + required: true + - type: input + id: version + attributes: + label: Version of PrusaSlicer + description: What version of PrusaSlicer are you running? You can see the full version in `Help` -> `About PrusaSlicer`. + placeholder: e.g. 2.4.1-alpha2-win64 / 2.3.3-linux / 2.4.1-alpha0+61-win64-gcd2459455 ... + validations: + required: true + - type: input + id: os + attributes: + label: Operating system + description: with the version if possible + placeholder: e.g. Windows 7/8/10/11 ... , Ubuntu 22.04/Debian ... , macOS 10.15/11.1 ... + validations: + required: true + - type: input + id: printer + attributes: + label: Printer model + description: Please, fill this in even when it seems irrelevant. + placeholder: voron 2.4 with afterburner + validations: + required: true + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..d373b69eea --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,9 @@ +contact_links: + - name: PrusaSlicer Manual and Support + url: https://help.prusa3d.com/en/article/customer-support_2287/ + about: If you are not sure that what you are reporting is really a bug, please, consult the manual first. + - name: PrusaPrinters Forum + url: https://forum.prusaprinters.org/forum/prusaslicer/ + about: Please get in touch on our PrusaPrinters Community Forum! (Not an official support channel.) + +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..aed1846872 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe how it would work** +Be as descriptive as your skill level allows you. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or paint drawing about the feature request here. From 8c8e908325adb2c7f97bb4eaf5e6c9567530fa09 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 18 Mar 2022 13:34:53 +0100 Subject: [PATCH 14/46] Tech ENABLE_PROCESS_G2_G3_LINES - Processing of gcode G2 and G3 lines --- src/libslic3r/GCode/GCodeProcessor.cpp | 286 +++++++++++++++++++++++-- src/libslic3r/GCode/GCodeProcessor.hpp | 9 + src/libslic3r/Technologies.hpp | 2 + src/slic3r/GUI/GUI_Preview.cpp | 31 +++ 4 files changed, 311 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 3bf7c4ffd3..9e98e4da4c 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -36,6 +36,10 @@ static const float DEFAULT_FILAMENT_DIAMETER = 1.75f; static const float DEFAULT_FILAMENT_DENSITY = 1.245f; static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero(); +#if ENABLE_PROCESS_G2_G3_LINES +static const std::string INTERNAL_G2G3_TAG = "!#!#! from G2/G3 expansion !#!#!"; +#endif // ENABLE_PROCESS_G2_G3_LINES + namespace Slic3r { const std::vector GCodeProcessor::Reserved_Tags = { @@ -1596,6 +1600,10 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool switch (cmd[1]) { case '0': { process_G0(line); break; } // Move case '1': { process_G1(line); break; } // Move +#if ENABLE_PROCESS_G2_G3_LINES + case '2': { process_G2_G3(line, true); break; } // CW Arc Move + case '3': { process_G2_G3(line, false); break; } // CCW Arc Move +#endif // ENABLE_PROCESS_G2_G3_LINES default: break; } break; @@ -2453,9 +2461,10 @@ void GCodeProcessor::process_G0(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) { - float filament_diameter = (static_cast(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back(); - float filament_radius = 0.5f * filament_diameter; - float area_filament_cross_section = static_cast(M_PI) * sqr(filament_radius); + const float filament_diameter = (static_cast(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back(); + const float filament_radius = 0.5f * filament_diameter; + const float area_filament_cross_section = static_cast(M_PI) * sqr(filament_radius); +#if !ENABLE_PROCESS_G2_G3_LINES auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) { bool is_relative = (m_global_positioning_type == EPositioningType::Relative); if (axis == E) @@ -2471,6 +2480,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) else return m_start_position[axis]; }; +#endif // !ENABLE_PROCESS_G2_G3_LINES auto move_type = [this](const AxisCoords& delta_pos) { EMoveType type = EMoveType::Noop; @@ -2498,7 +2508,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) // updates axes positions from line for (unsigned char a = X; a <= E; ++a) { +#if ENABLE_PROCESS_G2_G3_LINES + m_end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section)); +#else m_end_position[a] = absolute_position((Axis)a, line); +#endif // ENABLE_PROCESS_G2_G3_LINES } // updates feedrate from line, if present @@ -2517,11 +2531,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (max_abs_delta == 0.0f) return; - EMoveType type = move_type(delta_pos); + const EMoveType type = move_type(delta_pos); if (type == EMoveType::Extrude) { - float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); - float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; - float area_toolpath_cross_section = volume_extruded_filament / delta_xyz; + const float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); + const float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; + const float area_toolpath_cross_section = volume_extruded_filament / delta_xyz; // save extruded volume to the cache m_used_filaments.increase_caches(volume_extruded_filament); @@ -2532,12 +2546,23 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role); #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING +#if ENABLE_PROCESS_G2_G3_LINES + if (m_forced_height > 0.0f) + m_height = m_forced_height; + else if (m_layer_id == 0) + m_height = (m_end_position[Z] <= double(m_first_layer_height)) ? m_end_position[Z] : m_first_layer_height; + else if (line.comment() != INTERNAL_G2G3_TAG){ + if (m_end_position[Z] > m_extruded_last_z + EPSILON && delta_pos[Z] == 0.0) + m_height = m_end_position[Z] - m_extruded_last_z; + } +#else if (m_forced_height > 0.0f) m_height = m_forced_height; else { if (m_end_position[Z] > m_extruded_last_z + EPSILON) m_height = m_end_position[Z] - m_extruded_last_z; } +#endif // ENABLE_PROCESS_G2_G3_LINES if (m_height == 0.0f) m_height = DEFAULT_TOOLPATH_HEIGHT; @@ -2545,7 +2570,10 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (m_end_position[Z] == 0.0f) m_end_position[Z] = m_height; - m_extruded_last_z = m_end_position[Z]; +#if ENABLE_PROCESS_G2_G3_LINES + if (line.comment() != INTERNAL_G2G3_TAG) +#endif // ENABLE_PROCESS_G2_G3_LINES + m_extruded_last_z = m_end_position[Z]; m_options_z_corrector.update(m_height); #if ENABLE_GCODE_VIEWER_DATA_CHECKING @@ -2585,9 +2613,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) return delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f && delta_pos[Z] == 0.0f && delta_pos[E] != 0.0f; }; - float distance = move_length(delta_pos); + const float distance = move_length(delta_pos); assert(distance != 0.0f); - float inv_distance = 1.0f / distance; + const float inv_distance = 1.0f / distance; for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { TimeMachine& machine = m_time_processor.machines[i]; @@ -2618,7 +2646,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]); if (curr.abs_axis_feedrate[a] != 0.0f) { - float axis_max_feedrate = get_axis_max_feedrate(static_cast(i), static_cast(a)); + const float axis_max_feedrate = get_axis_max_feedrate(static_cast(i), static_cast(a)); if (axis_max_feedrate != 0.0f) min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]); } @@ -2641,7 +2669,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) get_acceleration(static_cast(i))); for (unsigned char a = X; a <= E; ++a) { - float axis_max_acceleration = get_axis_max_acceleration(static_cast(i), static_cast(a)); + const float axis_max_acceleration = get_axis_max_acceleration(static_cast(i), static_cast(a)); if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration) acceleration = axis_max_acceleration; } @@ -2652,7 +2680,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) curr.safe_feedrate = block.feedrate_profile.cruise; for (unsigned char a = X; a <= E; ++a) { - float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a)); + const float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a)); if (curr.abs_axis_feedrate[a] > axis_max_jerk) curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk); } @@ -2686,7 +2714,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) } // Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction. - float jerk = + const float jerk = (v_exit > v_entry) ? ((v_entry > 0.0f || v_exit < 0.0f) ? // coasting @@ -2700,7 +2728,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) // axis reversal std::max(-v_exit, v_entry)); - float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a)); + const float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(a)); if (jerk > axis_max_jerk) { v_factor *= axis_max_jerk / jerk; limited = true; @@ -2712,14 +2740,14 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) // Now the transition velocity is known, which maximizes the shared exit / entry velocity while // respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints. - float vmax_junction_threshold = vmax_junction * 0.99f; + const float vmax_junction_threshold = vmax_junction * 0.99f; // Not coasting. The machine will stop and start the movements anyway, better to start the segment from start. if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold) vmax_junction = curr.safe_feedrate; } - float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance); + const float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance); block.feedrate_profile.entry = std::min(vmax_junction, v_allowable); block.max_entry_speed = vmax_junction; @@ -2781,6 +2809,211 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) store_move_vertex(type); } +#if ENABLE_PROCESS_G2_G3_LINES +void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise) +{ + if (!line.has('X') || !line.has('Y') || !line.has('I') || !line.has('J')) + return; + + // relative center + Vec3f rel_center = Vec3f::Zero(); + if (!line.has_value('I', rel_center.x()) || !line.has_value('J', rel_center.y())) + return; + + // scale center, if needed + if (m_units == EUnits::Inches) + rel_center *= INCHES_TO_MM; + + struct Arc + { + Vec3d start{ Vec3d::Zero() }; + Vec3d end{ Vec3d::Zero() }; + Vec3d center{ Vec3d::Zero() }; + + double angle{ 0.0 }; + double delta_x() const { return end.x() - start.x(); } + double delta_y() const { return end.y() - start.y(); } + double delta_z() const { return end.z() - start.z(); } + + double length() const { return angle * start_radius(); } + double travel_length() const { return std::sqrt(sqr(length() + sqr(delta_z()))); } + double start_radius() const { return (start - center).norm(); } + double end_radius() const { return (end - center).norm(); } + + Vec3d relative_start() const { return start - center; } + Vec3d relative_end() const { return end - center; } + + bool closed() const { return end.isApprox(start); } + }; + + Arc arc; + + // arc start endpoint + arc.start = Vec3d(m_start_position[X], m_start_position[Y], m_start_position[Z]); + + // arc center + arc.center = arc.start + rel_center.cast(); + + const float filament_diameter = (static_cast(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back(); + const float filament_radius = 0.5f * filament_diameter; + const float area_filament_cross_section = static_cast(M_PI) * sqr(filament_radius); + + AxisCoords end_position = m_start_position; + for (unsigned char a = X; a <= E; ++a) { + end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section)); + } + + // arc end endpoint + arc.end = Vec3d(end_position[X], end_position[Y], end_position[Z]); + + // radii + if (std::abs(arc.end_radius() - arc.start_radius()) > EPSILON) { + // what to do ??? + } + + // updates feedrate from line + std::optional feedrate; + if (line.has_f()) + feedrate = m_feed_multiply.current * line.f() * MMMIN_TO_MMSEC; + + // updates extrusion from line + std::optional extrusion; + if (line.has_e()) + extrusion = end_position[E] - m_start_position[E]; + + // relative arc endpoints + const Vec3d rel_arc_start = arc.relative_start(); + const Vec3d rel_arc_end = arc.relative_end(); + + // arc angle + if (arc.closed()) + arc.angle = 2.0 * PI; + else { + arc.angle = std::atan2(rel_arc_start.x() * rel_arc_end.y() - rel_arc_start.y() * rel_arc_end.x(), + rel_arc_start.x() * rel_arc_end.x() + rel_arc_start.y() * rel_arc_end.y()); + if (arc.angle < 0.0) + arc.angle += 2.0 * PI; + if (clockwise) + arc.angle -= 2.0 * PI; + } + + const double travel_length = arc.travel_length(); + if (travel_length < 0.001) + return; + + auto adjust_target = [this, area_filament_cross_section](const AxisCoords& target, const AxisCoords& prev_position) { + AxisCoords ret = target; + if (m_global_positioning_type == EPositioningType::Relative) { + for (unsigned char a = X; a <= E; ++a) { + ret[a] -= prev_position[a]; + } + } + else if (m_e_local_positioning_type == EPositioningType::Relative) + ret[E] -= prev_position[E]; + + if (m_use_volumetric_e) + ret[E] *= area_filament_cross_section; + + const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0; + for (unsigned char a = X; a <= E; ++a) { + ret[a] /= lengthsScaleFactor; + } + return ret; + }; + + auto fake_g1_line = [this](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) { + std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str(); + if (has_z) + ret += (boost::format(" Z%1%") % target[Z]).str(); + if (feedrate.has_value()) + ret += (boost::format(" F%1%") % feedrate.value()).str(); + if (extrusion.has_value()) + ret += (boost::format(" E%1%") % target[E]).str(); + + ret += (boost::format(" ;%1%\n") % INTERNAL_G2G3_TAG).str(); + + return ret; + }; + + // calculate arc segments + // reference: + // Prusa-Firmware\Firmware\motion_control.cpp - mc_arc() + + // segments count + static const double MM_PER_ARC_SEGMENT = 1.0; + const size_t segments = std::max(std::floor(travel_length / MM_PER_ARC_SEGMENT), 1); + + const double theta_per_segment = arc.angle / double(segments); + const double z_per_segment = arc.delta_z() / double(segments); + const double extruder_per_segment = (extrusion.has_value()) ? extrusion.value() / double(segments) : 0.0; + + double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation + double sin_T = theta_per_segment; + + AxisCoords prev_target = m_start_position; + AxisCoords arc_target; + double sin_Ti; + double cos_Ti; + double r_axisi; + size_t count = 0; + + // Initialize the linear axis + arc_target[Z] = m_start_position[Z]; + + // Initialize the extruder axis + arc_target[E] = m_start_position[E]; + + static const size_t N_ARC_CORRECTION = 25; + + Vec3d curr_rel_arc_start = arc.relative_start(); + Vec3d curr_rel_arc_end = arc.relative_end(); + + std::string gcode; + + for (size_t i = 1; i < segments; ++i) { // Increment (segments-1) + if (count < N_ARC_CORRECTION) { + // Apply vector rotation matrix + r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T; + curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T; + curr_rel_arc_start.y() = r_axisi; + count++; + } + else { + // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. + // Compute exact location by applying transformation matrix from initial radius vector(=-offset). + cos_Ti = ::cos(double(i) * theta_per_segment); + sin_Ti = ::sin(double(i) * theta_per_segment); + curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti; + curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti; + count = 0; + } + + // Update arc_target location + arc_target[X] = arc.center.x() + curr_rel_arc_start.x(); + arc_target[Y] = arc.center.y() + curr_rel_arc_start.y(); + arc_target[Z] += z_per_segment; + arc_target[E] += extruder_per_segment; + + gcode += fake_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion); + prev_target = arc_target; + + // feedrate is constant, we do not need to repeat it + feedrate.reset(); + } + + // Ensure last segment arrives at target location. + gcode += fake_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion); + + // process fake gcode lines + GCodeReader parser; + parser.parse_buffer(gcode, [this](GCodeReader&, const GCodeReader::GCodeLine& line) { + // force all lines to share the same id + --m_line_id; + process_gcode_line(line, false); + }); +} +#endif // ENABLE_PROCESS_G2_G3_LINES + void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line) { // stores retract move @@ -3502,5 +3735,24 @@ void GCodeProcessor::update_estimated_times_stats() m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role; } +#if ENABLE_PROCESS_G2_G3_LINES +double GCodeProcessor::extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section) +{ + if (line.has(Slic3r::Axis(axis))) { + bool is_relative = (m_global_positioning_type == EPositioningType::Relative); + if (axis == E) + is_relative |= (m_e_local_positioning_type == EPositioningType::Relative); + + const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0; + double ret = line.value(Slic3r::Axis(axis)) * lengthsScaleFactor; + if (axis == E && m_use_volumetric_e) + ret /= area_filament_cross_section; + return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret; + } + else + return m_start_position[axis]; +} +#endif // ENABLE_PROCESS_G2_G3_LINES + } /* namespace Slic3r */ diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 25375f61b6..59a91dc244 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -652,6 +652,11 @@ namespace Slic3r { void process_G0(const GCodeReader::GCodeLine& line); void process_G1(const GCodeReader::GCodeLine& line); +#if ENABLE_PROCESS_G2_G3_LINES + // Arc Move + void process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise); +#endif // ENABLE_PROCESS_G2_G3_LINES + // Retract void process_G10(const GCodeReader::GCodeLine& line); @@ -777,6 +782,10 @@ namespace Slic3r { void simulate_st_synchronize(float additional_time = 0.0f); void update_estimated_times_stats(); + +#if ENABLE_PROCESS_G2_G3_LINES + double extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section); +#endif // ENABLE_PROCESS_G2_G3_LINES }; } /* namespace Slic3r */ diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 635fc49943..f7df9e6963 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -84,6 +84,8 @@ #define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1) // Enable modified rectangle selection #define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1) +// Enable processing of gcode G2 and G3 lines +#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 2cac5e3566..8c1bb7707e 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -859,6 +859,36 @@ void Preview::update_moves_slider() if (view.endpoints.last < view.endpoints.first) return; +#if ENABLE_PROCESS_G2_G3_LINES + assert(view.endpoints.first <= view.current.first && view.current.first <= view.endpoints.last); + assert(view.endpoints.first <= view.current.last && view.current.last <= view.endpoints.last); + + std::vector values; + values.reserve(view.endpoints.last - view.endpoints.first + 1); + std::vector alternate_values; + alternate_values.reserve(view.endpoints.last - view.endpoints.first + 1); + unsigned int last_gcode_id = view.gcode_ids[view.endpoints.first]; + for (unsigned int i = view.endpoints.first; i <= view.endpoints.last; ++i) { + if (i > view.endpoints.first) { + // skip consecutive moves with same gcode id (resulting from processing G2 and G3 lines) + if (last_gcode_id == view.gcode_ids[i]) { + values.back() = static_cast(i + 1); + alternate_values.back() = static_cast(view.gcode_ids[i]); + continue; + } + else + last_gcode_id = view.gcode_ids[i]; + } + + values.emplace_back(static_cast(i + 1)); + alternate_values.emplace_back(static_cast(view.gcode_ids[i])); + } + + m_moves_slider->SetSliderValues(values); + m_moves_slider->SetSliderAlternateValues(alternate_values); + m_moves_slider->SetMaxValue(int(values.size()) - 1); + m_moves_slider->SetSelectionSpan(values.front() - 1, values.back() - 1); +#else std::vector values(view.endpoints.last - view.endpoints.first + 1); std::vector alternate_values(view.endpoints.last - view.endpoints.first + 1); unsigned int count = 0; @@ -873,6 +903,7 @@ void Preview::update_moves_slider() m_moves_slider->SetSliderAlternateValues(alternate_values); m_moves_slider->SetMaxValue(view.endpoints.last - view.endpoints.first); m_moves_slider->SetSelectionSpan(view.current.first - view.endpoints.first, view.current.last - view.endpoints.first); +#endif // ENABLE_PROCESS_G2_G3_LINES } void Preview::enable_moves_slider(bool enable) From 8ce9241c48605d192f36f3fa22d4b1e98e1ce662 Mon Sep 17 00:00:00 2001 From: Jebtrix Date: Sat, 29 Jan 2022 11:44:25 -0500 Subject: [PATCH 15/46] Set CMAKE_GENERATOR environment variable to ensure MSVC version used --- build_win.bat | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build_win.bat b/build_win.bat index de5030ee50..3dbdb0ad6e 100644 --- a/build_win.bat +++ b/build_win.bat @@ -164,6 +164,9 @@ IF NOT EXIST "%MSVC_DIR%" ( @ECHO ERROR: Compatible Visual Studio installation not found. 1>&2 GOTO :HELP ) +REM Cmake always defaults to latest supported MSVC generator. Let's make sure it uses what we select. +FOR /F "tokens=* USEBACKQ" %%I IN (`^""%VSWHERE%" %MSVC_FILTER% -nologo -property catalog_productLineVersion^"`) DO SET PS_PRODUCT_VERSION=%%I + REM Give the user a chance to cancel if we found something odd. IF "%PS_ASK_TO_CONTINUE%" EQU "" GOTO :BUILD_ENV @ECHO. @@ -183,6 +186,7 @@ SET PS_CURRENT_STEP=environment @ECHO ** Deps path: %PS_DESTDIR% @ECHO ** Using Microsoft Visual Studio installation found at: @ECHO ** %MSVC_DIR% +SET CMAKE_GENERATOR=Visual Studio %PS_VERSION% %PS_PRODUCT_VERSION% CALL "%MSVC_DIR%\Common7\Tools\vsdevcmd.bat" -arch=%PS_ARCH% -host_arch=%PS_ARCH_HOST% -app_platform=Desktop IF %ERRORLEVEL% NEQ 0 GOTO :END REM Need to reset the echo state after vsdevcmd.bat clobbers it. From 82fe599cae8c7501862b2daf0735aa262a7f6090 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 18 Mar 2022 14:12:29 +0100 Subject: [PATCH 16/46] Fixed warnings and build on MAC OS --- src/libslic3r/GCode/GCodeProcessor.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index aaab86bd62..340515d5ff 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2897,12 +2897,12 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc return ret; }; - auto fake_g1_line = [this](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) { + auto fake_g1_line = [](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) { std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str(); if (has_z) ret += (boost::format(" Z%1%") % target[Z]).str(); if (feedrate.has_value()) - ret += (boost::format(" F%1%") % feedrate.value()).str(); + ret += (boost::format(" F%1%") % *feedrate).str(); if (extrusion.has_value()) ret += (boost::format(" E%1%") % target[E]).str(); @@ -2921,7 +2921,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc const double theta_per_segment = arc.angle / double(segments); const double z_per_segment = arc.delta_z() / double(segments); - const double extruder_per_segment = (extrusion.has_value()) ? extrusion.value() / double(segments) : 0.0; + const double extruder_per_segment = (extrusion.has_value()) ? *extrusion / double(segments) : 0.0; double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation double sin_T = theta_per_segment; @@ -2942,7 +2942,6 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc static const size_t N_ARC_CORRECTION = 25; Vec3d curr_rel_arc_start = arc.relative_start(); - Vec3d curr_rel_arc_end = arc.relative_end(); std::string gcode; From 8a340a0cf72e6e6367da48be64a52b5ce836909f Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Fri, 18 Mar 2022 15:39:30 +0100 Subject: [PATCH 17/46] Sync with PrusaSlicer-settings --- resources/profiles/Anycubic.idx | 1 + resources/profiles/Anycubic.ini | 101 +------------------------------- 2 files changed, 4 insertions(+), 98 deletions(-) diff --git a/resources/profiles/Anycubic.idx b/resources/profiles/Anycubic.idx index 47bdd8c271..232d534256 100644 --- a/resources/profiles/Anycubic.idx +++ b/resources/profiles/Anycubic.idx @@ -1,4 +1,5 @@ min_slic3r_version = 2.4.1-rc1 +0.1.1 Fixed before layer change g-code for Mega Zero. 0.1.0 Added Anycubic 4Max Pro 2.0 min_slic3r_version = 2.3.2-alpha0 0.0.12 Updated Anycubic i3 MEGA(S) profiles. diff --git a/resources/profiles/Anycubic.ini b/resources/profiles/Anycubic.ini index fd73c063e8..5640560411 100644 --- a/resources/profiles/Anycubic.ini +++ b/resources/profiles/Anycubic.ini @@ -5,7 +5,7 @@ name = Anycubic # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 0.1.0 +config_version = 0.1.1 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/ # changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% @@ -73,13 +73,6 @@ technology = FFF family = PREDATOR default_materials = Generic PLA @PREDATOR; Generic PETG @PREDATOR; Generic ABS @PREDATOR -[printer_model:PHOTON MONO X] -name = Photon Mono X -variants = default -technology = SLA -family = PHOTON MONO -default_materials = Generic Blue Resin @MONO 0.05 - # All presets starting with asterisk, for example *common*, are intermediate and they will # not make it into the user interface. @@ -742,7 +735,7 @@ filament_density = 1.27 [printer:*common_mega0*] printer_technology = FFF bed_shape = 0x0,220x0,220x220,0x220 -before_layer_gcode = ; BEFORE_LAYER_CHANGE [layer_num] @ [layer_z]mm +before_layer_gcode = ; BEFORE_LAYER_CHANGE [layer_num] @ [layer_z]mm\nG92 E0 between_objects_gcode = deretract_speed = 0 extruder_colour = #FFFF00 @@ -2238,92 +2231,4 @@ use_relative_e_distances = 0 use_volumetric_e = 0 variable_layer_height = 1 wipe = 0 -z_offset = 0 - -########## SLA printer presets ########## - -[sla_print:*common print ANYCUBIC SLA*] -compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/ -layer_height = 0.05 -output_filename_format = [input_filename_base].pwmx -pad_edge_radius = 0.5 -pad_enable = 0 -pad_max_merge_distance = 50 -pad_wall_height = 0 -pad_wall_thickness = 1 -pad_wall_slope = 45 -faded_layers = 8 -slice_closing_radius = 0.005 -support_base_diameter = 3 -support_base_height = 1 -support_critical_angle = 45 -support_density_at_45 = 250 -support_density_at_horizontal = 500 -support_head_front_diameter = 0.4 -support_head_penetration = 0.4 -support_head_width = 3 -support_max_bridge_length = 10 -support_minimal_z = 0 -support_object_elevation = 5 -support_pillar_diameter = 1 -support_pillar_connection_mode = zigzag -support_pillar_widening_factor = 0 -supports_enable = 1 -support_small_pillar_diameter_percent = 60% - -[sla_print:0.05 Normal @ANYCUBIC] -inherits = *common print ANYCUBIC SLA* -layer_height = 0.05 - -########### Materials - -[sla_material:*common ANYCUBIC SLA*] -compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/ -compatible_prints_condition = layer_height == 0.05 -exposure_time = 7 -initial_exposure_time = 40 -initial_layer_height = 0.05 -material_correction = 1,1,1 -material_notes = LIFT_DISTANCE=8.0\nLIFT_SPEED=2.5\nRETRACT_SPEED=3.0\nBOTTOM_LIFT_SPEED=2.0\nBOTTOM_LIFT_DISTANCE=9.0\nDELAY_BEFORE_EXPOSURE=0.5 - -[sla_material:*common 0.05 ANYCUBIC SLA*] -inherits = *common ANYCUBIC SLA* - -[sla_material:Generic Blue Resin @MONO 0.05] -inherits = *common 0.05 ANYCUBIC SLA* -exposure_time = 2.5 -initial_exposure_time = 40 -material_type = Tough -material_vendor = Generic -material_colour = #6080EC -compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/ - -########## Printers - -[printer:Anycubic Photon Mono X] -printer_technology = SLA -printer_model = PHOTON MONO X -printer_variant = default -default_sla_material_profile = Generic Blue Resin @MONO 0.05 -default_sla_print_profile = 0.05 Normal @ANYCUBIC -thumbnails = 224x168 -sla_archive_format = pwmx -bed_shape = 1.48x1.02,193.48x1.02,193.48x121.02,1.48x121.02 -display_height = 120 -display_orientation = landscape -display_mirror_x = 1 -display_mirror_y = 0 -display_pixels_x = 3840 -display_pixels_y = 2400 -display_width = 192 -max_print_height = 245 -elefant_foot_compensation = 0.2 -elefant_foot_min_width = 0.2 -min_exposure_time = 1 -max_exposure_time = 120 -min_initial_exposure_time = 1 -max_initial_exposure_time = 300 -printer_correction = 1,1,1 -gamma_correction = 1 -area_fill = 45 -printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.'\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PHOTONMONOX\n +z_offset = 0 \ No newline at end of file From b263ab9a8ea19fb8c965cb4568fdf775212c463d Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Fri, 18 Mar 2022 15:42:15 +0100 Subject: [PATCH 18/46] Readded Photon MONO X --- resources/profiles/Anycubic.ini | 4563 ++++++++++++++++--------------- 1 file changed, 2329 insertions(+), 2234 deletions(-) diff --git a/resources/profiles/Anycubic.ini b/resources/profiles/Anycubic.ini index 5640560411..e8fd89bf4a 100644 --- a/resources/profiles/Anycubic.ini +++ b/resources/profiles/Anycubic.ini @@ -1,2234 +1,2329 @@ -# Print profiles for the Anycubic printers. - -[vendor] -# Vendor name will be shown by the Config Wizard. -name = Anycubic -# Configuration version of this file. Config file will only be installed, if the config_version differs. -# This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 0.1.1 -# Where to get the updates from? -config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/ -# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% - -# The printer models will be shown by the Configuration Wizard in this order, -# also the first model installed & the first nozzle installed will be activated after install. -# Printer model name will be shown by the installation wizard. - -[printer_model:AKLP] -name = Anycubic Kossel Linear Plus -variants = 0.4 -technology = FFF -family = KOSSEL -bed_model = AKLP_Bed.stl -bed_texture = AK.svg -default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL - -[printer_model:AK] -name = Anycubic Kossel Pulley (Linear) -variants = 0.4 -technology = FFF -family = KOSSEL -bed_model = AK_Bed.stl -bed_texture = AK.svg -default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL - -[printer_model:MEGA0] -name = Anycubic Mega Zero -variants = 0.4 -technology = FFF -family = MEGA -bed_model = mega0_bed.stl -bed_texture = mega0.svg -default_materials = Generic PLA @MEGA0; Generic PETG @MEGA0; Anycubic PLA @MEGA0; Prusament PLA @MEGA0; Prusament PETG @MEGA0 - -[printer_model:I3MEGA] -name = Anycubic i3 Mega -variants = 0.4 -technology = FFF -family = MEGA -bed_model = i3megas_bed.stl -bed_texture = i3megas.svg - -[printer_model:I3MEGAS] -name = Anycubic i3 Mega S -variants = 0.4 -technology = FFF -family = MEGA -bed_model = i3megas_bed.stl -bed_texture = i3megas.svg - -[printer_model:4MAXPRO20] -name = Anycubic 4Max Pro 2.0 -variants = 0.4 -technology = FFF -family = 4Max -bed_model = 4MAXPRO20_bed.stl -bed_texture = 4MAXPRO20_texture.svg -default_materials = Generic PLA @4Max Pro 2.0; Generic TPU @4Max Pro 2.0; Generic ABS @4Max Pro 2.0 - -[printer_model:PREDATOR] -name = Anycubic Predator -variants = 0.4; 0.6; 0.8 -technology = FFF -family = PREDATOR -default_materials = Generic PLA @PREDATOR; Generic PETG @PREDATOR; Generic ABS @PREDATOR - -# All presets starting with asterisk, for example *common*, are intermediate and they will -# not make it into the user interface. - -## Anycubic KOSSEL -## Author: https://github.com/tc0fh -## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4220 - -# Common print preset -[print:*common_akossel*] -avoid_crossing_perimeters = 0 -bottom_solid_min_thickness = 0.5 -bridge_angle = 0 -bridge_flow_ratio = 0.8 -bridge_speed = 30 -brim_width = 0 -clip_multipart_objects = 1 -compatible_printers = -complete_objects = 0 -dont_support_bridges = 1 -elefant_foot_compensation = 0 -ensure_vertical_shell_thickness = 1 -external_fill_pattern = rectilinear -external_perimeters_first = 0 -external_perimeter_extrusion_width = 0.45 -extra_perimeters = 0 -extruder_clearance_height = 25 -extruder_clearance_radius = 45 -extrusion_width = 0.45 -fill_angle = 45 -fill_density = 20% -fill_pattern = grid -first_layer_extrusion_width = 0.42 -first_layer_height = 0.2 -first_layer_speed = 20 -gap_fill_speed = 40 -gcode_comments = 0 -infill_every_layers = 1 -infill_extruder = 1 -infill_extrusion_width = 0.45 -infill_first = 0 -infill_only_where_needed = 0 -infill_overlap = 25% -interface_shells = 0 -max_print_speed = 200 -max_volumetric_extrusion_rate_slope_negative = 0 -max_volumetric_extrusion_rate_slope_positive = 0 -max_volumetric_speed = 0 -min_skirt_length = 4 -notes = -overhangs = 0 -only_retract_when_crossing_perimeters = 0 -ooze_prevention = 0 -output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode -perimeters = 2 -perimeter_extruder = 1 -perimeter_extrusion_width = 0.45 -perimeter_speed = 45 -post_process = -print_settings_id = -raft_layers = 0 -resolution = 0 -seam_position = nearest -single_extruder_multi_material_priming = 0 -skirts = 2 -skirt_distance = 5 -skirt_height = 1 -small_perimeter_speed = 25 -solid_infill_below_area = 0 -solid_infill_every_layers = 0 -solid_infill_extruder = 1 -solid_infill_extrusion_width = 0.45 -spiral_vase = 0 -standby_temperature_delta = -5 -support_material = 0 -support_material_extruder = 0 -support_material_extrusion_width = 0.38 -support_material_interface_extruder = 0 -support_material_angle = 0 -support_material_buildplate_only = 0 -support_material_enforce_layers = 0 -support_material_contact_distance = 0.15 -support_material_interface_contact_loops = 0 -support_material_interface_layers = 2 -support_material_interface_spacing = 0.2 -support_material_interface_speed = 100% -support_material_pattern = rectilinear -support_material_spacing = 2 -support_material_speed = 50 -support_material_synchronize_layers = 0 -support_material_threshold = 45 -support_material_with_sheath = 0 -support_material_xy_spacing = 60% -thin_walls = 0 -top_infill_extrusion_width = 0.4 -top_solid_infill_speed = 40 -top_solid_min_thickness = 0.6 -travel_speed = 180 -wipe_tower = 1 -wipe_tower_bridging = 10 -wipe_tower_rotation_angle = 0 -wipe_tower_width = 60 -wipe_tower_x = 170 -wipe_tower_y = 140 -xy_size_compensation = 0 -bridge_acceleration = 1000 -default_acceleration = 1500 -first_layer_acceleration = 1000 -infill_acceleration = 1500 -perimeter_acceleration = 800 - -[print:*0.08mm_akossel*] -inherits = *common_akossel* -bottom_solid_layers = 10 -bridge_acceleration = 300 -bridge_flow_ratio = 0.7 -bridge_speed = 20 -external_perimeter_speed = 20 -first_layer_acceleration = 500 -gap_fill_speed = 20 -infill_acceleration = 800 -infill_speed = 40 -layer_height = 0.08 -max_print_speed = 80 -perimeter_acceleration = 300 -perimeter_speed = 30 -perimeters = 3 -small_perimeter_speed = 20 -solid_infill_speed = 40 -support_material_extrusion_width = 0.3 -support_material_spacing = 1.5 -support_material_speed = 40 -top_solid_infill_speed = 30 -top_solid_layers = 12 - -[print:*0.16mm_akossel*] -inherits = *common_akossel* -bottom_solid_layers = 5 -layer_height = 0.16 -top_solid_layers = 6 - -[print:*0.20mm_akossel*] -inherits = *common_akossel* -bottom_solid_layers = 4 -bridge_flow_ratio = 0.95 -layer_height = 0.20 -top_solid_layers = 5 - -[print:*0.24mm_akossel*] -inherits = *common_akossel* -bottom_solid_layers = 4 -bridge_flow_ratio = 0.95 -layer_height = 0.24 -perimeter_speed = 50 -external_perimeter_speed = 35 -top_solid_layers = 4 -infill_speed = 100 -solid_infill_speed = 100 -top_solid_infill_speed = 40 - -[print:*0.30mm_akossel*] -inherits = *common_akossel* -bottom_solid_layers = 3 -bridge_flow_ratio = 0.95 -external_perimeter_extrusion_width = 0.6 -external_perimeter_speed = 35 -extrusion_width = 0.5 -infill_extrusion_width = 0.5 -infill_speed = 70 -layer_height = 0.30 -perimeter_extrusion_width = 0.5 -perimeter_speed = 50 -small_perimeter_speed = 30 -solid_infill_extrusion_width = 0.5 -solid_infill_speed = 70 -support_material_speed = 45 -top_infill_extrusion_width = 0.45 -top_solid_infill_speed = 50 -top_solid_layers = 3 - -[print:0.08mm ULTRADETAIL @AKOSSEL] -inherits = *0.08mm_akossel* -fill_density = 15% -fill_pattern = gyroid -compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 - -[print:0.16mm QUALITY @AKOSSEL] -inherits = *0.16mm_akossel* -external_perimeter_speed = 25 -fill_density = 15% -fill_pattern = gyroid -infill_speed = 80 -compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 - -[print:0.16mm SPEED @AKOSSEL] -inherits = *0.16mm_akossel* -external_perimeter_speed = 35 -infill_speed = 120 -perimeter_speed = 60 -solid_infill_speed = 120 -top_solid_infill_speed = 50 -compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 - -[print:0.20mm QUALITY @AKOSSEL] -inherits = *0.20mm_akossel* -external_perimeter_speed = 25 -fill_density = 15% -fill_pattern = gyroid -infill_speed = 80 -compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 - -[print:0.20mm SPEED @AKOSSEL] -inherits = *0.20mm_akossel* -external_perimeter_speed = 35 -infill_speed = 120 -perimeter_speed = 60 -solid_infill_speed = 120 -top_solid_infill_speed = 50 -compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 - -[print:0.24mm DRAFT @AKOSSEL] -inherits = *0.24mm_akossel* -compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 - -[print:0.30mm FAST @AKOSSEL] -inherits = *0.30mm_akossel* -compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 - -# Common filament preset -[filament:*common_akossel*] -cooling = 0 -compatible_printers = -extrusion_multiplier = 1 -filament_cost = 0 -filament_density = 0 -filament_diameter = 1.75 -filament_notes = "" -filament_settings_id = "" -filament_soluble = 0 -min_print_speed = 15 -slowdown_below_layer_time = 20 -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_Anycubic.*/ and printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ - -[filament:*PLA_akossel*] -inherits = *common_akossel* -bed_temperature = 60 -fan_below_layer_time = 100 -filament_colour = #FF3232 -filament_max_volumetric_speed = 10 -filament_type = PLA -filament_density = 1.24 -filament_cost = 20 -first_layer_bed_temperature = 60 -first_layer_temperature = 200 -fan_always_on = 1 -cooling = 1 -max_fan_speed = 100 -min_fan_speed = 100 -bridge_fan_speed = 100 -disable_fan_first_layers = 1 -temperature = 200 - -[filament:*PET_akossel*] -inherits = *common_akossel* -bed_temperature = 70 -cooling = 1 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #FF8000 -filament_max_volumetric_speed = 8 -filament_type = PETG -filament_density = 1.27 -filament_cost = 30 -first_layer_bed_temperature =70 -first_layer_temperature = 240 -fan_always_on = 1 -max_fan_speed = 50 -min_fan_speed = 20 -bridge_fan_speed = 100 -temperature = 240 - -[filament:*ABS_akossel*] -inherits = *common_akossel* -bed_temperature = 100 -cooling = 0 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #3A80CA -filament_max_volumetric_speed = 10 -filament_type = ABS -filament_density = 1.04 -filament_cost = 20 -first_layer_bed_temperature = 100 -first_layer_temperature = 245 -fan_always_on = 0 -max_fan_speed = 0 -min_fan_speed = 0 -bridge_fan_speed = 30 -top_fan_speed = 0 -temperature = 245 - -[filament:Generic PLA @AKOSSEL] -inherits = *PLA_akossel* -filament_vendor = Generic - -[filament:Generic PETG @AKOSSEL] -inherits = *PET_akossel* -filament_vendor = Generic - -[filament:Generic ABS @AKOSSEL] -inherits = *ABS_akossel* -filament_vendor = Generic - -# Common printer preset -[printer:*common_akossel*] -printer_technology = FFF -bed_shape = -before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z] -between_objects_gcode = -deretract_speed = 40 -extruder_colour = #FFFF00 -extruder_offset = 0x0 -gcode_flavor = marlin -silent_mode = 0 -remaining_times = 0 -machine_max_acceleration_e = 3000 -machine_max_acceleration_extruding = 1000 -machine_max_acceleration_retracting = 1000 -machine_max_acceleration_x = 1500 -machine_max_acceleration_y = 1500 -machine_max_acceleration_z = 1500 -machine_max_feedrate_e = 60 -machine_max_feedrate_x = 200 -machine_max_feedrate_y = 200 -machine_max_feedrate_z = 200 -machine_max_jerk_e = 5 -machine_max_jerk_x = 5 -machine_max_jerk_y = 5 -machine_max_jerk_z = 5 -machine_min_extruding_rate = 0 -machine_min_travel_rate = 0 -layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] -max_layer_height = 0.3 -min_layer_height = 0.08 -max_print_height = 300 -nozzle_diameter = 0.4 -printer_notes = -printer_settings_id = -retract_before_travel = 2 -retract_before_wipe = 70% -retract_layer_change = 1 -retract_length = 5 -retract_length_toolchange = 1 -retract_lift = 0 -retract_lift_above = 0 -retract_lift_below = 0 -retract_restart_extra = 0 -retract_restart_extra_toolchange = 0 -retract_speed = 60 -single_extruder_multi_material = 0 -start_gcode = -end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG28 ; home\nM84 ; disable motors -toolchange_gcode = -use_firmware_retraction = 0 -use_relative_e_distances = 1 -use_volumetric_e = 0 -variable_layer_height = 1 -wipe = 1 -z_offset = 0 -default_print_profile = 0.20mm QUALITY @AKOSSEL -default_filament_profile = Generic PLA @AKOSSEL - -[printer:Anycubic Kossel Linear Plus] -inherits = *common_akossel* -printer_model = AKLP -printer_variant = 0.4 -printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AKLP\nPRINTER_HAS_BOWDEN\n -bed_shape = 114.562x10.0229,113.253x19.9695,111.081x29.7642,108.065x39.3323,104.225x48.6011,99.5929x57.5,94.2025x65.9613,88.0951x73.9206,81.3173x81.3173,73.9206x88.0951,65.9613x94.2025,57.5x99.5929,48.6011x104.225,39.3323x108.065,29.7642x111.081,19.9695x113.253,10.0229x114.562,7.04172e-15x115,-10.0229x114.562,-19.9695x113.253,-29.7642x111.081,-39.3323x108.065,-48.6011x104.225,-57.5x99.5929,-65.9613x94.2025,-73.9206x88.0951,-81.3173x81.3173,-88.0951x73.9206,-94.2025x65.9613,-99.5929x57.5,-104.225x48.6011,-108.065x39.3323,-111.081x29.7642,-113.253x19.9695,-114.562x10.0229,-115x1.40834e-14,-114.562x-10.0229,-113.253x-19.9695,-111.081x-29.7642,-108.065x-39.3323,-104.225x-48.6011,-99.5929x-57.5,-94.2025x-65.9613,-88.0951x-73.9206,-81.3173x-81.3173,-73.9206x-88.0951,-65.9613x-94.2025,-57.5x-99.5929,-48.6011x-104.225,-39.3323x-108.065,-29.7642x-111.081,-19.9695x-113.253,-10.0229x-114.562,-2.11252e-14x-115,10.0229x-114.562,19.9695x-113.253,29.7642x-111.081,39.3323x-108.065,48.6011x-104.225,57.5x-99.5929,65.9613x-94.2025,73.9206x-88.0951,81.3173x-81.3173,88.0951x-73.9206,94.2025x-65.9613,99.5929x-57.5,104.225x-48.6011,108.065x-39.3323,111.081x-29.7642,113.253x-19.9695,114.562x-10.0229,115x-2.81669e-14 -start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-54.672 Y95.203 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-52.931 Y96.185 E0.300\nG1 X-50.985 Y97.231 E0.331\nG1 X-49.018 Y98.238 E0.331\nG1 X-47.032 Y99.205 E0.331\nG1 X-45.026 Y100.132 E0.331\nG1 X-43.003 Y101.019 E0.331\nG1 X-40.961 Y101.864 E0.331\nG1 X-38.904 Y102.668 E0.331\nG1 X-36.83 Y103.431 E0.331\nG1 X-34.742 Y104.152 E0.331\nG1 X-32.639 Y104.83 E0.331\nG1 X-30.523 Y105.466 E0.331\nG1 X-28.395 Y106.06 E0.331\nG1 X-26.255 Y106.61 E0.331\nG1 X-24.105 Y107.117 E0.331\nG1 X-21.945 Y107.581 E0.331\nG1 X-19.776 Y108.001 E0.331\nG1 X-17.599 Y108.377 E0.331\nG1 X-15.415 Y108.71 E0.331\nG1 X-13.224 Y108.998 E0.331\nG1 X-11.028 Y109.242 E0.331\nG1 X-8.828 Y109.442 E0.331\nG1 X-6.624 Y109.598 E0.331\nG1 X-4.418 Y109.709 E0.331\nG1 X-2.209 Y109.776 E0.332\nG1 X0 Y109.798 E0.331\nG1 X2.209 Y109.776 E0.690\nG1 X4.418 Y109.709 E0.691\nG1 X6.624 Y109.598 E0.690\nG1 X8.828 Y109.442 E0.690\nG1 X11.028 Y109.242 E0.690\nG1 X13.224 Y108.998 E0.690\nG1 X15.415 Y108.71 E0.691\nG1 X17.599 Y108.377 E0.690\nG1 X19.776 Y108.001 E0.690\nG1 X21.945 Y107.581 E0.690\nG1 X24.105 Y107.117 E0.690\nG1 X26.255 Y106.61 E0.690\nG1 X28.395 Y106.06 E0.690\nG1 X30.523 Y105.466 E0.690\nG1 X32.639 Y104.83 E0.690\nG1 X34.742 Y104.152 E0.690\nG1 X36.83 Y103.431 E0.690\nG1 X38.904 Y102.668 E0.691\nG1 X40.961 Y101.864 E0.690\nG1 X43.003 Y101.019 E0.691\nG1 X45.026 Y100.132 E0.690\nG1 X47.032 Y99.205 E0.691\nG1 X49.018 Y98.238 E0.690\nG1 X50.985 Y97.231 E0.691\nG1 X52.931 Y96.185 E0.690\nG1 X54.672 Y95.203 E0.625\nG92 E0.0\nG1 E-5 F3000 ; retract 5mm\nG1 X52.931 Y96.185 F1000 ; wipe\nG1 X50.985 Y97.231 F1000 ; wipe\nG1 X49.018 Y98.238 F1000 ; wipe\nG1 X0 Y109.798 F1000\nG1 E4.8 F1500; de-retract\nG92 E0.0 ; reset extrusion distance\nM221 S{if layer_height<0.075}100{else}95{endif} - -[printer:Anycubic Kossel Pulley (Linear)] -inherits = *common_akossel* -printer_model = AK -printer_variant = 0.4 -printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AK\nPRINTER_HAS_BOWDEN\n -bed_shape = 89.6575x7.84402,88.6327x15.6283,86.9333x23.2937,84.5723x30.7818,81.5677x38.0356,77.9423x45,73.7237x51.6219,68.944x57.8509,63.6396x63.6396,57.8509x68.944,51.6219x73.7237,45x77.9423,38.0356x81.5677,30.7818x84.5723,23.2937x86.9333,15.6283x88.6327,7.84402x89.6575,5.51091e-15x90,-7.84402x89.6575,-15.6283x88.6327,-23.2937x86.9333,-30.7818x84.5723,-38.0356x81.5677,-45x77.9423,-51.6219x73.7237,-57.8509x68.944,-63.6396x63.6396,-68.944x57.8509,-73.7237x51.6219,-77.9423x45,-81.5677x38.0356,-84.5723x30.7818,-86.9333x23.2937,-88.6327x15.6283,-89.6575x7.84402,-90x1.10218e-14,-89.6575x-7.84402,-88.6327x-15.6283,-86.9333x-23.2937,-84.5723x-30.7818,-81.5677x-38.0356,-77.9423x-45,-73.7237x-51.6219,-68.944x-57.8509,-63.6396x-63.6396,-57.8509x-68.944,-51.6219x-73.7237,-45x-77.9423,-38.0356x-81.5677,-30.7818x-84.5723,-23.2937x-86.9333,-15.6283x-88.6327,-7.84402x-89.6575,-1.65327e-14x-90,7.84402x-89.6575,15.6283x-88.6327,23.2937x-86.9333,30.7818x-84.5723,38.0356x-81.5677,45x-77.9423,51.6219x-73.7237,57.8509x-68.944,63.6396x-63.6396,68.944x-57.8509,73.7237x-51.6219,77.9423x-45,81.5677x-38.0356,84.5723x-30.7818,86.9333x-23.2937,88.6327x-15.6283,89.6575x-7.84402,90x-2.20436e-14 -start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-39.672 Y69.712 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-38.457 Y70.397 E0.209\nG1 X-37.043 Y71.157 E0.241\nG1 X-35.614 Y71.889 E0.241\nG1 X-34.171 Y72.591 E0.241\nG1 X-32.714 Y73.265 E0.241\nG1 X-31.244 Y73.909 E0.241\nG1 X-29.761 Y74.523 E0.241\nG1 X-28.266 Y75.108 E0.241\nG1 X-26.759 Y75.662 E0.241\nG1 X-25.242 Y76.185 E0.241\nG1 X-23.714 Y76.678 E0.241\nG1 X-22.177 Y77.14 E0.241\nG1 X-20.63 Y77.571 E0.241\nG1 X-19.076 Y77.971 E0.241\nG1 X-17.514 Y78.34 E0.241\nG1 X-15.944 Y78.677 E0.241\nG1 X-14.368 Y78.982 E0.241\nG1 X-12.786 Y79.255 E0.241\nG1 X-11.199 Y79.497 E0.241\nG1 X-9.608 Y79.706 E0.241\nG1 X-8.013 Y79.884 E0.241\nG1 X-6.414 Y80.029 E0.241\nG1 X-4.813 Y80.142 E0.241\nG1 X-3.21 Y80.223 E0.241\nG1 X-1.605 Y80.271 E0.241\nG1 X0 Y80.287 E0.241\nG1 X1.605 Y80.271 E0.502\nG1 X3.21 Y80.223 E0.502\nG1 X4.813 Y80.142 E0.502\nG1 X6.414 Y80.029 E0.502\nG1 X8.013 Y79.884 E0.502\nG1 X9.608 Y79.706 E0.502\nG1 X11.199 Y79.497 E0.501\nG1 X12.786 Y79.255 E0.502\nG1 X14.368 Y78.982 E0.502\nG1 X15.944 Y78.677 E0.502\nG1 X17.514 Y78.34 E0.502\nG1 X19.076 Y77.971 E0.502\nG1 X20.63 Y77.571 E0.501\nG1 X22.177 Y77.14 E0.502\nG1 X23.714 Y76.678 E0.502\nG1 X25.242 Y76.185 E0.502\nG1 X26.759 Y75.662 E0.501\nG1 X28.266 Y75.108 E0.502\nG1 X29.761 Y74.523 E0.502\nG1 X31.244 Y73.909 E0.502\nG1 X32.714 Y73.265 E0.502\nG1 X34.171 Y72.591 E0.502\nG1 X35.614 Y71.889 E0.501\nG1 X37.043 Y71.157 E0.502\nG1 X38.457 Y70.397 E0.502\nG1 X39.672 Y69.712 E0.436\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} - -## Anycubic MEGA ZERO -## Author: https://github.com/kad -## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4057 - -# Common print preset -[print:*common_mega0*] -avoid_crossing_perimeters = 1 -bridge_angle = 0 -bridge_flow_ratio = 0.7 -bridge_speed = 25 -brim_width = 0 -clip_multipart_objects = 1 -compatible_printers = -complete_objects = 0 -dont_support_bridges = 1 -elefant_foot_compensation = 0 -ensure_vertical_shell_thickness = 1 -external_fill_pattern = rectilinear -external_perimeters_first = 0 -external_perimeter_extrusion_width = 0.45 -extra_perimeters = 0 -extruder_clearance_height = 25 -extruder_clearance_radius = 45 -extrusion_width = 0.45 -fill_angle = 45 -fill_density = 20% -fill_pattern = grid -first_layer_extrusion_width = 0.42 -first_layer_height = 0.2 -first_layer_speed = 20 -gap_fill_speed = 30 -gcode_comments = 0 -infill_every_layers = 1 -infill_extruder = 1 -infill_extrusion_width = 0.45 -infill_first = 0 -infill_only_where_needed = 0 -infill_overlap = 25% -interface_shells = 0 -max_print_speed = 100 -max_volumetric_extrusion_rate_slope_negative = 0 -max_volumetric_extrusion_rate_slope_positive = 0 -max_volumetric_speed = 0 -min_skirt_length = 4 -notes = -overhangs = 1 -only_retract_when_crossing_perimeters = 0 -ooze_prevention = 0 -output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode -perimeters = 2 -perimeter_extruder = 1 -perimeter_extrusion_width = 0.45 -post_process = -print_settings_id = -raft_layers = 0 -resolution = 0 -seam_position = nearest -single_extruder_multi_material_priming = 1 -skirts = 2 -skirt_distance = 2 -skirt_height = 2 -small_perimeter_speed = 25 -solid_infill_below_area = 0 -solid_infill_every_layers = 0 -solid_infill_extruder = 1 -solid_infill_extrusion_width = 0.45 -spiral_vase = 0 -standby_temperature_delta = -5 -support_material = 0 -support_material_extruder = 0 -support_material_extrusion_width = 0.4 -support_material_interface_extruder = 0 -support_material_angle = 0 -support_material_buildplate_only = 0 -support_material_enforce_layers = 0 -support_material_contact_distance = 0.15 -support_material_interface_contact_loops = 0 -support_material_interface_layers = 2 -support_material_interface_spacing = 0.2 -support_material_interface_speed = 100% -support_material_pattern = rectilinear -support_material_spacing = 2 -support_material_speed = 40 -support_material_synchronize_layers = 0 -support_material_threshold = 45 -support_material_with_sheath = 0 -support_material_xy_spacing = 60% -thin_walls = 0 -top_infill_extrusion_width = 0.45 -top_solid_infill_speed = 40 -travel_speed = 100 -wipe_tower = 0 -wipe_tower_bridging = 10 -wipe_tower_rotation_angle = 0 -wipe_tower_width = 60 -wipe_tower_x = 170 -wipe_tower_y = 140 -xy_size_compensation = 0 - -[print:*0.10mm_mega0*] -inherits = *common_mega0* -perimeter_speed = 40 -external_perimeter_speed = 25 -infill_speed = 50 -solid_infill_speed = 40 -layer_height = 0.10 -perimeters = 3 -top_infill_extrusion_width = 0.4 -bottom_solid_layers = 6 -top_solid_layers = 7 - -[print:*0.20mm_mega0*] -inherits = *common_mega0* -perimeter_speed = 40 -external_perimeter_speed = 25 -infill_speed = 50 -solid_infill_speed = 40 -layer_height = 0.20 -top_infill_extrusion_width = 0.4 -bottom_solid_layers = 4 -top_solid_layers = 5 - -[print:*0.30mm_mega0*] -inherits = *common_mega0* -perimeter_speed = 40 -external_perimeter_speed = 25 -infill_speed = 50 -solid_infill_speed = 40 -layer_height = 0.24 -top_infill_extrusion_width = 0.45 -bottom_solid_layers = 3 -top_solid_layers = 4 - -[print:0.10mm DETAIL @MEGA0] -inherits = *0.10mm_mega0* -travel_speed = 120 -infill_speed = 50 -solid_infill_speed = 40 -top_solid_infill_speed = 30 -support_material_extrusion_width = 0.38 -compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4 - -[print:0.20mm NORMAL @MEGA0] -inherits = *0.20mm_mega0* -travel_speed = 120 -infill_speed = 50 -solid_infill_speed = 40 -top_solid_infill_speed = 30 -support_material_extrusion_width = 0.38 -compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4 - -[print:0.30mm DRAFT @MEGA0] -inherits = *0.30mm_mega0* -travel_speed = 120 -infill_speed = 50 -solid_infill_speed = 40 -top_solid_infill_speed = 30 -support_material_extrusion_width = 0.38 -compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4 - -# Common filament preset -[filament:*common_mega0*] -cooling = 0 -compatible_printers = -extrusion_multiplier = 1 -filament_cost = 0 -filament_density = 0 -filament_diameter = 1.75 -filament_notes = "" -filament_settings_id = "" -filament_soluble = 0 -min_print_speed = 15 -slowdown_below_layer_time = 20 -compatible_printers_condition = printer_model=="MEGA0" - -[filament:*PLA_mega0*] -inherits = *common_mega0* -bed_temperature = 40 -fan_below_layer_time = 100 -filament_colour = #FF3232 -filament_max_volumetric_speed = 15 -filament_type = PLA -filament_density = 1.24 -filament_cost = 20 -first_layer_bed_temperature = 40 -first_layer_temperature = 215 -fan_always_on = 1 -cooling = 1 -max_fan_speed = 100 -min_fan_speed = 100 -bridge_fan_speed = 100 -disable_fan_first_layers = 1 -temperature = 210 - -[filament:*PET_mega0*] -inherits = *common_mega0* -bed_temperature = 70 -cooling = 1 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #FF8000 -filament_max_volumetric_speed = 8 -filament_type = PETG -filament_density = 1.27 -filament_cost = 30 -first_layer_bed_temperature =70 -first_layer_temperature = 240 -fan_always_on = 1 -max_fan_speed = 50 -min_fan_speed = 20 -bridge_fan_speed = 100 -temperature = 240 - -[filament:*ABS_mega0*] -inherits = *common_mega0* -bed_temperature = 100 -cooling = 0 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #3A80CA -filament_max_volumetric_speed = 11 -filament_type = ABS -filament_density = 1.04 -filament_cost = 20 -first_layer_bed_temperature = 100 -first_layer_temperature = 245 -fan_always_on = 0 -max_fan_speed = 0 -min_fan_speed = 0 -bridge_fan_speed = 30 -top_fan_speed = 0 -temperature = 245 - -[filament:Generic PLA @MEGA0] -inherits = *PLA_mega0* -filament_vendor = Generic - -[filament:Generic PETG @MEGA0] -inherits = *PET_mega0* -filament_vendor = Generic - -[filament:Generic ABS @MEGA0] -inherits = *ABS_mega0* -filament_vendor = Generic - -[filament:Anycubic PLA @MEGA0] -inherits = *PLA_mega0* -filament_vendor = Anycubic -temperature = 190 -first_layer_temperature = 195 -filament_cost = 24.99 -filament_density = 1.25 - -[filament:Prusament PLA @MEGA0] -inherits = *PLA_mega0* -filament_vendor = Prusa Polymers -temperature = 215 -bed_temperature = 40 -first_layer_temperature = 215 -filament_cost = 24.99 -filament_density = 1.24 - -[filament:Prusament PETG @MEGA0] -inherits = *PET_mega0* -filament_vendor = Prusa Polymers -temperature = 245 -bed_temperature = 70 -first_layer_temperature = 245 -filament_cost = 24.99 -filament_density = 1.27 - -# Common printer preset -[printer:*common_mega0*] -printer_technology = FFF -bed_shape = 0x0,220x0,220x220,0x220 -before_layer_gcode = ; BEFORE_LAYER_CHANGE [layer_num] @ [layer_z]mm\nG92 E0 -between_objects_gcode = -deretract_speed = 0 -extruder_colour = #FFFF00 -extruder_offset = 0x0 -gcode_flavor = marlin -silent_mode = 0 -remaining_times = 0 -machine_max_acceleration_e = 10000 -machine_max_acceleration_extruding = 2000 -machine_max_acceleration_retracting = 1500 -machine_max_acceleration_x = 3000 -machine_max_acceleration_y = 3000 -machine_max_acceleration_z = 500 -machine_max_feedrate_e = 120 -machine_max_feedrate_x = 500 -machine_max_feedrate_y = 500 -machine_max_feedrate_z = 12 -machine_max_jerk_e = 2.5 -machine_max_jerk_x = 20 -machine_max_jerk_y = 20 -machine_max_jerk_z = 0.4 -machine_min_extruding_rate = 0 -machine_min_travel_rate = 0 -layer_gcode = ; AFTER_LAYER_CHANGE [layer_num] @ [layer_z]mm -max_layer_height = 0.3 -min_layer_height = 0.1 -max_print_height = 200 -nozzle_diameter = 0.4 -printer_notes = -printer_settings_id = -retract_before_travel = 1 -retract_before_wipe = 0% -retract_layer_change = 1 -retract_length = 6 -retract_length_toolchange = 1 -retract_lift = 0 -retract_lift_above = 0 -retract_lift_below = 0 -retract_restart_extra = 0 -retract_restart_extra_toolchange = 0 -retract_speed = 30 -single_extruder_multi_material = 0 -start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n -end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM140 S0 ; turn off heatbed\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n -toolchange_gcode = -use_firmware_retraction = 0 -use_relative_e_distances = 1 -use_volumetric_e = 0 -variable_layer_height = 1 -wipe = 1 -z_offset = 0 -printer_model = -default_print_profile = -default_filament_profile = - -[printer:Anycubic Mega Zero] -inherits = *common_mega0* -printer_model = MEGA0 -printer_variant = 0.4 -max_layer_height = 0.3 -min_layer_height = 0.1 -printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_MEGA0 -bed_shape = 0x0,220x0,220x220,0x220 -max_print_height = 250 -machine_max_acceleration_e = 5000 -machine_max_acceleration_extruding = 500 -machine_max_acceleration_retracting = 500 -machine_max_acceleration_x = 500 -machine_max_acceleration_y = 500 -machine_max_acceleration_z = 100 -machine_max_feedrate_e = 25 -machine_max_feedrate_x = 500 -machine_max_feedrate_y = 500 -machine_max_feedrate_z = 5 -machine_max_jerk_e = 5 -machine_max_jerk_x = 10 -machine_max_jerk_y = 10 -machine_max_jerk_z = 0.4 -machine_min_extruding_rate = 0 -machine_min_travel_rate = 0 -nozzle_diameter = 0.4 -retract_before_travel = 2 -retract_layer_change = 0 -retract_length = 7 -retract_speed = 30 -retract_lift = 0.2 -deretract_speed = 30 -retract_before_wipe = 70% -default_print_profile = 0.20mm NORMAL @MEGA0 -default_filament_profile = Anycubic PLA @MEGA0 -start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n -end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n - -## Anycubic i3 Mega and i3 Mega S -## Author: https://github.com/Igami -## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4619 - -[print:*common_mega*] -bottom_solid_min_thickness = 0.5 -bridge_acceleration = 1000 -bridge_flow_ratio = 0.95 -bridge_speed = 25 -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ and nozzle_diameter[0]==0.4 -default_acceleration = 1000 -ensure_vertical_shell_thickness = 1 -external_perimeter_extrusion_width = 0.45 -external_perimeter_speed = 40 -extruder_clearance_height = 35 -extruder_clearance_radius = 60 -extrusion_width = 0.45 -fill_density = 15% -fill_pattern = gyroid -first_layer_acceleration = 800 -first_layer_extrusion_width = 0.42 -first_layer_height = 0.2 -first_layer_speed = 20 -gap_fill_speed = 40 -gcode_comments = 0 -gcode_label_objects = 1 -infill_acceleration = 1000 -infill_anchor = 2.5 -infill_anchor_max = 12 -infill_extrusion_width = 0.45 -max_print_speed = 100 -min_skirt_length = 4 -only_retract_when_crossing_perimeters = 0 -output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode -perimeter_acceleration = 800 -perimeter_extrusion_width = 0.45 -perimeter_speed = 50 -perimeters = 2 -seam_position = nearest -skirt_distance = 2 -skirt_height = 3 -skirts = 1 -small_perimeter_speed = 25 -solid_infill_below_area = 0 -solid_infill_extrusion_width = 0.45 -solid_infill_speed = 50 -support_material = 0 -support_material_buildplate_only = 0 -support_material_contact_distance = 0.1 -support_material_extrusion_width = 0.35 -support_material_interface_layers = 2 -support_material_interface_spacing = 0.2 -support_material_interface_speed = 80% -support_material_spacing = 2 -support_material_speed = 50 -support_material_threshold = 50 -support_material_xy_spacing = 60% -thin_walls = 0 -top_infill_extrusion_width = 0.4 -top_solid_infill_speed = 40 -top_solid_min_thickness = 0.7 -travel_speed = 180 - -# XXXXXXXXXXXXXXXXXXXX -# XXX--- 0.15mm ---XXX -# XXXXXXXXXXXXXXXXXXXX - -[print:*0.15mm_mega*] -inherits = *common_mega* -bottom_solid_layers = 5 -bridge_flow_ratio = 1 -infill_speed = 60 -layer_height = 0.15 -top_solid_layers = 7 - -[print:0.15mm QUALITY @MEGA] -inherits = *0.15mm_mega* - -# XXXXXXXXXXXXXXXXXXXX -# XXX--- 0.20mm ---XXX -# XXXXXXXXXXXXXXXXXXXX - -[print:*0.20mm_mega*] -inherits = *common_mega* -bottom_solid_layers = 4 -infill_speed = 60 -layer_height = 0.2 -top_solid_layers = 5 - -[print:0.20mm QUALITY @MEGA] -inherits = *0.20mm_mega* - -# XXXXXXXXXXXXXXXXXXXX -# XXX--- 0.30mm ---XXX -# XXXXXXXXXXXXXXXXXXXX - -[print:*0.30mm_mega*] -inherits = *common_mega* -bottom_solid_layers = 4 -external_perimeter_extrusion_width = 0.6 -external_perimeter_speed = 35 -extrusion_width = 0.5 -fill_pattern = cubic -infill_extrusion_width = 0.5 -infill_speed = 85 -layer_height = 0.3 -perimeter_extrusion_width = 0.5 -small_perimeter_speed = 30 -solid_infill_extrusion_width = 0.5 -support_material_extrusion_width = 0.38 -support_material_speed = 45 -top_solid_layers = 4 - -[print:0.30mm DRAFT @MEGA] -inherits = *0.30mm_mega* - -# XXXXXXXXXXXXXXXXXXXXXX -# XXX--- filament ---XXX -# XXXXXXXXXXXXXXXXXXXXXX - -[filament:*common_mega*] -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ -end_filament_gcode = "; Filament-specific end gcode" -fan_always_on = 1 -fan_below_layer_time = 100 -filament_vendor = Generic -min_print_speed = 15 -slowdown_below_layer_time = 20 - -[filament:*ABS_mega*] - inherits = *common_mega* - bed_temperature = 110 - bridge_fan_speed = 25 - cooling = 0 - fan_always_on = 0 - fan_below_layer_time = 20 - filament_colour = #3A80CA - filament_cost = 27.82 - filament_density = 1.04 - filament_max_volumetric_speed = 11 - filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" - filament_type = ABS - first_layer_bed_temperature = 105 - first_layer_temperature = 255 - max_fan_speed = 30 - min_fan_speed = 20 - temperature = 255 - -[filament:Generic ABS @MEGA] -inherits = *ABS_mega* - -[filament:*FLEX_mega*] -inherits = *common_mega* -bed_temperature = 50 -bridge_fan_speed = 80 -cooling = 0 -extrusion_multiplier = 1.15 -fan_always_on = 0 -filament_colour = #008000 -filament_cost = 82.00 -filament_density = 1.22 -filament_deretract_speed = 25 -filament_max_volumetric_speed = 1.2 -filament_retract_length = 0.8 -filament_type = FLEX -first_layer_bed_temperature = 55 -first_layer_temperature = 240 -max_fan_speed = 90 -min_fan_speed = 70 -temperature = 240 - -[filament:Generic FLEX @MEGA] -inherits = *FLEX_mega* - -[filament:SainSmart TPU @MEGA] -inherits = *FLEX_mega* -filament_vendor = SainSmart -bed_temperature = 50 -bridge_fan_speed = 100 -cooling = 1 -disable_fan_first_layers = 4 -filament_cost = 39.99 -filament_density = 1.21 -filament_deretract_speed = 15 -filament_max_volumetric_speed = 1.8 -filament_notes = "SainSmart TPU gains popularity among 3D Printing community for its balance of rigidity and flexibility. In addition, with a 95A Shore Hardness and improved bed adhesion, it is easier to print even with a stock elementary 3D Printer like the Creality Ender 3. SainSmart TPU will not disappoint if you are looking for flexible filament. From drone parts, phone cases, to small toys, all can be printed with ease.\n\nhttps://www.sainsmart.com/collections/tpu-filament/products/all-colors-tpu-flexible-filament-1-75mm-0-8kg-1-76lb" -filament_retract_before_travel = 5 -filament_retract_length = 4 -filament_retract_speed = 40 -filament_unloading_speed = 90 -first_layer_bed_temperature = 55 -first_layer_temperature = 235 -full_fan_speed_layer = 6 -max_fan_speed = 80 -min_fan_speed = 80 -slowdown_below_layer_time = 10 -temperature = 235 - -[filament:*PETG_mega*] -inherits = *common_mega* -bed_temperature = 90 -bridge_fan_speed = 50 -fan_below_layer_time = 20 -filament_colour = #FF8000 -filament_cost = 27.82 -filament_density = 1.27 -filament_max_volumetric_speed = 8 -filament_type = PETG -first_layer_bed_temperature = 90 -first_layer_temperature = 230 -max_fan_speed = 50 -min_fan_speed = 30 -temperature = 240 - -[filament:Generic PETG @MEGA] -inherits = *PETG_mega* - -[filament:ColorFabb XT-CF20 @MEGA] -inherits = *PETG_mega* -compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ -extrusion_multiplier = 1.05 -filament_colour = #804040 -filament_cost = 66.60 -filament_density = 1.35 -filament_deretract_speed = 25 -filament_max_volumetric_speed = 2 -filament_notes = "Based on colorFabb_XT, XT-CF20 is a carbon fiber composite material. Loaded with no less than 20% specially sourced carbon fibers we have developed a very stiff and tough 3D printing filament made for functional parts. It is truly a professional printers go-to material, especially for users looking for high melt strength, high melt viscosity and good dimensional accuracy and stability.\n\nhttps://colorfabb.com/xt-cf20" -filament_retract_before_travel = 1 -filament_retract_length = 1.4 -filament_retract_speed = 40 -filament_spool_weight = 236 -filament_vendor = ColorFabb -first_layer_temperature = 260 -full_fan_speed_layer = 5 -slowdown_below_layer_time = 15 -temperature = 260 - -[filament:ERYONE PETG @MEGA] -inherits = *PETG_mega* -filament_vendor = ERYONE -filament_cost = 20.99 -filament_notes = "https://eryone.com/petg/show/10.html" - -[filament:FormFutura HDglass @MEGA] -inherits = *PETG_mega* -filament_vendor = FormFutura -filament_cost = 46.65 -filament_notes = "HDglass is a high performance PETG type of 3D printer with unsurpassed 3D printing properties and improved mechanical strength, flexibility, toughness and heat resistance.\n\nhttps://www.formfutura.com/shop/product/hdglass-2812" - -[filament:FormFutura ReForm rPET @MEGA] -inherits = *PETG_mega* -filament_vendor = FormFutura -filament_cost = 26.65 -filament_notes = "ReForm rPET is a recycled PETG type of 3D printer filament that is made from post-industrial waste streams of a nearby located plastic bottle manufacturer.\n\nhttps://www.formfutura.com/shop/product/reform-rpet-2836" -filament_spool_weight = 176 - -[filament:Janbex transparent PETG @MEGA] -inherits = *PETG_mega* -filament_vendor = Janbex -filament_cost = 31.99 -filament_spool_weight = 222 -first_layer_temperature = 215 -min_fan_speed = 100 -temperature = 210 - -[filament:DAS FILAMENT PETG @MEGA] -inherits = *PETG_mega* -filament_vendor = DAS FILAMENT -bed_temperature = 75 -first_layer_bed_temperature = 75 -first_layer_temperature = 220 -temperature = 225 - -[filament:*PLA_mega*] -inherits = *common_mega* -bed_temperature = 60 -disable_fan_first_layers = 1 -filament_colour = #FF3232 -filament_cost = 25.40 -filament_density = 1.24 -filament_max_volumetric_speed = 10 -first_layer_bed_temperature = 65 -first_layer_temperature = 215 -min_fan_speed = 100 -temperature = 210 - -[filament:Generic PLA @MEGA] -inherits = *PLA_mega* - -[filament:3Dmensionals PLA @MEGA] -inherits = *PLA_mega* -filament_vendor = 3Dmensionals -filament_cost = 22.90 -filament_notes = "Das 3DFilaments - PLA von 3Dmensionals ist ein sehr leicht zu druckendes 3D-Drucker Filament. Dabei handelt es sich um ein etwas härteres PLA mit einer exzellenten thermischen Stabilität. Das Filament zeichnet sich vor allem durch verzugfreies 3D-Drucken aus und weist minimale bis keine Verformung nach dem Abkühlen auf. Daher ist es besonders gut für den Druck größerer Objekte geeignet. Zudem bietet 3DFilaments - PLA über die gesamte Fadenläge eine hervorragende Durchmesser- und Rundheitstoleranz.\n\nhttps://www.3dmensionals.de/3dfilaments?number=PSU3DM001V" - -[filament:3D Warhorse PLA @MEGA] -inherits = *PLA_mega* -filament_vendor = 3D Warhorse -filament_cost = 19.99 - -[filament:AMOLEN wood PLA] -inherits = *PLA_mega* -filament_vendor = AMOLEN -compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ -extrusion_multiplier = 1.1 -filament_colour = #DFC287 -filament_cost = 33.99 -filament_density = 1.23 -filament_max_volumetric_speed = 9 -filament_notes = "https://amolen.com/collections/wood/products/amolen-pla-filament-1-75mm-wood-color-3d-printer-filament-1kg2-2lb" - -[filament:FormFutura EasyFil PLA @MEGA] -inherits = *PLA_mega* -filament_vendor = FormFutura -filament_cost = 39.93 -filament_notes = "EasyFil PLA is an easy to print PLA type of 3D printer filament that is available in a wide variety of colors. Its improved flowing behavior make 3D printed layers flow more into each other.\n\nhttps://www.formfutura.com/shop/product/easyfil-pla-2801" - -[filament:FormFutura ReForm rPLA @MEGA] -inherits = *PLA_mega* -filament_vendor = FormFutura -filament_cost = 26.65 -filament_notes = "ReForm is a sustainable initiative within Formfutura to efficiently manage residual extrusion waste streams and re-use them into high-end upcycled filaments. The ideology behind ReForm is to a make 3D printing more sustainable – without having to make compromises on material properties – and yet keep it affordable.\n\nhttps://www.formfutura.com/shop/product/reform-rpla-2838" - -[filament:GIANTARM PLA @MEGA] -inherits = *PLA_mega* -filament_vendor = GIANTARM -filament_cost = 24.99 - -[filament:Prusament PLA @MEGA] -inherits = *PLA_mega* -filament_vendor = Prusa Polymers -filament_cost = 30.24 -filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa" -filament_spool_weight = 201 -temperature = 215 - -[filament:Verbatim PLA @MEGA] -inherits = *PLA_mega* -filament_vendor = Verbatim -filament_cost = 23.88 - -[printer:*common_mega*] -printer_technology = FFF -bed_shape = 0x0,210x0,210x210,0x210 -before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z] -default_filament_profile = Generic PLA @MEGA -default_print_profile = 0.15mm QUALITY @MEGA -deretract_speed = 50 -end_gcode = G1 E-1.0 F2100 ; retract\nG92 E0.0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} E-34.0 F720 ; move print head up & retract filament\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y105 F3000 ; park print head\nM84 ; disable motors -extruder_colour = #808080 -gcode_flavor = marlin -layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] -max_layer_height = 0.36 -max_print_height = 205 -remaining_times = 1 -retract_before_travel = 1.5 -retract_before_wipe = 60% -retract_layer_change = 1 -retract_length = 6 -retract_lift = 0.075 -retract_lift_below = 204 -retract_speed = 40 -silent_mode = 0 -start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y1.0 Z0.3 F1000 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0.0\n; initial load\nG1 X205.0 E19 F1000\nG1 Y1.6\nG1 X5.0 E19 F1000\nG92 E0.0\n; intro line\nG1 Y2.0 Z0.2 F1000\nG1 X65.0 E9.0 F1000\nG1 X105.0 E12.5 F1000\nG92 E0.0 -thumbnails = 16x16,220x124 -use_relative_e_distances = 1 -wipe = 1 -machine_max_acceleration_e = 10000 -machine_max_acceleration_extruding = 1250 -machine_max_acceleration_retracting = 1250 -machine_max_acceleration_x = 3000 -machine_max_acceleration_y = 2000 -machine_max_acceleration_z = 60 -machine_max_feedrate_e = 60 -machine_max_feedrate_x = 500 -machine_max_feedrate_y = 500 -machine_max_feedrate_z = 6 -machine_max_jerk_e = 5 -machine_max_jerk_x = 10 -machine_max_jerk_y = 10 -machine_max_jerk_z = 0.4 - -[printer:Anycubic i3 Mega] -inherits = *common_mega* -printer_model = I3MEGA -printer_variant = 0.4 -printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA\nPRINTER_HAS_BOWDEN - -[printer:Anycubic i3 Mega S] -inherits = *common_mega* -printer_model = I3MEGAS -printer_variant = 0.4 -printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA_S\nPRINTER_HAS_BOWDEN -machine_max_feedrate_e = 30 -machine_max_feedrate_z = 8 - - -## Anycubic PREDATOR -## Author: https://github.com/tillverka3d -## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4960 - -######################################### -###### begin common print presets ####### -######################################### - -# Common print preset -[print:*common predator*] -spiral_vase = 0 -top_solid_min_thickness = 0.8 -bottom_solid_min_thickness = 0.6 -extra_perimeters = 0 -ensure_vertical_shell_thickness = 1 -avoid_crossing_perimeters = 0 -thin_walls = 0 -overhangs = 1 -seam_position = nearest -external_perimeters_first = 0 -fill_density = 20% -external_fill_pattern = rectilinear -infill_every_layers = 1 -infill_only_where_needed = 0 -solid_infill_every_layers = 0 -fill_angle = 45 -solid_infill_below_area = 20 -bridge_angle = 0 -only_retract_when_crossing_perimeters = 0 -infill_first = 0 -skirts = 1 -skirt_distance = 4 -skirt_height = 1 -min_skirt_length = 8 -brim_width = 0 -support_material = 0 -support_material_auto = 1 -support_material_threshold = 50 -support_material_enforce_layers = 0 -raft_layers = 0 -support_material_contact_distance = 0.1 -support_material_pattern = rectilinear -support_material_with_sheath = 0 -support_material_spacing = 2 -support_material_angle = 0 -support_material_interface_layers = 2 -support_material_interface_spacing = 0.2 -support_material_interface_contact_loops = 0 -support_material_buildplate_only = 0 -support_material_xy_spacing = 60% -dont_support_bridges = 1 -support_material_synchronize_layers = 0 -travel_speed = 94 -first_layer_speed = 15 -perimeter_acceleration = 0 -infill_acceleration = 0 -bridge_acceleration = 0 -first_layer_acceleration = 0 -default_acceleration = 0 -max_volumetric_speed = 15 -perimeter_extruder = 1 -infill_extruder = 1 -solid_infill_extruder = 1 -support_material_extruder = 0 -support_material_interface_extruder = 0 -ooze_prevention = 0 -standby_temperature_delta = -5 -wipe_tower = 0 -wipe_tower_x = 170 -wipe_tower_y = 140 -wipe_tower_width = 60 -wipe_tower_rotation_angle = 0 -wipe_tower_bridging = 10 -interface_shells = 0 -bridge_flow_ratio = 0.8 -resolution = 0 -xy_size_compensation = 0 -elefant_foot_compensation = 0.2 -clip_multipart_objects = 1 -complete_objects = 0 -extruder_clearance_radius = 45 -extruder_clearance_height = 25 -gcode_comments = 0 -output_filename_format = {input_filename_base}.gcode -post_process = -notes = -max_volumetric_extrusion_rate_slope_negative = 0 -max_volumetric_extrusion_rate_slope_positive = 0 -print_settings_id = - -# Common print preset -[print:*common predator 0.4 nozzle*] -inherits = *common predator* -first_layer_height = 0.16 -infill_overlap = 25% -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.4 - -# Common print preset -[print:*common predator 0.6 nozzle*] -inherits = *common predator* -first_layer_height = 0.24 -infill_overlap = 27% -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.6 - -# Common print preset -[print:*common predator 0.8 nozzle*] -inherits = *common predator* -first_layer_height = 0.32 -infill_overlap = 30% -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.8 - -# Common print preset -[print:*common predator quality*] -perimeter_speed = 50 -small_perimeter_speed = 15 -external_perimeter_speed = 70% -infill_speed = 65 -solid_infill_speed = 85% -top_solid_infill_speed = 85% -support_material_speed = 30 -support_material_interface_speed = 85% -bridge_speed = 30 -gap_fill_speed = 40 -ironing_speed = 15 - -# Common print preset -[print:*common predator speed*] -perimeter_speed = 70 -small_perimeter_speed = 15 -external_perimeter_speed = 70% -infill_speed = 85 -solid_infill_speed = 85% -top_solid_infill_speed = 85% -support_material_speed = 30 -support_material_interface_speed = 85% -bridge_speed = 30 -gap_fill_speed = 40 -ironing_speed = 15 - -# Common print preset -[print:*common predator 0.4 nozzle detailed*] -inherits = *common predator 0.4 nozzle* -extrusion_width = 0.42 -first_layer_extrusion_width = 0.41 -perimeter_extrusion_width = 0.42 -external_perimeter_extrusion_width = 0.42 -infill_extrusion_width = 0.4 -solid_infill_extrusion_width = 0.4 -top_infill_extrusion_width = 0.4 -support_material_extrusion_width = 0.38 - -# Common print preset -[print:*common predator 0.4 nozzle coarse*] -inherits = *common predator 0.4 nozzle* -extrusion_width = 0.44 -first_layer_extrusion_width = 0.42 -perimeter_extrusion_width = 0.5 -external_perimeter_extrusion_width = 0.5 -infill_extrusion_width = 0.5 -solid_infill_extrusion_width = 0.5 -top_infill_extrusion_width = 0.4 -support_material_extrusion_width = 0.38 - -# Common print preset -[print:*common predator 0.6 nozzle detailed*] -inherits = *common predator 0.6 nozzle* -extrusion_width = 0.64 -first_layer_extrusion_width = 0.62 -perimeter_extrusion_width = 0.64 -external_perimeter_extrusion_width = 0.64 -infill_extrusion_width = 0.6 -solid_infill_extrusion_width = 0.6 -top_infill_extrusion_width = 0.6 -support_material_extrusion_width = 0.56 - -# Common print preset -[print:*common predator 0.6 nozzle coarse*] -inherits = *common predator 0.6 nozzle* -extrusion_width = 0.67 -first_layer_extrusion_width = 0.64 -perimeter_extrusion_width = 0.7 -external_perimeter_extrusion_width = 0.7 -infill_extrusion_width = 0.7 -solid_infill_extrusion_width = 0.7 -top_infill_extrusion_width = 0.6 -support_material_extrusion_width = 0.56 - -# Common print preset -[print:*common predator 0.8 nozzle detailed*] -inherits = *common predator 0.8 nozzle* -extrusion_width = 0.84 -first_layer_extrusion_width = 0.82 -perimeter_extrusion_width = 0.84 -external_perimeter_extrusion_width = 0.84 -infill_extrusion_width = 0.8 -solid_infill_extrusion_width = 0.8 -top_infill_extrusion_width = 0.8 -support_material_extrusion_width = 0.72 - -# Common print preset -[print:*common predator 0.8 nozzle coarse*] -inherits = *common predator 0.8 nozzle* -extrusion_width = 0.87 -first_layer_extrusion_width = 0.84 -perimeter_extrusion_width = 0.9 -external_perimeter_extrusion_width = 0.9 -infill_extrusion_width = 0.9 -solid_infill_extrusion_width = 0.9 -top_infill_extrusion_width = 0.8 -support_material_extrusion_width = 0.72 - -######################################### -####### end common print presets ######## -######################################### - -######################################### -########## begin print presets ########## -######################################### - -[print:0.08mm 0.4 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.4 nozzle detailed*; *common predator quality* -layer_height = 0.08 -max_print_speed = 50 -perimeters = 3 -fill_pattern = grid - -[print:0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.4 nozzle detailed*; *common predator quality* -layer_height = 0.16 -max_print_speed = 60 -perimeters = 3 -fill_pattern = grid - -[print:0.16mm 0.4 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.4 nozzle coarse*; *common predator quality* -layer_height = 0.16 -max_print_speed = 60 -perimeters = 3 -fill_pattern = grid - -[print:0.24mm 0.4 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.4 nozzle detailed*; *common predator quality* -layer_height = 0.24 -max_print_speed = 70 -perimeters = 3 -fill_pattern = grid - -[print:0.24mm 0.4 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.4 nozzle coarse*; *common predator quality* -layer_height = 0.24 -max_print_speed = 70 -perimeters = 3 -fill_pattern = grid - -[print:0.32mm 0.4 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.4 nozzle detailed*; *common predator quality* -layer_height = 0.32 -max_print_speed = 70 -perimeters = 3 -fill_pattern = grid - -[print:0.32mm 0.4 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.4 nozzle coarse*; *common predator quality* -layer_height = 0.32 -max_print_speed = 70 -perimeters = 3 -fill_pattern = grid - -[print:0.16mm 0.6 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator quality* -layer_height = 0.16 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.16mm 0.6 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator speed* -layer_height = 0.16 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.16mm 0.6 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator quality* -layer_height = 0.16 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.16mm 0.6 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator speed* -layer_height = 0.16 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.6 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator quality* -layer_height = 0.24 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.6 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator speed* -layer_height = 0.24 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.6 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator quality* -layer_height = 0.24 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.6 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator speed* -layer_height = 0.24 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.6 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator quality* -layer_height = 0.32 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.6 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator speed* -layer_height = 0.32 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.6 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator quality* -layer_height = 0.32 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.6 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator speed* -layer_height = 0.32 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.6 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator quality* -layer_height = 0.4 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.6 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle detailed*; *common predator speed* -layer_height = 0.4 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.6 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator quality* -layer_height = 0.4 -max_print_speed = 70 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.6 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.6 nozzle coarse*; *common predator speed* -layer_height = 0.4 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator quality* -layer_height = 0.24 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.8 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator speed* -layer_height = 0.24 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.8 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator quality* -layer_height = 0.24 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.24mm 0.8 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator speed* -layer_height = 0.24 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.8 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator quality* -layer_height = 0.32 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.8 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator speed* -layer_height = 0.32 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.8 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator quality* -layer_height = 0.32 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.32mm 0.8 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator speed* -layer_height = 0.32 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.8 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator quality* -layer_height = 0.4 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.8 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator speed* -layer_height = 0.4 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.8 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator quality* -layer_height = 0.4 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.4mm 0.8 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator speed* -layer_height = 0.4 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -[print:0.48mm 0.8 nozzle DETAILED QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator quality* -layer_height = 0.48 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.48mm 0.8 nozzle DETAILED SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle detailed*; *common predator speed* -layer_height = 0.48 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -[print:0.48mm 0.8 nozzle COARSE QUALITY @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator quality* -layer_height = 0.48 -max_print_speed = 80 -perimeters = 2 -fill_pattern = gyroid - -[print:0.48mm 0.8 nozzle COARSE SPEED @PREDATOR] -inherits = *common predator 0.8 nozzle coarse*; *common predator speed* -layer_height = 0.48 -max_print_speed = 90 -perimeters = 2 -fill_pattern = gyroid - -######################################### -########### end print presets ########### -######################################### - -######################################### -######## begin filament presets ######### -######################################### - -# Common filament preset -[filament:*common predator*] -cooling = 0 -compatible_printers = -extrusion_multiplier = 1 -filament_cost = 0 -filament_density = 0 -filament_diameter = 1.75 -filament_notes = "" -filament_settings_id = "" -filament_soluble = 0 -min_print_speed = 15 -slowdown_below_layer_time = 20 -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ - -[filament:*PLA predator*] -inherits = *common predator* -bed_temperature = 60 -fan_below_layer_time = 100 -filament_colour = #FF3232 -filament_max_volumetric_speed = 10 -filament_type = PLA -filament_density = 1.24 -filament_cost = 20 -first_layer_bed_temperature = 60 -first_layer_temperature = 200 -fan_always_on = 1 -cooling = 1 -max_fan_speed = 100 -min_fan_speed = 100 -bridge_fan_speed = 100 -disable_fan_first_layers = 1 -temperature = 200 - -[filament:*PET predator*] -inherits = *common predator* -bed_temperature = 70 -cooling = 1 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #FF8000 -filament_max_volumetric_speed = 8 -filament_type = PETG -filament_density = 1.27 -filament_cost = 30 -first_layer_bed_temperature =70 -first_layer_temperature = 240 -fan_always_on = 1 -max_fan_speed = 50 -min_fan_speed = 20 -bridge_fan_speed = 100 -temperature = 240 - -[filament:*ABS predator*] -inherits = *common predator* -bed_temperature = 100 -cooling = 0 -disable_fan_first_layers = 3 -fan_below_layer_time = 20 -filament_colour = #3A80CA -filament_max_volumetric_speed = 10 -filament_type = ABS -filament_density = 1.04 -filament_cost = 20 -first_layer_bed_temperature = 100 -first_layer_temperature = 245 -fan_always_on = 0 -max_fan_speed = 0 -min_fan_speed = 0 -bridge_fan_speed = 30 -top_fan_speed = 0 -temperature = 245 - -[filament:Generic PLA @PREDATOR] -inherits = *PLA predator* -filament_vendor = Generic - -[filament:Generic PETG @PREDATOR] -inherits = *PET predator* -filament_vendor = Generic - -[filament:Generic ABS @PREDATOR] -inherits = *ABS predator* -filament_vendor = Generic - -######################################### -######### end filament presets ########## -######################################### - -######################################### -######### begin printer presets ######### -######################################### - -# Anycubic predator common printer preset -[printer:*common predator*] -printer_vendor = Anycubic -printer_model = Predator -printer_technology = FFF -printer_variant = 0.4 -thumbnails = 16x16,220x124 -bed_shape = 188.779x16.516,186.621x32.9063,183.043x49.0462,178.072x64.8128,171.745x80.0862,164.112x94.75,155.229x108.693,145.165x121.808,133.997x133.997,121.808x145.165,108.693x155.229,94.75x164.112,80.0862x171.745,64.8128x178.072,49.0462x183.043,32.9063x186.621,16.516x188.779,1.16035e-14x189.5,-16.516x188.779,-32.9063x186.621,-49.0462x183.043,-64.8128x178.072,-80.0862x171.745,-94.75x164.112,-108.693x155.229,-121.808x145.165,-133.997x133.997,-145.165x121.808,-155.229x108.693,-164.112x94.75,-171.745x80.0862,-178.072x64.8128,-183.043x49.0462,-186.621x32.9063,-188.779x16.516,-189.5x2.32071e-14,-188.779x-16.516,-186.621x-32.9063,-183.043x-49.0462,-178.072x-64.8128,-171.745x-80.0862,-164.112x-94.75,-155.229x-108.693,-145.165x-121.808,-133.997x-133.997,-121.808x-145.165,-108.693x-155.229,-94.75x-164.112,-80.0862x-171.745,-64.8128x-178.072,-49.0462x-183.043,-32.9063x-186.621,-16.516x-188.779,-3.48106e-14x-189.5,16.516x-188.779,32.9063x-186.621,49.0462x-183.043,64.8128x-178.072,80.0862x-171.745,94.75x-164.112,108.693x-155.229,121.808x-145.165,133.997x-133.997,145.165x-121.808,155.229x-108.693,164.112x-94.75,171.745x-80.0862,178.072x-64.8128,183.043x-49.0462,186.621x-32.9063,188.779x-16.516,189.5x-4.64141e-14 -max_print_height = 445 -z_offset = 0 -single_extruder_multi_material = 0 -gcode_flavor = reprap -silent_mode = 0 -remaining_times = 0 -use_relative_e_distances = 0 -use_firmware_retraction = 0 -use_volumetric_e = 0 -variable_layer_height = 1 -start_gcode = ; start_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; set metric values\n\nG21\n\n; use absolute positioning\n\nG90\n\n; set extruder to absolute mode\n\nM82\n\n; start with fan off\n\nM107\n\n; set temps\n\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\n\n; home xy\n\nG28 X0 Y0\n\n; home z\n\nG28 Z0\n\n; move the head down to Z 94mm\n\nG1 Z94.0 F2394\n\n; set and wait for temps\n\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\n\n; zero the extruded length\n\nG92 E0\n\n; extrude 3mm of feed stock\n\nG1 F200 E3\n\n; zero the extruded length again\n\nG92 E0\n\n; set speed\n\nG1 F{travel_speed}\n\n; print preskirt\n\nG92 E0\nG1 E3.94000 F2520.00000\n\nG1 X125.464 Y-139.310\nG1 Z0.329 F3994.000\n\nG1 F994.000\n\nG1 X125.464 Y-139.310 E4.19679\nG1 X130.218 Y-134.876 E4.70359\nG1 X132.569 Y-132.567 E4.96053\nG1 X137.099 Y-127.877 E5.46890\nG1 X139.325 Y-125.447 E5.72585\nG1 X141.507 Y-122.981 E5.98254\nG1 X145.685 Y-118.002 E6.48934\nG1 X149.741 Y-112.810 E7.00296\nG1 X153.561 Y-107.552 E7.50975\nG1 X155.440 Y-104.819 E7.76827\nG1 X158.980 Y-99.367 E8.27506\nG1 X160.702 Y-96.558 E8.53201\nG1 X163.962 Y-90.911 E9.04038\nG1 X165.535 Y-88.015 E9.29732\nG1 X168.496 Y-82.205 E9.80570\nG1 X169.915 Y-79.231 E10.06264\nG1 X171.280 Y-76.235 E10.31934\nG1 X173.819 Y-70.251 E10.82613\nG1 X176.180 Y-64.101 E11.33975\nG1 X178.297 Y-57.955 E11.84654\nG1 X179.294 Y-54.793 E12.10507\nG1 X181.085 Y-48.544 E12.61186\nG1 X181.911 Y-45.354 E12.86880\nG1 X183.378 Y-39.001 E13.37718\nG1 X184.035 Y-35.771 E13.63412\nG1 X185.168 Y-29.350 E14.14250\nG1 X185.655 Y-26.091 E14.39944\nG1 X186.084 Y-22.826 E14.65614\nG1 X186.764 Y-16.362 E15.16293\nG1 X187.223 Y-9.790 E15.67655\nG1 X187.450 Y-3.294 E16.18334\nG1 X187.479 Y0.002 E16.44028\nG1 X187.450 Y3.294 E16.69698\nG1 X187.223 Y9.810 E17.20529\nG1 X187.021 Y13.100 E17.46229\nG1 X186.454 Y19.575 E17.96909\nG1 X186.079 Y22.870 E18.22761\nG1 X185.174 Y29.307 E18.73440\nG1 X184.031 Y35.794 E19.24802\nG1 X182.679 Y42.152 E19.75481\nG1 X181.910 Y45.357 E20.01176\nG1 X180.223 Y51.655 E20.52013\nG1 X179.287 Y54.815 E20.77708\nG1 X177.272 Y61.017 E21.28545\nG1 X176.172 Y64.123 E21.54239\nG1 X175.019 Y67.207 E21.79909\nG1 X172.584 Y73.234 E22.30588\nG1 X169.905 Y79.252 E22.81950\nG1 X167.055 Y85.094 E23.32629\nG1 X165.524 Y88.035 E23.58482\nG1 X162.373 Y93.721 E24.09161\nG1 X160.700 Y96.560 E24.34855\nG1 X157.245 Y102.090 E24.85693\nG1 X155.427 Y104.838 E25.11387\nG1 X151.687 Y110.180 E25.62225\nG1 X149.727 Y112.829 E25.87919\nG1 X147.722 Y115.441 E26.13588\nG1 X143.631 Y120.493 E26.64268\nG1 X139.310 Y125.464 E27.15629\nG1 X134.876 Y130.218 E27.66309\nG1 X132.567 Y132.569 E27.92003\nG1 X127.877 Y137.099 E28.42840\nG1 X125.447 Y139.325 E28.68535\nG1 X122.981 Y141.507 E28.94204\nG1 X118.002 Y145.685 E29.44883\nG1 X112.810 Y149.741 E29.96245\nG1 X107.552 Y153.561 E30.46924\nG1 X104.819 Y155.440 E30.72777\nG1 X99.367 Y158.980 E31.23456\nG1 X96.558 Y160.702 E31.49151\nG1 X90.911 Y163.962 E31.99988\nG1 X88.015 Y165.535 E32.25682\nG1 X82.205 Y168.496 E32.76520\nG1 X79.231 Y169.915 E33.02214\nG1 X76.235 Y171.280 E33.27884\nG1 X70.251 Y173.819 E33.78563\nG1 X64.101 Y176.180 E34.29925\nG1 X57.955 Y178.297 E34.80604\nG1 X54.793 Y179.294 E35.06457\nG1 X48.544 Y181.085 E35.57136\nG1 X45.354 Y181.911 E35.82830\nG1 X39.001 Y183.378 E36.33668\nG1 X35.771 Y184.035 E36.59362\nG1 X29.350 Y185.168 E37.10200\nG1 X26.091 Y185.655 E37.35894\nG1 X22.826 Y186.084 E37.61563\nG1 X16.362 Y186.764 E38.12242\nG1 X9.790 Y187.223 E38.63605\nG1 X3.294 Y187.450 E39.14283\nG1 X-0.002 Y187.479 E39.39978\nG1 X-3.294 Y187.450 E39.65648\nG1 X-9.810 Y187.223 E40.16479\nG1 X-13.100 Y187.021 E40.42179\nG1 X-19.575 Y186.454 E40.92858\nG1 X-22.870 Y186.079 E41.18711\nG1 X-29.307 Y185.174 E41.69390\nG1 X-35.794 Y184.031 E42.20752\nG1 X-42.152 Y182.679 E42.71431\nG1 X-45.357 Y181.910 E42.97126\nG1 X-51.655 Y180.223 E43.47963\nG1 X-54.815 Y179.287 E43.73657\nG1 X-61.017 Y177.272 E44.24495\nG1 X-64.123 Y176.172 E44.50189\nG1 X-67.207 Y175.019 E44.75859\nG1 X-73.234 Y172.584 E45.26538\nG1 X-79.252 Y169.905 E45.77900\nG1 X-85.094 Y167.055 E46.28579\nG1 X-88.035 Y165.524 E46.54432\nG1 X-93.721 Y162.373 E47.05111\nG1 X-96.560 Y160.700 E47.30805\nG1 X-102.090 Y157.245 E47.81643\nG1 X-104.838 Y155.427 E48.07337\nG1 X-110.180 Y151.687 E48.58174\nG1 X-112.829 Y149.727 E48.83869\nG1 X-115.441 Y147.722 E49.09538\nG1 X-120.493 Y143.631 E49.60218\nG1 X-125.464 Y139.310 E50.11579\nG1 X-130.218 Y134.876 E50.62259\nG1 X-132.569 Y132.567 E50.87953\nG1 X-137.099 Y127.877 E51.38790\nG1 X-139.325 Y125.447 E51.64485\nG1 X-141.507 Y122.981 E51.90154\nG1 X-145.685 Y118.002 E52.40833\nG1 X-149.741 Y112.810 E52.92195\nG1 X-153.561 Y107.552 E53.42874\nG1 X-155.440 Y104.819 E53.68727\nG1 X-158.980 Y99.367 E54.19406\nG1 X-160.702 Y96.558 E54.45101\nG1 X-163.962 Y90.911 E54.95938\nG1 X-165.535 Y88.015 E55.21632\nG1 X-168.496 Y82.205 E55.72470\nG1 X-169.915 Y79.231 E55.98164\nG1 X-171.280 Y76.235 E56.23834\nG1 X-173.819 Y70.251 E56.74513\nG1 X-176.180 Y64.101 E57.25875\nG1 X-178.297 Y57.955 E57.76554\nG1 X-179.294 Y54.793 E58.02407\nG1 X-181.085 Y48.544 E58.53086\nG1 X-181.911 Y45.354 E58.78780\nG1 X-183.378 Y39.001 E59.29618\nG1 X-184.035 Y35.771 E59.55312\nG1 X-185.168 Y29.350 E60.06149\nG1 X-185.655 Y26.091 E60.31844\nG1 X-186.084 Y22.826 E60.57513\nG1 X-186.764 Y16.362 E61.08192\nG1 X-187.223 Y9.790 E61.59554\nG1 X-187.450 Y3.294 E62.10233\nG1 X-187.479 Y-0.002 E62.35928\nG1 X-187.450 Y-3.294 E62.61598\nG1 X-187.223 Y-9.810 E63.12429\nG1 X-187.021 Y-13.100 E63.38129\nG1 X-186.454 Y-19.575 E63.88808\nG1 X-186.079 Y-22.870 E64.14661\nG1 X-185.174 Y-29.307 E64.65340\nG1 X-184.031 Y-35.794 E65.16702\nG1 X-182.679 Y-42.152 E65.67381\nG1 X-181.910 Y-45.357 E65.93076\nG1 X-180.223 Y-51.655 E66.43913\nG1 X-179.287 Y-54.815 E66.69607\nG1 X-177.272 Y-61.017 E67.20445\nG1 X-176.172 Y-64.123 E67.46139\nG1 X-175.019 Y-67.207 E67.71809\nG1 X-172.584 Y-73.234 E68.22488\nG1 X-169.905 Y-79.252 E68.73850\nG1 X-167.055 Y-85.094 E69.24529\nG1 X-165.524 Y-88.035 E69.50382\nG1 X-162.373 Y-93.721 E70.01061\nG1 X-160.700 Y-96.560 E70.26755\nG1 X-157.245 Y-102.090 E70.77593\nG1 X-155.427 Y-104.838 E71.03287\nG1 X-151.687 Y-110.180 E71.54124\nG1 X-149.727 Y-112.829 E71.79819\nG1 X-147.722 Y-115.441 E72.05488\nG1 X-143.631 Y-120.493 E72.56167\nG1 X-139.310 Y-125.464 E73.07529\nG1 X-134.876 Y-130.218 E73.58209\nG1 X-132.567 Y-132.569 E73.83903\nG1 X-127.877 Y-137.099 E74.34740\nG1 X-125.447 Y-139.325 E74.60435\nG1 X-122.981 Y-141.507 E74.86104\nG1 X-118.002 Y-145.685 E75.36783\nG1 X-112.810 Y-149.741 E75.88145\nG1 X-107.552 Y-153.561 E76.38824\nG1 X-104.819 Y-155.440 E76.64677\nG1 X-99.367 Y-158.980 E77.15356\nG1 X-96.558 Y-160.702 E77.41051\nG1 X-90.911 Y-163.962 E77.91888\nG1 X-88.015 Y-165.535 E78.17582\nG1 X-82.205 Y-168.496 E78.68420\nG1 X-79.231 Y-169.915 E78.94114\nG1 X-76.235 Y-171.280 E79.19784\nG1 X-70.251 Y-173.819 E79.70463\nG1 X-64.101 Y-176.180 E80.21825\nG1 X-57.955 Y-178.297 E80.72504\nG1 X-54.793 Y-179.294 E80.98356\nG1 X-48.544 Y-181.085 E81.49036\nG1 X-45.354 Y-181.911 E81.74730\nG1 X-39.001 Y-183.378 E82.25568\nG1 X-35.771 Y-184.035 E82.51262\nG1 X-29.350 Y-185.168 E83.02099\nG1 X-26.091 Y-185.655 E83.27794\nG1 X-22.826 Y-186.084 E83.53463\nG1 X-16.362 Y-186.764 E84.04142\nG1 X-9.790 Y-187.223 E84.55504\nG1 X-3.294 Y-187.450 E85.06183\nG1 X0.006 Y-187.479 E85.31908\nG1 X6.521 Y-187.366 E85.82715\nG1 X9.810 Y-187.223 E86.08379\nG1 X13.100 Y-187.021 E86.34079\nG1 X19.575 Y-186.454 E86.84758\nG1 X22.870 Y-186.079 E87.10611\nG1 X29.307 Y-185.174 E87.61290\nG1 X35.794 Y-184.031 E88.12652\nG1 X42.152 Y-182.679 E88.63331\nG1 X45.357 Y-181.910 E88.89025\nG1 X51.655 Y-180.223 E89.39863\nG1 X54.815 Y-179.287 E89.65557\nG1 X61.017 Y-177.272 E90.16395\nG1 X64.123 Y-176.172 E90.42089\nG1 X67.207 Y-175.019 E90.67759\nG1 X73.234 Y-172.584 E91.18438\nG1 X79.252 Y-169.905 E91.69800\nG1 X85.094 Y-167.055 E92.20479\nG1 X88.035 Y-165.524 E92.46332\nG1 X93.721 Y-162.373 E92.97011\nG1 X96.560 Y-160.700 E93.22705\nG1 X102.090 Y-157.245 E93.73543\nG1 X104.838 Y-155.427 E93.99237\nG1 X110.180 Y-151.687 E94.50074\nG1 X112.829 Y-149.727 E94.75768\nG1 X115.441 Y-147.722 E95.01438\nG1 X120.493 Y-143.631 E95.52117\nG1 X122.911 Y-141.529 E95.77098\n\n; end preskirt\n; start_gcode | end -end_gcode = ; end_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; use relative positioning\n\nG91\n\n; retract the filament a bit before lifting the nozzle to release some of the pressure\n\nG1 E-1 F300\n\n; home\n\nG28\n\n; use absolute positioning\n\nG90\n\n; cooldown\n\nM104 S0\nM140 S0\n\n; end_gcode | end\n -before_layer_gcode = -layer_gcode = -toolchange_gcode = -between_objects_gcode = -retract_length = 4 -retract_lift = 0.3 -retract_lift_above = 0 -retract_lift_below = 449 -retract_speed = 30 -deretract_speed = 0 -retract_restart_extra = 0 -retract_before_travel = 2 -retract_layer_change = 1 -wipe = 1 -retract_before_wipe = 70% -retract_length_toolchange = 10 -retract_restart_extra_toolchange = 0 -extruder_colour = #1193FF -machine_max_acceleration_e = 3000 -machine_max_acceleration_extruding = 1000 -machine_max_acceleration_retracting = 1000 -machine_max_acceleration_x = 1500 -machine_max_acceleration_y = 1500 -machine_max_acceleration_z = 1500 -machine_max_feedrate_e = 60 -machine_max_feedrate_x = 200 -machine_max_feedrate_y = 200 -machine_max_feedrate_z = 200 -machine_max_jerk_e = 5 -machine_max_jerk_x = 5 -machine_max_jerk_y = 5 -machine_max_jerk_z = 5 -machine_min_extruding_rate = 0 -machine_min_travel_rate = 0 -printer_settings_id = -printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PREDATOR\nPRINTER_HAS_BOWDEN\n -default_filament_profile = Generic PLA @PREDATOR - -[printer:Anycubic Predator 0.4 nozzle] -inherits = *common predator* -printer_model = PREDATOR -printer_variant = 0.4 -nozzle_diameter = 0.4 -min_layer_height = 0.08 -max_layer_height = 0.32 -default_print_profile = 0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR - -[printer:Anycubic Predator 0.6 nozzle] -inherits = *common predator* -printer_model = PREDATOR -printer_variant = 0.6 -nozzle_diameter = 0.6 -min_layer_height = 0.12 -max_layer_height = 0.4 -default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR - -[printer:Anycubic Predator 0.8 nozzle] -inherits = *common predator* -printer_model = PREDATOR -printer_variant = 0.8 -nozzle_diameter = 0.8 -min_layer_height = 0.16 -max_layer_height = 0.48 -default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR - -## Anycubic 4MAX Pro 2.0 -## based on https://hartrusion.com/en/prusaslicer-config-for-anycubic-4max-pro-2-0/ - -[print:*common_4max*] -avoid_crossing_perimeters = 0 -avoid_crossing_perimeters_max_detour = 0 -bottom_fill_pattern = monotonic -bottom_solid_layers = 4 -bridge_acceleration = 300 -bridge_angle = 0 -bridge_flow_ratio = 0.65 -bridge_speed = 30 -brim_separation = 0 -brim_type = outer_only -brim_width = 0 -clip_multipart_objects = 1 -compatible_printers_condition = printer_model=="4MAXPRO20" and nozzle_diameter[0]==0.4 -complete_objects = 0 -default_acceleration = 900 -dont_support_bridges = 1 -draft_shield = disabled -elefant_foot_compensation = 0.2 -ensure_vertical_shell_thickness = 1 -external_perimeter_extrusion_width = 0 -external_perimeter_speed = 35 -external_perimeters_first = 0 -extra_perimeters = 0 -extruder_clearance_height = 20 -extruder_clearance_radius = 20 -extrusion_width = 0.45 -fill_angle = 45 -fill_density = 20% -fill_pattern = gyroid -first_layer_acceleration = 300 -first_layer_acceleration_over_raft = 0 -first_layer_extrusion_width = 0.65 -first_layer_height = 0.3 -first_layer_speed = 20 -first_layer_speed_over_raft = 30 -fuzzy_skin = none -fuzzy_skin_point_dist = 0.8 -fuzzy_skin_thickness = 0.3 -gap_fill_enabled = 1 -gap_fill_speed = 40 -gcode_comments = 0 -gcode_label_objects = 0 -gcode_resolution = 0.0125 -infill_acceleration = 600 -infill_anchor = 400% -infill_anchor_max = 50 -infill_every_layers = 1 -infill_extruder = 1 -infill_extrusion_width = 0 -infill_first = 0 -infill_only_where_needed = 0 -infill_overlap = 23% -infill_speed = 45 -inherits = -interface_shells = 0 -ironing = 0 -ironing_flowrate = 15% -ironing_spacing = 0.1 -ironing_speed = 15 -ironing_type = top -layer_height = 0.2 -max_print_speed = 50 -max_volumetric_speed = 0 -min_skirt_length = 0 -only_retract_when_crossing_perimeters = 0 -ooze_prevention = 0 -output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{print_time}.gcode -overhangs = 1 -perimeter_acceleration = 500 -perimeter_extruder = 1 -perimeter_extrusion_width = 0 -perimeter_speed = 45 -perimeters = 3 -post_process = -print_settings_id = -raft_contact_distance = 0.1 -raft_expansion = 1.5 -raft_first_layer_density = 90% -raft_first_layer_expansion = 3 -raft_layers = 0 -resolution = 0 -seam_position = aligned -single_extruder_multi_material_priming = 1 -skirt_distance = 5 -skirt_height = 1 -skirts = 2 -slicing_mode = regular -small_perimeter_speed = 20 -solid_infill_below_area = 0 -solid_infill_every_layers = 0 -solid_infill_extruder = 1 -solid_infill_extrusion_width = 0 -solid_infill_speed = 45 -spiral_vase = 0 -standby_temperature_delta = -5 -support_material = 0 -support_material_angle = 0 -support_material_auto = 1 -support_material_bottom_contact_distance = 0 -support_material_bottom_interface_layers = -1 -support_material_buildplate_only = 1 -support_material_closing_radius = 2 -support_material_contact_distance = 0.2 -support_material_enforce_layers = 0 -support_material_extruder = 1 -support_material_extrusion_width = 0.4 -support_material_interface_contact_loops = 0 -support_material_interface_extruder = 1 -support_material_interface_layers = 2 -support_material_interface_pattern = rectilinear -support_material_interface_spacing = 0.2 -support_material_interface_speed = 30 -support_material_pattern = rectilinear-grid -support_material_spacing = 2.5 -support_material_speed = 45 -support_material_style = grid -support_material_synchronize_layers = 0 -support_material_threshold = 45 -support_material_with_sheath = 1 -support_material_xy_spacing = 60% -thick_bridges = 1 -thin_walls = 0 -top_fill_pattern = monotonic -top_infill_extrusion_width = 0.4 -top_solid_infill_speed = 30 -top_solid_layers = 5 -travel_speed = 60 -travel_speed_z = 0 -wipe_tower = 0 -wipe_tower_bridging = 10 -wipe_tower_brim_width = 2 -wipe_tower_no_sparse_layers = 0 -wipe_tower_rotation_angle = 0 -wipe_tower_width = 60 -wipe_tower_x = 180 -wipe_tower_y = 140 -xy_size_compensation = 0 - -[print:0.15mm Detail @4Max Pro 2.0] -inherits = *common_4max* -layer_height = 0.15 -bottom_solid_layers = 5 -top_solid_layers = 7 -perimeter_speed = 40 -external_perimeter_speed = 25 - -[print:0.20mm Quality @4Max Pro 2.0] -inherits = *common_4max* -external_perimeter_speed = 25 - -[print:0.30mm Draft @4Max Pro 2.0] -inherits = *common_4max* -layer_height = 0.3 -bottom_solid_layers = 3 -top_solid_layers = 3 - -[filament:*common_4max*] -bed_temperature = 60 -bridge_fan_speed = 100 -compatible_printers_condition = printer_model=="4MAXPRO20" -cooling = 1 -disable_fan_first_layers = 1 -extrusion_multiplier = 1 -fan_always_on = 1 -fan_below_layer_time = 30 -filament_density = 1.24 -filament_diameter = 1.75 -filament_max_volumetric_speed = 0 -filament_type = PLA -first_layer_bed_temperature = 60 -first_layer_temperature = 210 -full_fan_speed_layer = 5 -max_fan_speed = 100 -min_fan_speed = 80 -min_print_speed = 10 -slowdown_below_layer_time = 15 -temperature = 205 - -[filament:*PLA_4max*] -inherits = *common_4max* - -[filament:Generic PLA @4Max Pro 2.0] -inherits = *PLA_4max* -filament_vendor = Generic - -[filament:Anycubic PLA @4Max Pro 2.0] -inherits = *PLA_4max* -first_layer_temperature = 215 -temperature = 207 -filament_vendor = Anycubic - -[filament:Generic ABS @4Max Pro 2.0] -filament_vendor = Generic -compatible_printers_condition = printer_model=="4MAXPRO20" -bed_temperature = 100 -first_layer_bed_temperature = 100 -temperature = 245 -first_layer_temperature = 245 -bridge_fan_speed = 15 -cooling = 1 -disable_fan_first_layers = 3 -extrusion_multiplier = 1 -fan_always_on = 0 -fan_below_layer_time = 60 -filament_colour = #800000 -filament_density = 1.04 -filament_diameter = 1.75 -filament_type = ABS -full_fan_speed_layer = 0 -max_fan_speed = 0 -min_fan_speed = 0 -min_print_speed = 10 -slowdown_below_layer_time = 25 - -[filament:Generic TPU @4Max Pro 2.0] -filament_vendor = Generic -bed_temperature = 60 -bridge_fan_speed = 0 -compatible_printers_condition = printer_model=="4MAXPRO20" -cooling = 1 -disable_fan_first_layers = 3 -extrusion_multiplier = 1 -fan_always_on = 0 -fan_below_layer_time = 60 -filament_colour = #211AB5 -filament_density = 1.19 -filament_deretract_speed = 20 -filament_diameter = 1.75 -filament_retract_speed = 30 -filament_type = FLEX -filament_max_volumetric_speed = 1.65 -first_layer_bed_temperature = 60 -first_layer_temperature = 215 -full_fan_speed_layer = 0 -max_fan_speed = 0 -min_fan_speed = 0 -min_print_speed = 10 -slowdown_below_layer_time = 20 -temperature = 215 - -[filament:Polymaker PolyFlex TPU95 @4Max Pro 2.0] -filament_vendor = Polymaker -bed_temperature = 45 -bridge_fan_speed = 80 -compatible_printers_condition = printer_model=="4MAXPRO20" -cooling = 1 -disable_fan_first_layers = 5 -extrusion_multiplier = 1.04 -fan_always_on = 1 -fan_below_layer_time = 45 -filament_colour = #FD7D2F -filament_density = 1.22 -filament_deretract_speed = 25 -filament_diameter = 1.75 -filament_max_volumetric_speed = 1.65 -filament_retract_length = 4 -filament_retract_restart_extra = 0.1 -filament_retract_speed = 60 -filament_type = FLEX -first_layer_bed_temperature = 55 -first_layer_temperature = 215 -full_fan_speed_layer = 8 -max_fan_speed = 50 -min_fan_speed = 25 -min_print_speed = 10 -slowdown_below_layer_time = 10 -temperature = 217 - -[printer:Anycubic 4Max Pro 2.0] -printer_model = 4MAXPRO20 -printer_variant = 0.4 -printer_technology = FFF -bed_shape = 0x0,270x0,270x210,0x210 -color_change_gcode = M600 -default_filament_profile = Generic PLA @4Max Pro 2.0 -default_print_profile = 0.20mm Quality @4Max Pro 2.0 -deretract_speed = 25 -end_gcode = M104 S0 ; turn off extruder heating\nM140 S0 ; turn off bed heating\nM107 ; turn off fans\nG91 ; relative positioning\nG0 Z+0.5 ; move Z up a tiny bit\nG90 ; absolute positioning\nG0 X135 Y105 F{machine_max_feedrate_x[0]*60} ; move extruder to center position\nG0 Z190.5 F{machine_max_feedrate_z[0]*60} ; lower the plattform to Z min\nM84 ; steppers off\nG90 ; absolute positioning\n -extruder_offset = 0x0 -gcode_flavor = marlin -machine_limits_usage = time_estimate_only -machine_max_acceleration_e = 5000 -machine_max_acceleration_extruding = 1250 -machine_max_acceleration_retracting = 1250 -machine_max_acceleration_travel = 1500 -machine_max_acceleration_x = 900 -machine_max_acceleration_y = 900 -machine_max_acceleration_z = 100 -machine_max_feedrate_e = 120 -machine_max_feedrate_x = 200 -machine_max_feedrate_y = 200 -machine_max_feedrate_z = 16 -machine_max_jerk_e = 5 -machine_max_jerk_x = 6 -machine_max_jerk_y = 6 -machine_max_jerk_z = 0.2 -machine_min_extruding_rate = 0 -machine_min_travel_rate = 0 -max_layer_height = 0.3 -max_print_height = 190 -min_layer_height = 0.07 -nozzle_diameter = 0.4 -pause_print_gcode = M601 -remaining_times = 0 -retract_before_travel = 2 -retract_before_wipe = 0% -retract_layer_change = 1 -retract_length = 2.5 -retract_length_toolchange = 10 -retract_lift = 0 -retract_lift_above = 0 -retract_lift_below = 0 -retract_restart_extra = 0 -retract_restart_extra_toolchange = 0 -retract_speed = 35 -silent_mode = 0 -single_extruder_multi_material = 0 -start_gcode = G21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 X0 Y0 ; home X and Y\nG28 Z0 ; home Z\nG1 Z30 F{machine_max_feedrate_z[0]*60} ; move Z a bit down to not blow on the bed edge while heating\nG1 X10 F3900 ; let some space on x to prevent the filament cooling exhaust from beeing blocked by the servo motor\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM104 S[first_layer_temperature] ; set extruder temp\nM106 S80 ; turn on fan to prevent air nozzle melt while heating up\nM109 S[first_layer_temperature] ; wait for extruder temp\nM107 ; start with the fan off\nG28 X0 ; goto X home again\nG92 E0 ; zero the extruded length\nG1 Z0.2 F360 ; move plattform upwards\n; extrude material next to the plattform (comment or remove following lines to disable)\nG1 F180 E20 ; extrude some material next to the plattform\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG92 E0 ; zero the extruded length again\nG1 X5 F3900 ; move sideways to get rid of that string\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\nG92 E0 ; zero the extruded length again\n; draw intro line (comment or remove following lines to disable)\nG1 X30 E5 F700 ; draw intro line\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG1 X40 Z2.0 ; move away from the introline\nG92 E0 ; zero the extruded length again\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\n; end of intro line code\nM117 Printing...\nG5 -use_firmware_retraction = 0 -use_relative_e_distances = 0 -use_volumetric_e = 0 -variable_layer_height = 1 -wipe = 0 -z_offset = 0 \ No newline at end of file +# Print profiles for the Anycubic printers. + +[vendor] +# Vendor name will be shown by the Config Wizard. +name = Anycubic +# Configuration version of this file. Config file will only be installed, if the config_version differs. +# This means, the server may force the PrusaSlicer configuration to be downgraded. +config_version = 0.1.1 +# Where to get the updates from? +config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anycubic/ +# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% + +# The printer models will be shown by the Configuration Wizard in this order, +# also the first model installed & the first nozzle installed will be activated after install. +# Printer model name will be shown by the installation wizard. + +[printer_model:AKLP] +name = Anycubic Kossel Linear Plus +variants = 0.4 +technology = FFF +family = KOSSEL +bed_model = AKLP_Bed.stl +bed_texture = AK.svg +default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL + +[printer_model:AK] +name = Anycubic Kossel Pulley (Linear) +variants = 0.4 +technology = FFF +family = KOSSEL +bed_model = AK_Bed.stl +bed_texture = AK.svg +default_materials = Generic PLA @AKOSSEL; Generic PETG @AKOSSEL; Generic ABS @AKOSSEL + +[printer_model:MEGA0] +name = Anycubic Mega Zero +variants = 0.4 +technology = FFF +family = MEGA +bed_model = mega0_bed.stl +bed_texture = mega0.svg +default_materials = Generic PLA @MEGA0; Generic PETG @MEGA0; Anycubic PLA @MEGA0; Prusament PLA @MEGA0; Prusament PETG @MEGA0 + +[printer_model:I3MEGA] +name = Anycubic i3 Mega +variants = 0.4 +technology = FFF +family = MEGA +bed_model = i3megas_bed.stl +bed_texture = i3megas.svg + +[printer_model:I3MEGAS] +name = Anycubic i3 Mega S +variants = 0.4 +technology = FFF +family = MEGA +bed_model = i3megas_bed.stl +bed_texture = i3megas.svg + +[printer_model:4MAXPRO20] +name = Anycubic 4Max Pro 2.0 +variants = 0.4 +technology = FFF +family = 4Max +bed_model = 4MAXPRO20_bed.stl +bed_texture = 4MAXPRO20_texture.svg +default_materials = Generic PLA @4Max Pro 2.0; Generic TPU @4Max Pro 2.0; Generic ABS @4Max Pro 2.0 + +[printer_model:PREDATOR] +name = Anycubic Predator +variants = 0.4; 0.6; 0.8 +technology = FFF +family = PREDATOR +default_materials = Generic PLA @PREDATOR; Generic PETG @PREDATOR; Generic ABS @PREDATOR + +[printer_model:PHOTON MONO X] +name = Photon Mono X +variants = default +technology = SLA +family = PHOTON MONO +default_materials = Generic Blue Resin @MONO 0.05 + +# All presets starting with asterisk, for example *common*, are intermediate and they will +# not make it into the user interface. + +## Anycubic KOSSEL +## Author: https://github.com/tc0fh +## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4220 + +# Common print preset +[print:*common_akossel*] +avoid_crossing_perimeters = 0 +bottom_solid_min_thickness = 0.5 +bridge_angle = 0 +bridge_flow_ratio = 0.8 +bridge_speed = 30 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = +complete_objects = 0 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeters_first = 0 +external_perimeter_extrusion_width = 0.45 +extra_perimeters = 0 +extruder_clearance_height = 25 +extruder_clearance_radius = 45 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = grid +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 20 +gap_fill_speed = 40 +gcode_comments = 0 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +interface_shells = 0 +max_print_speed = 200 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +overhangs = 0 +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode +perimeters = 2 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 45 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +single_extruder_multi_material_priming = 0 +skirts = 2 +skirt_distance = 5 +skirt_height = 1 +small_perimeter_speed = 25 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.38 +support_material_interface_extruder = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_enforce_layers = 0 +support_material_contact_distance = 0.15 +support_material_interface_contact_loops = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 50 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 40 +top_solid_min_thickness = 0.6 +travel_speed = 180 +wipe_tower = 1 +wipe_tower_bridging = 10 +wipe_tower_rotation_angle = 0 +wipe_tower_width = 60 +wipe_tower_x = 170 +wipe_tower_y = 140 +xy_size_compensation = 0 +bridge_acceleration = 1000 +default_acceleration = 1500 +first_layer_acceleration = 1000 +infill_acceleration = 1500 +perimeter_acceleration = 800 + +[print:*0.08mm_akossel*] +inherits = *common_akossel* +bottom_solid_layers = 10 +bridge_acceleration = 300 +bridge_flow_ratio = 0.7 +bridge_speed = 20 +external_perimeter_speed = 20 +first_layer_acceleration = 500 +gap_fill_speed = 20 +infill_acceleration = 800 +infill_speed = 40 +layer_height = 0.08 +max_print_speed = 80 +perimeter_acceleration = 300 +perimeter_speed = 30 +perimeters = 3 +small_perimeter_speed = 20 +solid_infill_speed = 40 +support_material_extrusion_width = 0.3 +support_material_spacing = 1.5 +support_material_speed = 40 +top_solid_infill_speed = 30 +top_solid_layers = 12 + +[print:*0.16mm_akossel*] +inherits = *common_akossel* +bottom_solid_layers = 5 +layer_height = 0.16 +top_solid_layers = 6 + +[print:*0.20mm_akossel*] +inherits = *common_akossel* +bottom_solid_layers = 4 +bridge_flow_ratio = 0.95 +layer_height = 0.20 +top_solid_layers = 5 + +[print:*0.24mm_akossel*] +inherits = *common_akossel* +bottom_solid_layers = 4 +bridge_flow_ratio = 0.95 +layer_height = 0.24 +perimeter_speed = 50 +external_perimeter_speed = 35 +top_solid_layers = 4 +infill_speed = 100 +solid_infill_speed = 100 +top_solid_infill_speed = 40 + +[print:*0.30mm_akossel*] +inherits = *common_akossel* +bottom_solid_layers = 3 +bridge_flow_ratio = 0.95 +external_perimeter_extrusion_width = 0.6 +external_perimeter_speed = 35 +extrusion_width = 0.5 +infill_extrusion_width = 0.5 +infill_speed = 70 +layer_height = 0.30 +perimeter_extrusion_width = 0.5 +perimeter_speed = 50 +small_perimeter_speed = 30 +solid_infill_extrusion_width = 0.5 +solid_infill_speed = 70 +support_material_speed = 45 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 50 +top_solid_layers = 3 + +[print:0.08mm ULTRADETAIL @AKOSSEL] +inherits = *0.08mm_akossel* +fill_density = 15% +fill_pattern = gyroid +compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 + +[print:0.16mm QUALITY @AKOSSEL] +inherits = *0.16mm_akossel* +external_perimeter_speed = 25 +fill_density = 15% +fill_pattern = gyroid +infill_speed = 80 +compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 + +[print:0.16mm SPEED @AKOSSEL] +inherits = *0.16mm_akossel* +external_perimeter_speed = 35 +infill_speed = 120 +perimeter_speed = 60 +solid_infill_speed = 120 +top_solid_infill_speed = 50 +compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 + +[print:0.20mm QUALITY @AKOSSEL] +inherits = *0.20mm_akossel* +external_perimeter_speed = 25 +fill_density = 15% +fill_pattern = gyroid +infill_speed = 80 +compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 + +[print:0.20mm SPEED @AKOSSEL] +inherits = *0.20mm_akossel* +external_perimeter_speed = 35 +infill_speed = 120 +perimeter_speed = 60 +solid_infill_speed = 120 +top_solid_infill_speed = 50 +compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 + +[print:0.24mm DRAFT @AKOSSEL] +inherits = *0.24mm_akossel* +compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 + +[print:0.30mm FAST @AKOSSEL] +inherits = *0.30mm_akossel* +compatible_printers_condition = printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ and nozzle_diameter[0]==0.4 + +# Common filament preset +[filament:*common_akossel*] +cooling = 0 +compatible_printers = +extrusion_multiplier = 1 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_notes = "" +filament_settings_id = "" +filament_soluble = 0 +min_print_speed = 15 +slowdown_below_layer_time = 20 +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_Anycubic.*/ and printer_notes=~/.*PRINTER_MODEL_AK(|LP).*/ + +[filament:*PLA_akossel*] +inherits = *common_akossel* +bed_temperature = 60 +fan_below_layer_time = 100 +filament_colour = #FF3232 +filament_max_volumetric_speed = 10 +filament_type = PLA +filament_density = 1.24 +filament_cost = 20 +first_layer_bed_temperature = 60 +first_layer_temperature = 200 +fan_always_on = 1 +cooling = 1 +max_fan_speed = 100 +min_fan_speed = 100 +bridge_fan_speed = 100 +disable_fan_first_layers = 1 +temperature = 200 + +[filament:*PET_akossel*] +inherits = *common_akossel* +bed_temperature = 70 +cooling = 1 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_max_volumetric_speed = 8 +filament_type = PETG +filament_density = 1.27 +filament_cost = 30 +first_layer_bed_temperature =70 +first_layer_temperature = 240 +fan_always_on = 1 +max_fan_speed = 50 +min_fan_speed = 20 +bridge_fan_speed = 100 +temperature = 240 + +[filament:*ABS_akossel*] +inherits = *common_akossel* +bed_temperature = 100 +cooling = 0 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_max_volumetric_speed = 10 +filament_type = ABS +filament_density = 1.04 +filament_cost = 20 +first_layer_bed_temperature = 100 +first_layer_temperature = 245 +fan_always_on = 0 +max_fan_speed = 0 +min_fan_speed = 0 +bridge_fan_speed = 30 +top_fan_speed = 0 +temperature = 245 + +[filament:Generic PLA @AKOSSEL] +inherits = *PLA_akossel* +filament_vendor = Generic + +[filament:Generic PETG @AKOSSEL] +inherits = *PET_akossel* +filament_vendor = Generic + +[filament:Generic ABS @AKOSSEL] +inherits = *ABS_akossel* +filament_vendor = Generic + +# Common printer preset +[printer:*common_akossel*] +printer_technology = FFF +bed_shape = +before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0\n;[layer_z] +between_objects_gcode = +deretract_speed = 40 +extruder_colour = #FFFF00 +extruder_offset = 0x0 +gcode_flavor = marlin +silent_mode = 0 +remaining_times = 0 +machine_max_acceleration_e = 3000 +machine_max_acceleration_extruding = 1000 +machine_max_acceleration_retracting = 1000 +machine_max_acceleration_x = 1500 +machine_max_acceleration_y = 1500 +machine_max_acceleration_z = 1500 +machine_max_feedrate_e = 60 +machine_max_feedrate_x = 200 +machine_max_feedrate_y = 200 +machine_max_feedrate_z = 200 +machine_max_jerk_e = 5 +machine_max_jerk_x = 5 +machine_max_jerk_y = 5 +machine_max_jerk_z = 5 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.3 +min_layer_height = 0.08 +max_print_height = 300 +nozzle_diameter = 0.4 +printer_notes = +printer_settings_id = +retract_before_travel = 2 +retract_before_wipe = 70% +retract_layer_change = 1 +retract_length = 5 +retract_length_toolchange = 1 +retract_lift = 0 +retract_lift_above = 0 +retract_lift_below = 0 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 60 +single_extruder_multi_material = 0 +start_gcode = +end_gcode = M104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG28 ; home\nM84 ; disable motors +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 +default_print_profile = 0.20mm QUALITY @AKOSSEL +default_filament_profile = Generic PLA @AKOSSEL + +[printer:Anycubic Kossel Linear Plus] +inherits = *common_akossel* +printer_model = AKLP +printer_variant = 0.4 +printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AKLP\nPRINTER_HAS_BOWDEN\n +bed_shape = 114.562x10.0229,113.253x19.9695,111.081x29.7642,108.065x39.3323,104.225x48.6011,99.5929x57.5,94.2025x65.9613,88.0951x73.9206,81.3173x81.3173,73.9206x88.0951,65.9613x94.2025,57.5x99.5929,48.6011x104.225,39.3323x108.065,29.7642x111.081,19.9695x113.253,10.0229x114.562,7.04172e-15x115,-10.0229x114.562,-19.9695x113.253,-29.7642x111.081,-39.3323x108.065,-48.6011x104.225,-57.5x99.5929,-65.9613x94.2025,-73.9206x88.0951,-81.3173x81.3173,-88.0951x73.9206,-94.2025x65.9613,-99.5929x57.5,-104.225x48.6011,-108.065x39.3323,-111.081x29.7642,-113.253x19.9695,-114.562x10.0229,-115x1.40834e-14,-114.562x-10.0229,-113.253x-19.9695,-111.081x-29.7642,-108.065x-39.3323,-104.225x-48.6011,-99.5929x-57.5,-94.2025x-65.9613,-88.0951x-73.9206,-81.3173x-81.3173,-73.9206x-88.0951,-65.9613x-94.2025,-57.5x-99.5929,-48.6011x-104.225,-39.3323x-108.065,-29.7642x-111.081,-19.9695x-113.253,-10.0229x-114.562,-2.11252e-14x-115,10.0229x-114.562,19.9695x-113.253,29.7642x-111.081,39.3323x-108.065,48.6011x-104.225,57.5x-99.5929,65.9613x-94.2025,73.9206x-88.0951,81.3173x-81.3173,88.0951x-73.9206,94.2025x-65.9613,99.5929x-57.5,104.225x-48.6011,108.065x-39.3323,111.081x-29.7642,113.253x-19.9695,114.562x-10.0229,115x-2.81669e-14 +start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-54.672 Y95.203 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-52.931 Y96.185 E0.300\nG1 X-50.985 Y97.231 E0.331\nG1 X-49.018 Y98.238 E0.331\nG1 X-47.032 Y99.205 E0.331\nG1 X-45.026 Y100.132 E0.331\nG1 X-43.003 Y101.019 E0.331\nG1 X-40.961 Y101.864 E0.331\nG1 X-38.904 Y102.668 E0.331\nG1 X-36.83 Y103.431 E0.331\nG1 X-34.742 Y104.152 E0.331\nG1 X-32.639 Y104.83 E0.331\nG1 X-30.523 Y105.466 E0.331\nG1 X-28.395 Y106.06 E0.331\nG1 X-26.255 Y106.61 E0.331\nG1 X-24.105 Y107.117 E0.331\nG1 X-21.945 Y107.581 E0.331\nG1 X-19.776 Y108.001 E0.331\nG1 X-17.599 Y108.377 E0.331\nG1 X-15.415 Y108.71 E0.331\nG1 X-13.224 Y108.998 E0.331\nG1 X-11.028 Y109.242 E0.331\nG1 X-8.828 Y109.442 E0.331\nG1 X-6.624 Y109.598 E0.331\nG1 X-4.418 Y109.709 E0.331\nG1 X-2.209 Y109.776 E0.332\nG1 X0 Y109.798 E0.331\nG1 X2.209 Y109.776 E0.690\nG1 X4.418 Y109.709 E0.691\nG1 X6.624 Y109.598 E0.690\nG1 X8.828 Y109.442 E0.690\nG1 X11.028 Y109.242 E0.690\nG1 X13.224 Y108.998 E0.690\nG1 X15.415 Y108.71 E0.691\nG1 X17.599 Y108.377 E0.690\nG1 X19.776 Y108.001 E0.690\nG1 X21.945 Y107.581 E0.690\nG1 X24.105 Y107.117 E0.690\nG1 X26.255 Y106.61 E0.690\nG1 X28.395 Y106.06 E0.690\nG1 X30.523 Y105.466 E0.690\nG1 X32.639 Y104.83 E0.690\nG1 X34.742 Y104.152 E0.690\nG1 X36.83 Y103.431 E0.690\nG1 X38.904 Y102.668 E0.691\nG1 X40.961 Y101.864 E0.690\nG1 X43.003 Y101.019 E0.691\nG1 X45.026 Y100.132 E0.690\nG1 X47.032 Y99.205 E0.691\nG1 X49.018 Y98.238 E0.690\nG1 X50.985 Y97.231 E0.691\nG1 X52.931 Y96.185 E0.690\nG1 X54.672 Y95.203 E0.625\nG92 E0.0\nG1 E-5 F3000 ; retract 5mm\nG1 X52.931 Y96.185 F1000 ; wipe\nG1 X50.985 Y97.231 F1000 ; wipe\nG1 X49.018 Y98.238 F1000 ; wipe\nG1 X0 Y109.798 F1000\nG1 E4.8 F1500; de-retract\nG92 E0.0 ; reset extrusion distance\nM221 S{if layer_height<0.075}100{else}95{endif} + +[printer:Anycubic Kossel Pulley (Linear)] +inherits = *common_akossel* +printer_model = AK +printer_variant = 0.4 +printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_Anycubic\nPRINTER_MODEL_AK\nPRINTER_HAS_BOWDEN\n +bed_shape = 89.6575x7.84402,88.6327x15.6283,86.9333x23.2937,84.5723x30.7818,81.5677x38.0356,77.9423x45,73.7237x51.6219,68.944x57.8509,63.6396x63.6396,57.8509x68.944,51.6219x73.7237,45x77.9423,38.0356x81.5677,30.7818x84.5723,23.2937x86.9333,15.6283x88.6327,7.84402x89.6575,5.51091e-15x90,-7.84402x89.6575,-15.6283x88.6327,-23.2937x86.9333,-30.7818x84.5723,-38.0356x81.5677,-45x77.9423,-51.6219x73.7237,-57.8509x68.944,-63.6396x63.6396,-68.944x57.8509,-73.7237x51.6219,-77.9423x45,-81.5677x38.0356,-84.5723x30.7818,-86.9333x23.2937,-88.6327x15.6283,-89.6575x7.84402,-90x1.10218e-14,-89.6575x-7.84402,-88.6327x-15.6283,-86.9333x-23.2937,-84.5723x-30.7818,-81.5677x-38.0356,-77.9423x-45,-73.7237x-51.6219,-68.944x-57.8509,-63.6396x-63.6396,-57.8509x-68.944,-51.6219x-73.7237,-45x-77.9423,-38.0356x-81.5677,-30.7818x-84.5723,-23.2937x-86.9333,-15.6283x-88.6327,-7.84402x-89.6575,-1.65327e-14x-90,7.84402x-89.6575,15.6283x-88.6327,23.2937x-86.9333,30.7818x-84.5723,38.0356x-81.5677,45x-77.9423,51.6219x-73.7237,57.8509x-68.944,63.6396x-63.6396,68.944x-57.8509,73.7237x-51.6219,77.9423x-45,81.5677x-38.0356,84.5723x-30.7818,86.9333x-23.2937,88.6327x-15.6283,89.6575x-7.84402,90x-2.20436e-14 +start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 ; home\nG1 X-39.672 Y69.712 Z0.3 F9000\nG92 E0.0\nG1 F1000\nG1 X-38.457 Y70.397 E0.209\nG1 X-37.043 Y71.157 E0.241\nG1 X-35.614 Y71.889 E0.241\nG1 X-34.171 Y72.591 E0.241\nG1 X-32.714 Y73.265 E0.241\nG1 X-31.244 Y73.909 E0.241\nG1 X-29.761 Y74.523 E0.241\nG1 X-28.266 Y75.108 E0.241\nG1 X-26.759 Y75.662 E0.241\nG1 X-25.242 Y76.185 E0.241\nG1 X-23.714 Y76.678 E0.241\nG1 X-22.177 Y77.14 E0.241\nG1 X-20.63 Y77.571 E0.241\nG1 X-19.076 Y77.971 E0.241\nG1 X-17.514 Y78.34 E0.241\nG1 X-15.944 Y78.677 E0.241\nG1 X-14.368 Y78.982 E0.241\nG1 X-12.786 Y79.255 E0.241\nG1 X-11.199 Y79.497 E0.241\nG1 X-9.608 Y79.706 E0.241\nG1 X-8.013 Y79.884 E0.241\nG1 X-6.414 Y80.029 E0.241\nG1 X-4.813 Y80.142 E0.241\nG1 X-3.21 Y80.223 E0.241\nG1 X-1.605 Y80.271 E0.241\nG1 X0 Y80.287 E0.241\nG1 X1.605 Y80.271 E0.502\nG1 X3.21 Y80.223 E0.502\nG1 X4.813 Y80.142 E0.502\nG1 X6.414 Y80.029 E0.502\nG1 X8.013 Y79.884 E0.502\nG1 X9.608 Y79.706 E0.502\nG1 X11.199 Y79.497 E0.501\nG1 X12.786 Y79.255 E0.502\nG1 X14.368 Y78.982 E0.502\nG1 X15.944 Y78.677 E0.502\nG1 X17.514 Y78.34 E0.502\nG1 X19.076 Y77.971 E0.502\nG1 X20.63 Y77.571 E0.501\nG1 X22.177 Y77.14 E0.502\nG1 X23.714 Y76.678 E0.502\nG1 X25.242 Y76.185 E0.502\nG1 X26.759 Y75.662 E0.501\nG1 X28.266 Y75.108 E0.502\nG1 X29.761 Y74.523 E0.502\nG1 X31.244 Y73.909 E0.502\nG1 X32.714 Y73.265 E0.502\nG1 X34.171 Y72.591 E0.502\nG1 X35.614 Y71.889 E0.501\nG1 X37.043 Y71.157 E0.502\nG1 X38.457 Y70.397 E0.502\nG1 X39.672 Y69.712 E0.436\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} + +## Anycubic MEGA ZERO +## Author: https://github.com/kad +## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4057 + +# Common print preset +[print:*common_mega0*] +avoid_crossing_perimeters = 1 +bridge_angle = 0 +bridge_flow_ratio = 0.7 +bridge_speed = 25 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = +complete_objects = 0 +dont_support_bridges = 1 +elefant_foot_compensation = 0 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeters_first = 0 +external_perimeter_extrusion_width = 0.45 +extra_perimeters = 0 +extruder_clearance_height = 25 +extruder_clearance_radius = 45 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = grid +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 20 +gap_fill_speed = 30 +gcode_comments = 0 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +interface_shells = 0 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +max_volumetric_speed = 0 +min_skirt_length = 4 +notes = +overhangs = 1 +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode +perimeters = 2 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = nearest +single_extruder_multi_material_priming = 1 +skirts = 2 +skirt_distance = 2 +skirt_height = 2 +small_perimeter_speed = 25 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.4 +support_material_interface_extruder = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_enforce_layers = 0 +support_material_contact_distance = 0.15 +support_material_interface_contact_loops = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 40 +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +top_infill_extrusion_width = 0.45 +top_solid_infill_speed = 40 +travel_speed = 100 +wipe_tower = 0 +wipe_tower_bridging = 10 +wipe_tower_rotation_angle = 0 +wipe_tower_width = 60 +wipe_tower_x = 170 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:*0.10mm_mega0*] +inherits = *common_mega0* +perimeter_speed = 40 +external_perimeter_speed = 25 +infill_speed = 50 +solid_infill_speed = 40 +layer_height = 0.10 +perimeters = 3 +top_infill_extrusion_width = 0.4 +bottom_solid_layers = 6 +top_solid_layers = 7 + +[print:*0.20mm_mega0*] +inherits = *common_mega0* +perimeter_speed = 40 +external_perimeter_speed = 25 +infill_speed = 50 +solid_infill_speed = 40 +layer_height = 0.20 +top_infill_extrusion_width = 0.4 +bottom_solid_layers = 4 +top_solid_layers = 5 + +[print:*0.30mm_mega0*] +inherits = *common_mega0* +perimeter_speed = 40 +external_perimeter_speed = 25 +infill_speed = 50 +solid_infill_speed = 40 +layer_height = 0.24 +top_infill_extrusion_width = 0.45 +bottom_solid_layers = 3 +top_solid_layers = 4 + +[print:0.10mm DETAIL @MEGA0] +inherits = *0.10mm_mega0* +travel_speed = 120 +infill_speed = 50 +solid_infill_speed = 40 +top_solid_infill_speed = 30 +support_material_extrusion_width = 0.38 +compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4 + +[print:0.20mm NORMAL @MEGA0] +inherits = *0.20mm_mega0* +travel_speed = 120 +infill_speed = 50 +solid_infill_speed = 40 +top_solid_infill_speed = 30 +support_material_extrusion_width = 0.38 +compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4 + +[print:0.30mm DRAFT @MEGA0] +inherits = *0.30mm_mega0* +travel_speed = 120 +infill_speed = 50 +solid_infill_speed = 40 +top_solid_infill_speed = 30 +support_material_extrusion_width = 0.38 +compatible_printers_condition = printer_model=="MEGA0" and nozzle_diameter[0]==0.4 + +# Common filament preset +[filament:*common_mega0*] +cooling = 0 +compatible_printers = +extrusion_multiplier = 1 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_notes = "" +filament_settings_id = "" +filament_soluble = 0 +min_print_speed = 15 +slowdown_below_layer_time = 20 +compatible_printers_condition = printer_model=="MEGA0" + +[filament:*PLA_mega0*] +inherits = *common_mega0* +bed_temperature = 40 +fan_below_layer_time = 100 +filament_colour = #FF3232 +filament_max_volumetric_speed = 15 +filament_type = PLA +filament_density = 1.24 +filament_cost = 20 +first_layer_bed_temperature = 40 +first_layer_temperature = 215 +fan_always_on = 1 +cooling = 1 +max_fan_speed = 100 +min_fan_speed = 100 +bridge_fan_speed = 100 +disable_fan_first_layers = 1 +temperature = 210 + +[filament:*PET_mega0*] +inherits = *common_mega0* +bed_temperature = 70 +cooling = 1 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_max_volumetric_speed = 8 +filament_type = PETG +filament_density = 1.27 +filament_cost = 30 +first_layer_bed_temperature =70 +first_layer_temperature = 240 +fan_always_on = 1 +max_fan_speed = 50 +min_fan_speed = 20 +bridge_fan_speed = 100 +temperature = 240 + +[filament:*ABS_mega0*] +inherits = *common_mega0* +bed_temperature = 100 +cooling = 0 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_max_volumetric_speed = 11 +filament_type = ABS +filament_density = 1.04 +filament_cost = 20 +first_layer_bed_temperature = 100 +first_layer_temperature = 245 +fan_always_on = 0 +max_fan_speed = 0 +min_fan_speed = 0 +bridge_fan_speed = 30 +top_fan_speed = 0 +temperature = 245 + +[filament:Generic PLA @MEGA0] +inherits = *PLA_mega0* +filament_vendor = Generic + +[filament:Generic PETG @MEGA0] +inherits = *PET_mega0* +filament_vendor = Generic + +[filament:Generic ABS @MEGA0] +inherits = *ABS_mega0* +filament_vendor = Generic + +[filament:Anycubic PLA @MEGA0] +inherits = *PLA_mega0* +filament_vendor = Anycubic +temperature = 190 +first_layer_temperature = 195 +filament_cost = 24.99 +filament_density = 1.25 + +[filament:Prusament PLA @MEGA0] +inherits = *PLA_mega0* +filament_vendor = Prusa Polymers +temperature = 215 +bed_temperature = 40 +first_layer_temperature = 215 +filament_cost = 24.99 +filament_density = 1.24 + +[filament:Prusament PETG @MEGA0] +inherits = *PET_mega0* +filament_vendor = Prusa Polymers +temperature = 245 +bed_temperature = 70 +first_layer_temperature = 245 +filament_cost = 24.99 +filament_density = 1.27 + +# Common printer preset +[printer:*common_mega0*] +printer_technology = FFF +bed_shape = 0x0,220x0,220x220,0x220 +before_layer_gcode = ; BEFORE_LAYER_CHANGE [layer_num] @ [layer_z]mm\nG92 E0 +between_objects_gcode = +deretract_speed = 0 +extruder_colour = #FFFF00 +extruder_offset = 0x0 +gcode_flavor = marlin +silent_mode = 0 +remaining_times = 0 +machine_max_acceleration_e = 10000 +machine_max_acceleration_extruding = 2000 +machine_max_acceleration_retracting = 1500 +machine_max_acceleration_x = 3000 +machine_max_acceleration_y = 3000 +machine_max_acceleration_z = 500 +machine_max_feedrate_e = 120 +machine_max_feedrate_x = 500 +machine_max_feedrate_y = 500 +machine_max_feedrate_z = 12 +machine_max_jerk_e = 2.5 +machine_max_jerk_x = 20 +machine_max_jerk_y = 20 +machine_max_jerk_z = 0.4 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +layer_gcode = ; AFTER_LAYER_CHANGE [layer_num] @ [layer_z]mm +max_layer_height = 0.3 +min_layer_height = 0.1 +max_print_height = 200 +nozzle_diameter = 0.4 +printer_notes = +printer_settings_id = +retract_before_travel = 1 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 6 +retract_length_toolchange = 1 +retract_lift = 0 +retract_lift_above = 0 +retract_lift_below = 0 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 30 +single_extruder_multi_material = 0 +start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n +end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM140 S0 ; turn off heatbed\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 1 +z_offset = 0 +printer_model = +default_print_profile = +default_filament_profile = + +[printer:Anycubic Mega Zero] +inherits = *common_mega0* +printer_model = MEGA0 +printer_variant = 0.4 +max_layer_height = 0.3 +min_layer_height = 0.1 +printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_MEGA0 +bed_shape = 0x0,220x0,220x220,0x220 +max_print_height = 250 +machine_max_acceleration_e = 5000 +machine_max_acceleration_extruding = 500 +machine_max_acceleration_retracting = 500 +machine_max_acceleration_x = 500 +machine_max_acceleration_y = 500 +machine_max_acceleration_z = 100 +machine_max_feedrate_e = 25 +machine_max_feedrate_x = 500 +machine_max_feedrate_y = 500 +machine_max_feedrate_z = 5 +machine_max_jerk_e = 5 +machine_max_jerk_x = 10 +machine_max_jerk_y = 10 +machine_max_jerk_z = 0.4 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +nozzle_diameter = 0.4 +retract_before_travel = 2 +retract_layer_change = 0 +retract_length = 7 +retract_speed = 30 +retract_lift = 0.2 +deretract_speed = 30 +retract_before_wipe = 70% +default_print_profile = 0.20mm NORMAL @MEGA0 +default_filament_profile = Anycubic PLA @MEGA0 +start_gcode = G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nM117 Homing X/Y ...\nG28 X0 Y0 ;move X/Y to min endstops\nM117 Homing Z ...\nG28 Z0 ;move Z to min endstops\nG1 Z15.0 F240 ;move the platform down 15mm\nM117 Heating ...\nM104 S[first_layer_temperature]\n ; set extruder temp\nM109 S[first_layer_temperature]\n ; wait for extruder temp\nM117 Start cleaning ...\nG92 E0 ;zero the extruded length\nG1 F200 E10 ;extrude 10mm of feed stock\nG92 E0 ;zero the extruded length again\nM117 Intro line ...\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z[first_layer_height] F5000.0 ; Move to start position\nG1 X0.1 Y200.0 Z[first_layer_height] F1500.0 E15 ; Draw the first line\nG1 X0.4 Y200.0 Z[first_layer_height] F5000.0 ; Move to side a little\nG1 X0.4 Y20 Z0.3[first_layer_height] F1500.0 E30 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 E-1 F500 ; Retract filiment by 1 mm\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.3 F240 ; Move over to prevent blob squish\nG92 E0 ; Reset Extruder\nM117 Printing...\n +end_gcode = M117 Cooling down...\nM104 S0 ; turn off extruder\nM107 ; Fan off\nM84 ; disable motors\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z+0.5 E-5 ;X-20 Y-20 F240 ;move Z up a bit and retract filament even more\nG28 X0 ;move X to min endstops, so the head is out of the way\nG90 ;Absolute positionning\nG1 Y200 F3000 ;Present print\nM84 ;steppers off\nM300 P300 S4000\nM117 Finished.\n + +## Anycubic i3 Mega and i3 Mega S +## Author: https://github.com/Igami +## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4619 + +[print:*common_mega*] +bottom_solid_min_thickness = 0.5 +bridge_acceleration = 1000 +bridge_flow_ratio = 0.95 +bridge_speed = 25 +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ and nozzle_diameter[0]==0.4 +default_acceleration = 1000 +ensure_vertical_shell_thickness = 1 +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 40 +extruder_clearance_height = 35 +extruder_clearance_radius = 60 +extrusion_width = 0.45 +fill_density = 15% +fill_pattern = gyroid +first_layer_acceleration = 800 +first_layer_extrusion_width = 0.42 +first_layer_height = 0.2 +first_layer_speed = 20 +gap_fill_speed = 40 +gcode_comments = 0 +gcode_label_objects = 1 +infill_acceleration = 1000 +infill_anchor = 2.5 +infill_anchor_max = 12 +infill_extrusion_width = 0.45 +max_print_speed = 100 +min_skirt_length = 4 +only_retract_when_crossing_perimeters = 0 +output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode +perimeter_acceleration = 800 +perimeter_extrusion_width = 0.45 +perimeter_speed = 50 +perimeters = 2 +seam_position = nearest +skirt_distance = 2 +skirt_height = 3 +skirts = 1 +small_perimeter_speed = 25 +solid_infill_below_area = 0 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 50 +support_material = 0 +support_material_buildplate_only = 0 +support_material_contact_distance = 0.1 +support_material_extrusion_width = 0.35 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_speed = 80% +support_material_spacing = 2 +support_material_speed = 50 +support_material_threshold = 50 +support_material_xy_spacing = 60% +thin_walls = 0 +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 40 +top_solid_min_thickness = 0.7 +travel_speed = 180 + +# XXXXXXXXXXXXXXXXXXXX +# XXX--- 0.15mm ---XXX +# XXXXXXXXXXXXXXXXXXXX + +[print:*0.15mm_mega*] +inherits = *common_mega* +bottom_solid_layers = 5 +bridge_flow_ratio = 1 +infill_speed = 60 +layer_height = 0.15 +top_solid_layers = 7 + +[print:0.15mm QUALITY @MEGA] +inherits = *0.15mm_mega* + +# XXXXXXXXXXXXXXXXXXXX +# XXX--- 0.20mm ---XXX +# XXXXXXXXXXXXXXXXXXXX + +[print:*0.20mm_mega*] +inherits = *common_mega* +bottom_solid_layers = 4 +infill_speed = 60 +layer_height = 0.2 +top_solid_layers = 5 + +[print:0.20mm QUALITY @MEGA] +inherits = *0.20mm_mega* + +# XXXXXXXXXXXXXXXXXXXX +# XXX--- 0.30mm ---XXX +# XXXXXXXXXXXXXXXXXXXX + +[print:*0.30mm_mega*] +inherits = *common_mega* +bottom_solid_layers = 4 +external_perimeter_extrusion_width = 0.6 +external_perimeter_speed = 35 +extrusion_width = 0.5 +fill_pattern = cubic +infill_extrusion_width = 0.5 +infill_speed = 85 +layer_height = 0.3 +perimeter_extrusion_width = 0.5 +small_perimeter_speed = 30 +solid_infill_extrusion_width = 0.5 +support_material_extrusion_width = 0.38 +support_material_speed = 45 +top_solid_layers = 4 + +[print:0.30mm DRAFT @MEGA] +inherits = *0.30mm_mega* + +# XXXXXXXXXXXXXXXXXXXXXX +# XXX--- filament ---XXX +# XXXXXXXXXXXXXXXXXXXXXX + +[filament:*common_mega*] +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ +end_filament_gcode = "; Filament-specific end gcode" +fan_always_on = 1 +fan_below_layer_time = 100 +filament_vendor = Generic +min_print_speed = 15 +slowdown_below_layer_time = 20 + +[filament:*ABS_mega*] + inherits = *common_mega* + bed_temperature = 110 + bridge_fan_speed = 25 + cooling = 0 + fan_always_on = 0 + fan_below_layer_time = 20 + filament_colour = #3A80CA + filament_cost = 27.82 + filament_density = 1.04 + filament_max_volumetric_speed = 11 + filament_ramming_parameters = "120 100 5.70968 6.03226 7 8.25806 9 9.19355 9.3871 9.77419 10.129 10.3226 10.4516 10.5161| 0.05 5.69677 0.45 6.15484 0.95 8.76774 1.45 9.20323 1.95 9.95806 2.45 10.3871 2.95 10.5677 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" + filament_type = ABS + first_layer_bed_temperature = 105 + first_layer_temperature = 255 + max_fan_speed = 30 + min_fan_speed = 20 + temperature = 255 + +[filament:Generic ABS @MEGA] +inherits = *ABS_mega* + +[filament:*FLEX_mega*] +inherits = *common_mega* +bed_temperature = 50 +bridge_fan_speed = 80 +cooling = 0 +extrusion_multiplier = 1.15 +fan_always_on = 0 +filament_colour = #008000 +filament_cost = 82.00 +filament_density = 1.22 +filament_deretract_speed = 25 +filament_max_volumetric_speed = 1.2 +filament_retract_length = 0.8 +filament_type = FLEX +first_layer_bed_temperature = 55 +first_layer_temperature = 240 +max_fan_speed = 90 +min_fan_speed = 70 +temperature = 240 + +[filament:Generic FLEX @MEGA] +inherits = *FLEX_mega* + +[filament:SainSmart TPU @MEGA] +inherits = *FLEX_mega* +filament_vendor = SainSmart +bed_temperature = 50 +bridge_fan_speed = 100 +cooling = 1 +disable_fan_first_layers = 4 +filament_cost = 39.99 +filament_density = 1.21 +filament_deretract_speed = 15 +filament_max_volumetric_speed = 1.8 +filament_notes = "SainSmart TPU gains popularity among 3D Printing community for its balance of rigidity and flexibility. In addition, with a 95A Shore Hardness and improved bed adhesion, it is easier to print even with a stock elementary 3D Printer like the Creality Ender 3. SainSmart TPU will not disappoint if you are looking for flexible filament. From drone parts, phone cases, to small toys, all can be printed with ease.\n\nhttps://www.sainsmart.com/collections/tpu-filament/products/all-colors-tpu-flexible-filament-1-75mm-0-8kg-1-76lb" +filament_retract_before_travel = 5 +filament_retract_length = 4 +filament_retract_speed = 40 +filament_unloading_speed = 90 +first_layer_bed_temperature = 55 +first_layer_temperature = 235 +full_fan_speed_layer = 6 +max_fan_speed = 80 +min_fan_speed = 80 +slowdown_below_layer_time = 10 +temperature = 235 + +[filament:*PETG_mega*] +inherits = *common_mega* +bed_temperature = 90 +bridge_fan_speed = 50 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_cost = 27.82 +filament_density = 1.27 +filament_max_volumetric_speed = 8 +filament_type = PETG +first_layer_bed_temperature = 90 +first_layer_temperature = 230 +max_fan_speed = 50 +min_fan_speed = 30 +temperature = 240 + +[filament:Generic PETG @MEGA] +inherits = *PETG_mega* + +[filament:ColorFabb XT-CF20 @MEGA] +inherits = *PETG_mega* +compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ +extrusion_multiplier = 1.05 +filament_colour = #804040 +filament_cost = 66.60 +filament_density = 1.35 +filament_deretract_speed = 25 +filament_max_volumetric_speed = 2 +filament_notes = "Based on colorFabb_XT, XT-CF20 is a carbon fiber composite material. Loaded with no less than 20% specially sourced carbon fibers we have developed a very stiff and tough 3D printing filament made for functional parts. It is truly a professional printers go-to material, especially for users looking for high melt strength, high melt viscosity and good dimensional accuracy and stability.\n\nhttps://colorfabb.com/xt-cf20" +filament_retract_before_travel = 1 +filament_retract_length = 1.4 +filament_retract_speed = 40 +filament_spool_weight = 236 +filament_vendor = ColorFabb +first_layer_temperature = 260 +full_fan_speed_layer = 5 +slowdown_below_layer_time = 15 +temperature = 260 + +[filament:ERYONE PETG @MEGA] +inherits = *PETG_mega* +filament_vendor = ERYONE +filament_cost = 20.99 +filament_notes = "https://eryone.com/petg/show/10.html" + +[filament:FormFutura HDglass @MEGA] +inherits = *PETG_mega* +filament_vendor = FormFutura +filament_cost = 46.65 +filament_notes = "HDglass is a high performance PETG type of 3D printer with unsurpassed 3D printing properties and improved mechanical strength, flexibility, toughness and heat resistance.\n\nhttps://www.formfutura.com/shop/product/hdglass-2812" + +[filament:FormFutura ReForm rPET @MEGA] +inherits = *PETG_mega* +filament_vendor = FormFutura +filament_cost = 26.65 +filament_notes = "ReForm rPET is a recycled PETG type of 3D printer filament that is made from post-industrial waste streams of a nearby located plastic bottle manufacturer.\n\nhttps://www.formfutura.com/shop/product/reform-rpet-2836" +filament_spool_weight = 176 + +[filament:Janbex transparent PETG @MEGA] +inherits = *PETG_mega* +filament_vendor = Janbex +filament_cost = 31.99 +filament_spool_weight = 222 +first_layer_temperature = 215 +min_fan_speed = 100 +temperature = 210 + +[filament:DAS FILAMENT PETG @MEGA] +inherits = *PETG_mega* +filament_vendor = DAS FILAMENT +bed_temperature = 75 +first_layer_bed_temperature = 75 +first_layer_temperature = 220 +temperature = 225 + +[filament:*PLA_mega*] +inherits = *common_mega* +bed_temperature = 60 +disable_fan_first_layers = 1 +filament_colour = #FF3232 +filament_cost = 25.40 +filament_density = 1.24 +filament_max_volumetric_speed = 10 +first_layer_bed_temperature = 65 +first_layer_temperature = 215 +min_fan_speed = 100 +temperature = 210 + +[filament:Generic PLA @MEGA] +inherits = *PLA_mega* + +[filament:3Dmensionals PLA @MEGA] +inherits = *PLA_mega* +filament_vendor = 3Dmensionals +filament_cost = 22.90 +filament_notes = "Das 3DFilaments - PLA von 3Dmensionals ist ein sehr leicht zu druckendes 3D-Drucker Filament. Dabei handelt es sich um ein etwas härteres PLA mit einer exzellenten thermischen Stabilität. Das Filament zeichnet sich vor allem durch verzugfreies 3D-Drucken aus und weist minimale bis keine Verformung nach dem Abkühlen auf. Daher ist es besonders gut für den Druck größerer Objekte geeignet. Zudem bietet 3DFilaments - PLA über die gesamte Fadenläge eine hervorragende Durchmesser- und Rundheitstoleranz.\n\nhttps://www.3dmensionals.de/3dfilaments?number=PSU3DM001V" + +[filament:3D Warhorse PLA @MEGA] +inherits = *PLA_mega* +filament_vendor = 3D Warhorse +filament_cost = 19.99 + +[filament:AMOLEN wood PLA] +inherits = *PLA_mega* +filament_vendor = AMOLEN +compatible_printers_condition = nozzle_diameter[0]>0.35 and printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_I3_MEGA.*/ +extrusion_multiplier = 1.1 +filament_colour = #DFC287 +filament_cost = 33.99 +filament_density = 1.23 +filament_max_volumetric_speed = 9 +filament_notes = "https://amolen.com/collections/wood/products/amolen-pla-filament-1-75mm-wood-color-3d-printer-filament-1kg2-2lb" + +[filament:FormFutura EasyFil PLA @MEGA] +inherits = *PLA_mega* +filament_vendor = FormFutura +filament_cost = 39.93 +filament_notes = "EasyFil PLA is an easy to print PLA type of 3D printer filament that is available in a wide variety of colors. Its improved flowing behavior make 3D printed layers flow more into each other.\n\nhttps://www.formfutura.com/shop/product/easyfil-pla-2801" + +[filament:FormFutura ReForm rPLA @MEGA] +inherits = *PLA_mega* +filament_vendor = FormFutura +filament_cost = 26.65 +filament_notes = "ReForm is a sustainable initiative within Formfutura to efficiently manage residual extrusion waste streams and re-use them into high-end upcycled filaments. The ideology behind ReForm is to a make 3D printing more sustainable – without having to make compromises on material properties – and yet keep it affordable.\n\nhttps://www.formfutura.com/shop/product/reform-rpla-2838" + +[filament:GIANTARM PLA @MEGA] +inherits = *PLA_mega* +filament_vendor = GIANTARM +filament_cost = 24.99 + +[filament:Prusament PLA @MEGA] +inherits = *PLA_mega* +filament_vendor = Prusa Polymers +filament_cost = 30.24 +filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa" +filament_spool_weight = 201 +temperature = 215 + +[filament:Verbatim PLA @MEGA] +inherits = *PLA_mega* +filament_vendor = Verbatim +filament_cost = 23.88 + +[printer:*common_mega*] +printer_technology = FFF +bed_shape = 0x0,210x0,210x210,0x210 +before_layer_gcode = ;BEFORE_LAYER_CHANGE\nG92 E0.0\n;[layer_z] +default_filament_profile = Generic PLA @MEGA +default_print_profile = 0.15mm QUALITY @MEGA +deretract_speed = 50 +end_gcode = G1 E-1.0 F2100 ; retract\nG92 E0.0\nG1{if max_layer_z < max_print_height} Z{z_offset+min(max_layer_z+30, max_print_height)}{endif} E-34.0 F720 ; move print head up & retract filament\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y105 F3000 ; park print head\nM84 ; disable motors +extruder_colour = #808080 +gcode_flavor = marlin +layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] +max_layer_height = 0.36 +max_print_height = 205 +remaining_times = 1 +retract_before_travel = 1.5 +retract_before_wipe = 60% +retract_layer_change = 1 +retract_length = 6 +retract_lift = 0.075 +retract_lift_below = 204 +retract_speed = 40 +silent_mode = 0 +start_gcode = G90 ; use absolute coordinates\nM83 ; extruder relative mode\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 ; home all\nG1 Y1.0 Z0.3 F1000 ; move print head up\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG92 E0.0\n; initial load\nG1 X205.0 E19 F1000\nG1 Y1.6\nG1 X5.0 E19 F1000\nG92 E0.0\n; intro line\nG1 Y2.0 Z0.2 F1000\nG1 X65.0 E9.0 F1000\nG1 X105.0 E12.5 F1000\nG92 E0.0 +thumbnails = 16x16,220x124 +use_relative_e_distances = 1 +wipe = 1 +machine_max_acceleration_e = 10000 +machine_max_acceleration_extruding = 1250 +machine_max_acceleration_retracting = 1250 +machine_max_acceleration_x = 3000 +machine_max_acceleration_y = 2000 +machine_max_acceleration_z = 60 +machine_max_feedrate_e = 60 +machine_max_feedrate_x = 500 +machine_max_feedrate_y = 500 +machine_max_feedrate_z = 6 +machine_max_jerk_e = 5 +machine_max_jerk_x = 10 +machine_max_jerk_y = 10 +machine_max_jerk_z = 0.4 + +[printer:Anycubic i3 Mega] +inherits = *common_mega* +printer_model = I3MEGA +printer_variant = 0.4 +printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA\nPRINTER_HAS_BOWDEN + +[printer:Anycubic i3 Mega S] +inherits = *common_mega* +printer_model = I3MEGAS +printer_variant = 0.4 +printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_I3_MEGA_S\nPRINTER_HAS_BOWDEN +machine_max_feedrate_e = 30 +machine_max_feedrate_z = 8 + + +## Anycubic PREDATOR +## Author: https://github.com/tillverka3d +## Initial PR: https://github.com/prusa3d/PrusaSlicer/pull/4960 + +######################################### +###### begin common print presets ####### +######################################### + +# Common print preset +[print:*common predator*] +spiral_vase = 0 +top_solid_min_thickness = 0.8 +bottom_solid_min_thickness = 0.6 +extra_perimeters = 0 +ensure_vertical_shell_thickness = 1 +avoid_crossing_perimeters = 0 +thin_walls = 0 +overhangs = 1 +seam_position = nearest +external_perimeters_first = 0 +fill_density = 20% +external_fill_pattern = rectilinear +infill_every_layers = 1 +infill_only_where_needed = 0 +solid_infill_every_layers = 0 +fill_angle = 45 +solid_infill_below_area = 20 +bridge_angle = 0 +only_retract_when_crossing_perimeters = 0 +infill_first = 0 +skirts = 1 +skirt_distance = 4 +skirt_height = 1 +min_skirt_length = 8 +brim_width = 0 +support_material = 0 +support_material_auto = 1 +support_material_threshold = 50 +support_material_enforce_layers = 0 +raft_layers = 0 +support_material_contact_distance = 0.1 +support_material_pattern = rectilinear +support_material_with_sheath = 0 +support_material_spacing = 2 +support_material_angle = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_interface_contact_loops = 0 +support_material_buildplate_only = 0 +support_material_xy_spacing = 60% +dont_support_bridges = 1 +support_material_synchronize_layers = 0 +travel_speed = 94 +first_layer_speed = 15 +perimeter_acceleration = 0 +infill_acceleration = 0 +bridge_acceleration = 0 +first_layer_acceleration = 0 +default_acceleration = 0 +max_volumetric_speed = 15 +perimeter_extruder = 1 +infill_extruder = 1 +solid_infill_extruder = 1 +support_material_extruder = 0 +support_material_interface_extruder = 0 +ooze_prevention = 0 +standby_temperature_delta = -5 +wipe_tower = 0 +wipe_tower_x = 170 +wipe_tower_y = 140 +wipe_tower_width = 60 +wipe_tower_rotation_angle = 0 +wipe_tower_bridging = 10 +interface_shells = 0 +bridge_flow_ratio = 0.8 +resolution = 0 +xy_size_compensation = 0 +elefant_foot_compensation = 0.2 +clip_multipart_objects = 1 +complete_objects = 0 +extruder_clearance_radius = 45 +extruder_clearance_height = 25 +gcode_comments = 0 +output_filename_format = {input_filename_base}.gcode +post_process = +notes = +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +print_settings_id = + +# Common print preset +[print:*common predator 0.4 nozzle*] +inherits = *common predator* +first_layer_height = 0.16 +infill_overlap = 25% +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.4 + +# Common print preset +[print:*common predator 0.6 nozzle*] +inherits = *common predator* +first_layer_height = 0.24 +infill_overlap = 27% +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.6 + +# Common print preset +[print:*common predator 0.8 nozzle*] +inherits = *common predator* +first_layer_height = 0.32 +infill_overlap = 30% +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ and printer_notes=~/.*PRINTER_HAS_BOWDEN.*/ and nozzle_diameter[0]==0.8 + +# Common print preset +[print:*common predator quality*] +perimeter_speed = 50 +small_perimeter_speed = 15 +external_perimeter_speed = 70% +infill_speed = 65 +solid_infill_speed = 85% +top_solid_infill_speed = 85% +support_material_speed = 30 +support_material_interface_speed = 85% +bridge_speed = 30 +gap_fill_speed = 40 +ironing_speed = 15 + +# Common print preset +[print:*common predator speed*] +perimeter_speed = 70 +small_perimeter_speed = 15 +external_perimeter_speed = 70% +infill_speed = 85 +solid_infill_speed = 85% +top_solid_infill_speed = 85% +support_material_speed = 30 +support_material_interface_speed = 85% +bridge_speed = 30 +gap_fill_speed = 40 +ironing_speed = 15 + +# Common print preset +[print:*common predator 0.4 nozzle detailed*] +inherits = *common predator 0.4 nozzle* +extrusion_width = 0.42 +first_layer_extrusion_width = 0.41 +perimeter_extrusion_width = 0.42 +external_perimeter_extrusion_width = 0.42 +infill_extrusion_width = 0.4 +solid_infill_extrusion_width = 0.4 +top_infill_extrusion_width = 0.4 +support_material_extrusion_width = 0.38 + +# Common print preset +[print:*common predator 0.4 nozzle coarse*] +inherits = *common predator 0.4 nozzle* +extrusion_width = 0.44 +first_layer_extrusion_width = 0.42 +perimeter_extrusion_width = 0.5 +external_perimeter_extrusion_width = 0.5 +infill_extrusion_width = 0.5 +solid_infill_extrusion_width = 0.5 +top_infill_extrusion_width = 0.4 +support_material_extrusion_width = 0.38 + +# Common print preset +[print:*common predator 0.6 nozzle detailed*] +inherits = *common predator 0.6 nozzle* +extrusion_width = 0.64 +first_layer_extrusion_width = 0.62 +perimeter_extrusion_width = 0.64 +external_perimeter_extrusion_width = 0.64 +infill_extrusion_width = 0.6 +solid_infill_extrusion_width = 0.6 +top_infill_extrusion_width = 0.6 +support_material_extrusion_width = 0.56 + +# Common print preset +[print:*common predator 0.6 nozzle coarse*] +inherits = *common predator 0.6 nozzle* +extrusion_width = 0.67 +first_layer_extrusion_width = 0.64 +perimeter_extrusion_width = 0.7 +external_perimeter_extrusion_width = 0.7 +infill_extrusion_width = 0.7 +solid_infill_extrusion_width = 0.7 +top_infill_extrusion_width = 0.6 +support_material_extrusion_width = 0.56 + +# Common print preset +[print:*common predator 0.8 nozzle detailed*] +inherits = *common predator 0.8 nozzle* +extrusion_width = 0.84 +first_layer_extrusion_width = 0.82 +perimeter_extrusion_width = 0.84 +external_perimeter_extrusion_width = 0.84 +infill_extrusion_width = 0.8 +solid_infill_extrusion_width = 0.8 +top_infill_extrusion_width = 0.8 +support_material_extrusion_width = 0.72 + +# Common print preset +[print:*common predator 0.8 nozzle coarse*] +inherits = *common predator 0.8 nozzle* +extrusion_width = 0.87 +first_layer_extrusion_width = 0.84 +perimeter_extrusion_width = 0.9 +external_perimeter_extrusion_width = 0.9 +infill_extrusion_width = 0.9 +solid_infill_extrusion_width = 0.9 +top_infill_extrusion_width = 0.8 +support_material_extrusion_width = 0.72 + +######################################### +####### end common print presets ######## +######################################### + +######################################### +########## begin print presets ########## +######################################### + +[print:0.08mm 0.4 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.4 nozzle detailed*; *common predator quality* +layer_height = 0.08 +max_print_speed = 50 +perimeters = 3 +fill_pattern = grid + +[print:0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.4 nozzle detailed*; *common predator quality* +layer_height = 0.16 +max_print_speed = 60 +perimeters = 3 +fill_pattern = grid + +[print:0.16mm 0.4 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.4 nozzle coarse*; *common predator quality* +layer_height = 0.16 +max_print_speed = 60 +perimeters = 3 +fill_pattern = grid + +[print:0.24mm 0.4 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.4 nozzle detailed*; *common predator quality* +layer_height = 0.24 +max_print_speed = 70 +perimeters = 3 +fill_pattern = grid + +[print:0.24mm 0.4 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.4 nozzle coarse*; *common predator quality* +layer_height = 0.24 +max_print_speed = 70 +perimeters = 3 +fill_pattern = grid + +[print:0.32mm 0.4 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.4 nozzle detailed*; *common predator quality* +layer_height = 0.32 +max_print_speed = 70 +perimeters = 3 +fill_pattern = grid + +[print:0.32mm 0.4 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.4 nozzle coarse*; *common predator quality* +layer_height = 0.32 +max_print_speed = 70 +perimeters = 3 +fill_pattern = grid + +[print:0.16mm 0.6 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator quality* +layer_height = 0.16 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.16mm 0.6 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator speed* +layer_height = 0.16 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.16mm 0.6 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator quality* +layer_height = 0.16 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.16mm 0.6 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator speed* +layer_height = 0.16 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.6 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator quality* +layer_height = 0.24 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.6 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator speed* +layer_height = 0.24 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.6 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator quality* +layer_height = 0.24 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.6 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator speed* +layer_height = 0.24 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.6 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator quality* +layer_height = 0.32 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.6 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator speed* +layer_height = 0.32 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.6 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator quality* +layer_height = 0.32 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.6 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator speed* +layer_height = 0.32 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.6 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator quality* +layer_height = 0.4 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.6 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle detailed*; *common predator speed* +layer_height = 0.4 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.6 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator quality* +layer_height = 0.4 +max_print_speed = 70 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.6 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.6 nozzle coarse*; *common predator speed* +layer_height = 0.4 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator quality* +layer_height = 0.24 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.8 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator speed* +layer_height = 0.24 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.8 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator quality* +layer_height = 0.24 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.24mm 0.8 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator speed* +layer_height = 0.24 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.8 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator quality* +layer_height = 0.32 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.8 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator speed* +layer_height = 0.32 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.8 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator quality* +layer_height = 0.32 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.32mm 0.8 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator speed* +layer_height = 0.32 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.8 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator quality* +layer_height = 0.4 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.8 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator speed* +layer_height = 0.4 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.8 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator quality* +layer_height = 0.4 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.4mm 0.8 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator speed* +layer_height = 0.4 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +[print:0.48mm 0.8 nozzle DETAILED QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator quality* +layer_height = 0.48 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.48mm 0.8 nozzle DETAILED SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle detailed*; *common predator speed* +layer_height = 0.48 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +[print:0.48mm 0.8 nozzle COARSE QUALITY @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator quality* +layer_height = 0.48 +max_print_speed = 80 +perimeters = 2 +fill_pattern = gyroid + +[print:0.48mm 0.8 nozzle COARSE SPEED @PREDATOR] +inherits = *common predator 0.8 nozzle coarse*; *common predator speed* +layer_height = 0.48 +max_print_speed = 90 +perimeters = 2 +fill_pattern = gyroid + +######################################### +########### end print presets ########### +######################################### + +######################################### +######## begin filament presets ######### +######################################### + +# Common filament preset +[filament:*common predator*] +cooling = 0 +compatible_printers = +extrusion_multiplier = 1 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_notes = "" +filament_settings_id = "" +filament_soluble = 0 +min_print_speed = 15 +slowdown_below_layer_time = 20 +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_ANYCUBIC.*/ and printer_notes=~/.*PRINTER_MODEL_PREDATOR.*/ + +[filament:*PLA predator*] +inherits = *common predator* +bed_temperature = 60 +fan_below_layer_time = 100 +filament_colour = #FF3232 +filament_max_volumetric_speed = 10 +filament_type = PLA +filament_density = 1.24 +filament_cost = 20 +first_layer_bed_temperature = 60 +first_layer_temperature = 200 +fan_always_on = 1 +cooling = 1 +max_fan_speed = 100 +min_fan_speed = 100 +bridge_fan_speed = 100 +disable_fan_first_layers = 1 +temperature = 200 + +[filament:*PET predator*] +inherits = *common predator* +bed_temperature = 70 +cooling = 1 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #FF8000 +filament_max_volumetric_speed = 8 +filament_type = PETG +filament_density = 1.27 +filament_cost = 30 +first_layer_bed_temperature =70 +first_layer_temperature = 240 +fan_always_on = 1 +max_fan_speed = 50 +min_fan_speed = 20 +bridge_fan_speed = 100 +temperature = 240 + +[filament:*ABS predator*] +inherits = *common predator* +bed_temperature = 100 +cooling = 0 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #3A80CA +filament_max_volumetric_speed = 10 +filament_type = ABS +filament_density = 1.04 +filament_cost = 20 +first_layer_bed_temperature = 100 +first_layer_temperature = 245 +fan_always_on = 0 +max_fan_speed = 0 +min_fan_speed = 0 +bridge_fan_speed = 30 +top_fan_speed = 0 +temperature = 245 + +[filament:Generic PLA @PREDATOR] +inherits = *PLA predator* +filament_vendor = Generic + +[filament:Generic PETG @PREDATOR] +inherits = *PET predator* +filament_vendor = Generic + +[filament:Generic ABS @PREDATOR] +inherits = *ABS predator* +filament_vendor = Generic + +######################################### +######### end filament presets ########## +######################################### + +######################################### +######### begin printer presets ######### +######################################### + +# Anycubic predator common printer preset +[printer:*common predator*] +printer_vendor = Anycubic +printer_model = Predator +printer_technology = FFF +printer_variant = 0.4 +thumbnails = 16x16,220x124 +bed_shape = 188.779x16.516,186.621x32.9063,183.043x49.0462,178.072x64.8128,171.745x80.0862,164.112x94.75,155.229x108.693,145.165x121.808,133.997x133.997,121.808x145.165,108.693x155.229,94.75x164.112,80.0862x171.745,64.8128x178.072,49.0462x183.043,32.9063x186.621,16.516x188.779,1.16035e-14x189.5,-16.516x188.779,-32.9063x186.621,-49.0462x183.043,-64.8128x178.072,-80.0862x171.745,-94.75x164.112,-108.693x155.229,-121.808x145.165,-133.997x133.997,-145.165x121.808,-155.229x108.693,-164.112x94.75,-171.745x80.0862,-178.072x64.8128,-183.043x49.0462,-186.621x32.9063,-188.779x16.516,-189.5x2.32071e-14,-188.779x-16.516,-186.621x-32.9063,-183.043x-49.0462,-178.072x-64.8128,-171.745x-80.0862,-164.112x-94.75,-155.229x-108.693,-145.165x-121.808,-133.997x-133.997,-121.808x-145.165,-108.693x-155.229,-94.75x-164.112,-80.0862x-171.745,-64.8128x-178.072,-49.0462x-183.043,-32.9063x-186.621,-16.516x-188.779,-3.48106e-14x-189.5,16.516x-188.779,32.9063x-186.621,49.0462x-183.043,64.8128x-178.072,80.0862x-171.745,94.75x-164.112,108.693x-155.229,121.808x-145.165,133.997x-133.997,145.165x-121.808,155.229x-108.693,164.112x-94.75,171.745x-80.0862,178.072x-64.8128,183.043x-49.0462,186.621x-32.9063,188.779x-16.516,189.5x-4.64141e-14 +max_print_height = 445 +z_offset = 0 +single_extruder_multi_material = 0 +gcode_flavor = reprap +silent_mode = 0 +remaining_times = 0 +use_relative_e_distances = 0 +use_firmware_retraction = 0 +use_volumetric_e = 0 +variable_layer_height = 1 +start_gcode = ; start_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; set metric values\n\nG21\n\n; use absolute positioning\n\nG90\n\n; set extruder to absolute mode\n\nM82\n\n; start with fan off\n\nM107\n\n; set temps\n\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\n\n; home xy\n\nG28 X0 Y0\n\n; home z\n\nG28 Z0\n\n; move the head down to Z 94mm\n\nG1 Z94.0 F2394\n\n; set and wait for temps\n\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\n\n; zero the extruded length\n\nG92 E0\n\n; extrude 3mm of feed stock\n\nG1 F200 E3\n\n; zero the extruded length again\n\nG92 E0\n\n; set speed\n\nG1 F{travel_speed}\n\n; print preskirt\n\nG92 E0\nG1 E3.94000 F2520.00000\n\nG1 X125.464 Y-139.310\nG1 Z0.329 F3994.000\n\nG1 F994.000\n\nG1 X125.464 Y-139.310 E4.19679\nG1 X130.218 Y-134.876 E4.70359\nG1 X132.569 Y-132.567 E4.96053\nG1 X137.099 Y-127.877 E5.46890\nG1 X139.325 Y-125.447 E5.72585\nG1 X141.507 Y-122.981 E5.98254\nG1 X145.685 Y-118.002 E6.48934\nG1 X149.741 Y-112.810 E7.00296\nG1 X153.561 Y-107.552 E7.50975\nG1 X155.440 Y-104.819 E7.76827\nG1 X158.980 Y-99.367 E8.27506\nG1 X160.702 Y-96.558 E8.53201\nG1 X163.962 Y-90.911 E9.04038\nG1 X165.535 Y-88.015 E9.29732\nG1 X168.496 Y-82.205 E9.80570\nG1 X169.915 Y-79.231 E10.06264\nG1 X171.280 Y-76.235 E10.31934\nG1 X173.819 Y-70.251 E10.82613\nG1 X176.180 Y-64.101 E11.33975\nG1 X178.297 Y-57.955 E11.84654\nG1 X179.294 Y-54.793 E12.10507\nG1 X181.085 Y-48.544 E12.61186\nG1 X181.911 Y-45.354 E12.86880\nG1 X183.378 Y-39.001 E13.37718\nG1 X184.035 Y-35.771 E13.63412\nG1 X185.168 Y-29.350 E14.14250\nG1 X185.655 Y-26.091 E14.39944\nG1 X186.084 Y-22.826 E14.65614\nG1 X186.764 Y-16.362 E15.16293\nG1 X187.223 Y-9.790 E15.67655\nG1 X187.450 Y-3.294 E16.18334\nG1 X187.479 Y0.002 E16.44028\nG1 X187.450 Y3.294 E16.69698\nG1 X187.223 Y9.810 E17.20529\nG1 X187.021 Y13.100 E17.46229\nG1 X186.454 Y19.575 E17.96909\nG1 X186.079 Y22.870 E18.22761\nG1 X185.174 Y29.307 E18.73440\nG1 X184.031 Y35.794 E19.24802\nG1 X182.679 Y42.152 E19.75481\nG1 X181.910 Y45.357 E20.01176\nG1 X180.223 Y51.655 E20.52013\nG1 X179.287 Y54.815 E20.77708\nG1 X177.272 Y61.017 E21.28545\nG1 X176.172 Y64.123 E21.54239\nG1 X175.019 Y67.207 E21.79909\nG1 X172.584 Y73.234 E22.30588\nG1 X169.905 Y79.252 E22.81950\nG1 X167.055 Y85.094 E23.32629\nG1 X165.524 Y88.035 E23.58482\nG1 X162.373 Y93.721 E24.09161\nG1 X160.700 Y96.560 E24.34855\nG1 X157.245 Y102.090 E24.85693\nG1 X155.427 Y104.838 E25.11387\nG1 X151.687 Y110.180 E25.62225\nG1 X149.727 Y112.829 E25.87919\nG1 X147.722 Y115.441 E26.13588\nG1 X143.631 Y120.493 E26.64268\nG1 X139.310 Y125.464 E27.15629\nG1 X134.876 Y130.218 E27.66309\nG1 X132.567 Y132.569 E27.92003\nG1 X127.877 Y137.099 E28.42840\nG1 X125.447 Y139.325 E28.68535\nG1 X122.981 Y141.507 E28.94204\nG1 X118.002 Y145.685 E29.44883\nG1 X112.810 Y149.741 E29.96245\nG1 X107.552 Y153.561 E30.46924\nG1 X104.819 Y155.440 E30.72777\nG1 X99.367 Y158.980 E31.23456\nG1 X96.558 Y160.702 E31.49151\nG1 X90.911 Y163.962 E31.99988\nG1 X88.015 Y165.535 E32.25682\nG1 X82.205 Y168.496 E32.76520\nG1 X79.231 Y169.915 E33.02214\nG1 X76.235 Y171.280 E33.27884\nG1 X70.251 Y173.819 E33.78563\nG1 X64.101 Y176.180 E34.29925\nG1 X57.955 Y178.297 E34.80604\nG1 X54.793 Y179.294 E35.06457\nG1 X48.544 Y181.085 E35.57136\nG1 X45.354 Y181.911 E35.82830\nG1 X39.001 Y183.378 E36.33668\nG1 X35.771 Y184.035 E36.59362\nG1 X29.350 Y185.168 E37.10200\nG1 X26.091 Y185.655 E37.35894\nG1 X22.826 Y186.084 E37.61563\nG1 X16.362 Y186.764 E38.12242\nG1 X9.790 Y187.223 E38.63605\nG1 X3.294 Y187.450 E39.14283\nG1 X-0.002 Y187.479 E39.39978\nG1 X-3.294 Y187.450 E39.65648\nG1 X-9.810 Y187.223 E40.16479\nG1 X-13.100 Y187.021 E40.42179\nG1 X-19.575 Y186.454 E40.92858\nG1 X-22.870 Y186.079 E41.18711\nG1 X-29.307 Y185.174 E41.69390\nG1 X-35.794 Y184.031 E42.20752\nG1 X-42.152 Y182.679 E42.71431\nG1 X-45.357 Y181.910 E42.97126\nG1 X-51.655 Y180.223 E43.47963\nG1 X-54.815 Y179.287 E43.73657\nG1 X-61.017 Y177.272 E44.24495\nG1 X-64.123 Y176.172 E44.50189\nG1 X-67.207 Y175.019 E44.75859\nG1 X-73.234 Y172.584 E45.26538\nG1 X-79.252 Y169.905 E45.77900\nG1 X-85.094 Y167.055 E46.28579\nG1 X-88.035 Y165.524 E46.54432\nG1 X-93.721 Y162.373 E47.05111\nG1 X-96.560 Y160.700 E47.30805\nG1 X-102.090 Y157.245 E47.81643\nG1 X-104.838 Y155.427 E48.07337\nG1 X-110.180 Y151.687 E48.58174\nG1 X-112.829 Y149.727 E48.83869\nG1 X-115.441 Y147.722 E49.09538\nG1 X-120.493 Y143.631 E49.60218\nG1 X-125.464 Y139.310 E50.11579\nG1 X-130.218 Y134.876 E50.62259\nG1 X-132.569 Y132.567 E50.87953\nG1 X-137.099 Y127.877 E51.38790\nG1 X-139.325 Y125.447 E51.64485\nG1 X-141.507 Y122.981 E51.90154\nG1 X-145.685 Y118.002 E52.40833\nG1 X-149.741 Y112.810 E52.92195\nG1 X-153.561 Y107.552 E53.42874\nG1 X-155.440 Y104.819 E53.68727\nG1 X-158.980 Y99.367 E54.19406\nG1 X-160.702 Y96.558 E54.45101\nG1 X-163.962 Y90.911 E54.95938\nG1 X-165.535 Y88.015 E55.21632\nG1 X-168.496 Y82.205 E55.72470\nG1 X-169.915 Y79.231 E55.98164\nG1 X-171.280 Y76.235 E56.23834\nG1 X-173.819 Y70.251 E56.74513\nG1 X-176.180 Y64.101 E57.25875\nG1 X-178.297 Y57.955 E57.76554\nG1 X-179.294 Y54.793 E58.02407\nG1 X-181.085 Y48.544 E58.53086\nG1 X-181.911 Y45.354 E58.78780\nG1 X-183.378 Y39.001 E59.29618\nG1 X-184.035 Y35.771 E59.55312\nG1 X-185.168 Y29.350 E60.06149\nG1 X-185.655 Y26.091 E60.31844\nG1 X-186.084 Y22.826 E60.57513\nG1 X-186.764 Y16.362 E61.08192\nG1 X-187.223 Y9.790 E61.59554\nG1 X-187.450 Y3.294 E62.10233\nG1 X-187.479 Y-0.002 E62.35928\nG1 X-187.450 Y-3.294 E62.61598\nG1 X-187.223 Y-9.810 E63.12429\nG1 X-187.021 Y-13.100 E63.38129\nG1 X-186.454 Y-19.575 E63.88808\nG1 X-186.079 Y-22.870 E64.14661\nG1 X-185.174 Y-29.307 E64.65340\nG1 X-184.031 Y-35.794 E65.16702\nG1 X-182.679 Y-42.152 E65.67381\nG1 X-181.910 Y-45.357 E65.93076\nG1 X-180.223 Y-51.655 E66.43913\nG1 X-179.287 Y-54.815 E66.69607\nG1 X-177.272 Y-61.017 E67.20445\nG1 X-176.172 Y-64.123 E67.46139\nG1 X-175.019 Y-67.207 E67.71809\nG1 X-172.584 Y-73.234 E68.22488\nG1 X-169.905 Y-79.252 E68.73850\nG1 X-167.055 Y-85.094 E69.24529\nG1 X-165.524 Y-88.035 E69.50382\nG1 X-162.373 Y-93.721 E70.01061\nG1 X-160.700 Y-96.560 E70.26755\nG1 X-157.245 Y-102.090 E70.77593\nG1 X-155.427 Y-104.838 E71.03287\nG1 X-151.687 Y-110.180 E71.54124\nG1 X-149.727 Y-112.829 E71.79819\nG1 X-147.722 Y-115.441 E72.05488\nG1 X-143.631 Y-120.493 E72.56167\nG1 X-139.310 Y-125.464 E73.07529\nG1 X-134.876 Y-130.218 E73.58209\nG1 X-132.567 Y-132.569 E73.83903\nG1 X-127.877 Y-137.099 E74.34740\nG1 X-125.447 Y-139.325 E74.60435\nG1 X-122.981 Y-141.507 E74.86104\nG1 X-118.002 Y-145.685 E75.36783\nG1 X-112.810 Y-149.741 E75.88145\nG1 X-107.552 Y-153.561 E76.38824\nG1 X-104.819 Y-155.440 E76.64677\nG1 X-99.367 Y-158.980 E77.15356\nG1 X-96.558 Y-160.702 E77.41051\nG1 X-90.911 Y-163.962 E77.91888\nG1 X-88.015 Y-165.535 E78.17582\nG1 X-82.205 Y-168.496 E78.68420\nG1 X-79.231 Y-169.915 E78.94114\nG1 X-76.235 Y-171.280 E79.19784\nG1 X-70.251 Y-173.819 E79.70463\nG1 X-64.101 Y-176.180 E80.21825\nG1 X-57.955 Y-178.297 E80.72504\nG1 X-54.793 Y-179.294 E80.98356\nG1 X-48.544 Y-181.085 E81.49036\nG1 X-45.354 Y-181.911 E81.74730\nG1 X-39.001 Y-183.378 E82.25568\nG1 X-35.771 Y-184.035 E82.51262\nG1 X-29.350 Y-185.168 E83.02099\nG1 X-26.091 Y-185.655 E83.27794\nG1 X-22.826 Y-186.084 E83.53463\nG1 X-16.362 Y-186.764 E84.04142\nG1 X-9.790 Y-187.223 E84.55504\nG1 X-3.294 Y-187.450 E85.06183\nG1 X0.006 Y-187.479 E85.31908\nG1 X6.521 Y-187.366 E85.82715\nG1 X9.810 Y-187.223 E86.08379\nG1 X13.100 Y-187.021 E86.34079\nG1 X19.575 Y-186.454 E86.84758\nG1 X22.870 Y-186.079 E87.10611\nG1 X29.307 Y-185.174 E87.61290\nG1 X35.794 Y-184.031 E88.12652\nG1 X42.152 Y-182.679 E88.63331\nG1 X45.357 Y-181.910 E88.89025\nG1 X51.655 Y-180.223 E89.39863\nG1 X54.815 Y-179.287 E89.65557\nG1 X61.017 Y-177.272 E90.16395\nG1 X64.123 Y-176.172 E90.42089\nG1 X67.207 Y-175.019 E90.67759\nG1 X73.234 Y-172.584 E91.18438\nG1 X79.252 Y-169.905 E91.69800\nG1 X85.094 Y-167.055 E92.20479\nG1 X88.035 Y-165.524 E92.46332\nG1 X93.721 Y-162.373 E92.97011\nG1 X96.560 Y-160.700 E93.22705\nG1 X102.090 Y-157.245 E93.73543\nG1 X104.838 Y-155.427 E93.99237\nG1 X110.180 Y-151.687 E94.50074\nG1 X112.829 Y-149.727 E94.75768\nG1 X115.441 Y-147.722 E95.01438\nG1 X120.493 Y-143.631 E95.52117\nG1 X122.911 Y-141.529 E95.77098\n\n; end preskirt\n; start_gcode | end +end_gcode = ; end_gcode | start\n\n; v11 2020-11-14_11-27 tillverka\n\n; use relative positioning\n\nG91\n\n; retract the filament a bit before lifting the nozzle to release some of the pressure\n\nG1 E-1 F300\n\n; home\n\nG28\n\n; use absolute positioning\n\nG90\n\n; cooldown\n\nM104 S0\nM140 S0\n\n; end_gcode | end\n +before_layer_gcode = +layer_gcode = +toolchange_gcode = +between_objects_gcode = +retract_length = 4 +retract_lift = 0.3 +retract_lift_above = 0 +retract_lift_below = 449 +retract_speed = 30 +deretract_speed = 0 +retract_restart_extra = 0 +retract_before_travel = 2 +retract_layer_change = 1 +wipe = 1 +retract_before_wipe = 70% +retract_length_toolchange = 10 +retract_restart_extra_toolchange = 0 +extruder_colour = #1193FF +machine_max_acceleration_e = 3000 +machine_max_acceleration_extruding = 1000 +machine_max_acceleration_retracting = 1000 +machine_max_acceleration_x = 1500 +machine_max_acceleration_y = 1500 +machine_max_acceleration_z = 1500 +machine_max_feedrate_e = 60 +machine_max_feedrate_x = 200 +machine_max_feedrate_y = 200 +machine_max_feedrate_z = 200 +machine_max_jerk_e = 5 +machine_max_jerk_x = 5 +machine_max_jerk_y = 5 +machine_max_jerk_z = 5 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +printer_settings_id = +printer_notes = Do not remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PREDATOR\nPRINTER_HAS_BOWDEN\n +default_filament_profile = Generic PLA @PREDATOR + +[printer:Anycubic Predator 0.4 nozzle] +inherits = *common predator* +printer_model = PREDATOR +printer_variant = 0.4 +nozzle_diameter = 0.4 +min_layer_height = 0.08 +max_layer_height = 0.32 +default_print_profile = 0.16mm 0.4 nozzle DETAILED QUALITY @PREDATOR + +[printer:Anycubic Predator 0.6 nozzle] +inherits = *common predator* +printer_model = PREDATOR +printer_variant = 0.6 +nozzle_diameter = 0.6 +min_layer_height = 0.12 +max_layer_height = 0.4 +default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR + +[printer:Anycubic Predator 0.8 nozzle] +inherits = *common predator* +printer_model = PREDATOR +printer_variant = 0.8 +nozzle_diameter = 0.8 +min_layer_height = 0.16 +max_layer_height = 0.48 +default_print_profile = 0.24mm 0.8 nozzle DETAILED QUALITY @PREDATOR + +## Anycubic 4MAX Pro 2.0 +## based on https://hartrusion.com/en/prusaslicer-config-for-anycubic-4max-pro-2-0/ + +[print:*common_4max*] +avoid_crossing_perimeters = 0 +avoid_crossing_perimeters_max_detour = 0 +bottom_fill_pattern = monotonic +bottom_solid_layers = 4 +bridge_acceleration = 300 +bridge_angle = 0 +bridge_flow_ratio = 0.65 +bridge_speed = 30 +brim_separation = 0 +brim_type = outer_only +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers_condition = printer_model=="4MAXPRO20" and nozzle_diameter[0]==0.4 +complete_objects = 0 +default_acceleration = 900 +dont_support_bridges = 1 +draft_shield = disabled +elefant_foot_compensation = 0.2 +ensure_vertical_shell_thickness = 1 +external_perimeter_extrusion_width = 0 +external_perimeter_speed = 35 +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 20 +extruder_clearance_radius = 20 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = gyroid +first_layer_acceleration = 300 +first_layer_acceleration_over_raft = 0 +first_layer_extrusion_width = 0.65 +first_layer_height = 0.3 +first_layer_speed = 20 +first_layer_speed_over_raft = 30 +fuzzy_skin = none +fuzzy_skin_point_dist = 0.8 +fuzzy_skin_thickness = 0.3 +gap_fill_enabled = 1 +gap_fill_speed = 40 +gcode_comments = 0 +gcode_label_objects = 0 +gcode_resolution = 0.0125 +infill_acceleration = 600 +infill_anchor = 400% +infill_anchor_max = 50 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 23% +infill_speed = 45 +inherits = +interface_shells = 0 +ironing = 0 +ironing_flowrate = 15% +ironing_spacing = 0.1 +ironing_speed = 15 +ironing_type = top +layer_height = 0.2 +max_print_speed = 50 +max_volumetric_speed = 0 +min_skirt_length = 0 +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{print_time}.gcode +overhangs = 1 +perimeter_acceleration = 500 +perimeter_extruder = 1 +perimeter_extrusion_width = 0 +perimeter_speed = 45 +perimeters = 3 +post_process = +print_settings_id = +raft_contact_distance = 0.1 +raft_expansion = 1.5 +raft_first_layer_density = 90% +raft_first_layer_expansion = 3 +raft_layers = 0 +resolution = 0 +seam_position = aligned +single_extruder_multi_material_priming = 1 +skirt_distance = 5 +skirt_height = 1 +skirts = 2 +slicing_mode = regular +small_perimeter_speed = 20 +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0 +solid_infill_speed = 45 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_auto = 1 +support_material_bottom_contact_distance = 0 +support_material_bottom_interface_layers = -1 +support_material_buildplate_only = 1 +support_material_closing_radius = 2 +support_material_contact_distance = 0.2 +support_material_enforce_layers = 0 +support_material_extruder = 1 +support_material_extrusion_width = 0.4 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 1 +support_material_interface_layers = 2 +support_material_interface_pattern = rectilinear +support_material_interface_spacing = 0.2 +support_material_interface_speed = 30 +support_material_pattern = rectilinear-grid +support_material_spacing = 2.5 +support_material_speed = 45 +support_material_style = grid +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 1 +support_material_xy_spacing = 60% +thick_bridges = 1 +thin_walls = 0 +top_fill_pattern = monotonic +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 30 +top_solid_layers = 5 +travel_speed = 60 +travel_speed_z = 0 +wipe_tower = 0 +wipe_tower_bridging = 10 +wipe_tower_brim_width = 2 +wipe_tower_no_sparse_layers = 0 +wipe_tower_rotation_angle = 0 +wipe_tower_width = 60 +wipe_tower_x = 180 +wipe_tower_y = 140 +xy_size_compensation = 0 + +[print:0.15mm Detail @4Max Pro 2.0] +inherits = *common_4max* +layer_height = 0.15 +bottom_solid_layers = 5 +top_solid_layers = 7 +perimeter_speed = 40 +external_perimeter_speed = 25 + +[print:0.20mm Quality @4Max Pro 2.0] +inherits = *common_4max* +external_perimeter_speed = 25 + +[print:0.30mm Draft @4Max Pro 2.0] +inherits = *common_4max* +layer_height = 0.3 +bottom_solid_layers = 3 +top_solid_layers = 3 + +[filament:*common_4max*] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers_condition = printer_model=="4MAXPRO20" +cooling = 1 +disable_fan_first_layers = 1 +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 30 +filament_density = 1.24 +filament_diameter = 1.75 +filament_max_volumetric_speed = 0 +filament_type = PLA +first_layer_bed_temperature = 60 +first_layer_temperature = 210 +full_fan_speed_layer = 5 +max_fan_speed = 100 +min_fan_speed = 80 +min_print_speed = 10 +slowdown_below_layer_time = 15 +temperature = 205 + +[filament:*PLA_4max*] +inherits = *common_4max* + +[filament:Generic PLA @4Max Pro 2.0] +inherits = *PLA_4max* +filament_vendor = Generic + +[filament:Anycubic PLA @4Max Pro 2.0] +inherits = *PLA_4max* +first_layer_temperature = 215 +temperature = 207 +filament_vendor = Anycubic + +[filament:Generic ABS @4Max Pro 2.0] +filament_vendor = Generic +compatible_printers_condition = printer_model=="4MAXPRO20" +bed_temperature = 100 +first_layer_bed_temperature = 100 +temperature = 245 +first_layer_temperature = 245 +bridge_fan_speed = 15 +cooling = 1 +disable_fan_first_layers = 3 +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 60 +filament_colour = #800000 +filament_density = 1.04 +filament_diameter = 1.75 +filament_type = ABS +full_fan_speed_layer = 0 +max_fan_speed = 0 +min_fan_speed = 0 +min_print_speed = 10 +slowdown_below_layer_time = 25 + +[filament:Generic TPU @4Max Pro 2.0] +filament_vendor = Generic +bed_temperature = 60 +bridge_fan_speed = 0 +compatible_printers_condition = printer_model=="4MAXPRO20" +cooling = 1 +disable_fan_first_layers = 3 +extrusion_multiplier = 1 +fan_always_on = 0 +fan_below_layer_time = 60 +filament_colour = #211AB5 +filament_density = 1.19 +filament_deretract_speed = 20 +filament_diameter = 1.75 +filament_retract_speed = 30 +filament_type = FLEX +filament_max_volumetric_speed = 1.65 +first_layer_bed_temperature = 60 +first_layer_temperature = 215 +full_fan_speed_layer = 0 +max_fan_speed = 0 +min_fan_speed = 0 +min_print_speed = 10 +slowdown_below_layer_time = 20 +temperature = 215 + +[filament:Polymaker PolyFlex TPU95 @4Max Pro 2.0] +filament_vendor = Polymaker +bed_temperature = 45 +bridge_fan_speed = 80 +compatible_printers_condition = printer_model=="4MAXPRO20" +cooling = 1 +disable_fan_first_layers = 5 +extrusion_multiplier = 1.04 +fan_always_on = 1 +fan_below_layer_time = 45 +filament_colour = #FD7D2F +filament_density = 1.22 +filament_deretract_speed = 25 +filament_diameter = 1.75 +filament_max_volumetric_speed = 1.65 +filament_retract_length = 4 +filament_retract_restart_extra = 0.1 +filament_retract_speed = 60 +filament_type = FLEX +first_layer_bed_temperature = 55 +first_layer_temperature = 215 +full_fan_speed_layer = 8 +max_fan_speed = 50 +min_fan_speed = 25 +min_print_speed = 10 +slowdown_below_layer_time = 10 +temperature = 217 + +[printer:Anycubic 4Max Pro 2.0] +printer_model = 4MAXPRO20 +printer_variant = 0.4 +printer_technology = FFF +bed_shape = 0x0,270x0,270x210,0x210 +color_change_gcode = M600 +default_filament_profile = Generic PLA @4Max Pro 2.0 +default_print_profile = 0.20mm Quality @4Max Pro 2.0 +deretract_speed = 25 +end_gcode = M104 S0 ; turn off extruder heating\nM140 S0 ; turn off bed heating\nM107 ; turn off fans\nG91 ; relative positioning\nG0 Z+0.5 ; move Z up a tiny bit\nG90 ; absolute positioning\nG0 X135 Y105 F{machine_max_feedrate_x[0]*60} ; move extruder to center position\nG0 Z190.5 F{machine_max_feedrate_z[0]*60} ; lower the plattform to Z min\nM84 ; steppers off\nG90 ; absolute positioning\n +extruder_offset = 0x0 +gcode_flavor = marlin +machine_limits_usage = time_estimate_only +machine_max_acceleration_e = 5000 +machine_max_acceleration_extruding = 1250 +machine_max_acceleration_retracting = 1250 +machine_max_acceleration_travel = 1500 +machine_max_acceleration_x = 900 +machine_max_acceleration_y = 900 +machine_max_acceleration_z = 100 +machine_max_feedrate_e = 120 +machine_max_feedrate_x = 200 +machine_max_feedrate_y = 200 +machine_max_feedrate_z = 16 +machine_max_jerk_e = 5 +machine_max_jerk_x = 6 +machine_max_jerk_y = 6 +machine_max_jerk_z = 0.2 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +max_layer_height = 0.3 +max_print_height = 190 +min_layer_height = 0.07 +nozzle_diameter = 0.4 +pause_print_gcode = M601 +remaining_times = 0 +retract_before_travel = 2 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 2.5 +retract_length_toolchange = 10 +retract_lift = 0 +retract_lift_above = 0 +retract_lift_below = 0 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 35 +silent_mode = 0 +single_extruder_multi_material = 0 +start_gcode = G21 ; metric values\nG90 ; absolute positioning\nM82 ; set extruder to absolute mode\nM140 S[first_layer_bed_temperature] ; set bed temp\nG28 X0 Y0 ; home X and Y\nG28 Z0 ; home Z\nG1 Z30 F{machine_max_feedrate_z[0]*60} ; move Z a bit down to not blow on the bed edge while heating\nG1 X10 F3900 ; let some space on x to prevent the filament cooling exhaust from beeing blocked by the servo motor\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM104 S[first_layer_temperature] ; set extruder temp\nM106 S80 ; turn on fan to prevent air nozzle melt while heating up\nM109 S[first_layer_temperature] ; wait for extruder temp\nM107 ; start with the fan off\nG28 X0 ; goto X home again\nG92 E0 ; zero the extruded length\nG1 Z0.2 F360 ; move plattform upwards\n; extrude material next to the plattform (comment or remove following lines to disable)\nG1 F180 E20 ; extrude some material next to the plattform\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG92 E0 ; zero the extruded length again\nG1 X5 F3900 ; move sideways to get rid of that string\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\nG92 E0 ; zero the extruded length again\n; draw intro line (comment or remove following lines to disable)\nG1 X30 E5 F700 ; draw intro line\nG92 E0 ; zero the extruded length\nG1 E-[retract_length] F{retract_speed[0]*60} ; do a filament retract\nG1 X40 Z2.0 ; move away from the introline\nG92 E0 ; zero the extruded length again\nG1 E[retract_length] F{retract_speed[0]*60} ; do a filament deretract with retract parameters\n; end of intro line code\nM117 Printing...\nG5 +use_firmware_retraction = 0 +use_relative_e_distances = 0 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 0 +z_offset = 0 + +########## SLA printer presets ########## + +[sla_print:*common print ANYCUBIC SLA*] +compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/ +layer_height = 0.05 +output_filename_format = [input_filename_base].pwmx +pad_edge_radius = 0.5 +pad_enable = 0 +pad_max_merge_distance = 50 +pad_wall_height = 0 +pad_wall_thickness = 1 +pad_wall_slope = 45 +faded_layers = 8 +slice_closing_radius = 0.005 +support_base_diameter = 3 +support_base_height = 1 +support_critical_angle = 45 +support_density_at_45 = 250 +support_density_at_horizontal = 500 +support_head_front_diameter = 0.4 +support_head_penetration = 0.4 +support_head_width = 3 +support_max_bridge_length = 10 +support_minimal_z = 0 +support_object_elevation = 5 +support_pillar_diameter = 1 +support_pillar_connection_mode = zigzag +support_pillar_widening_factor = 0 +supports_enable = 1 +support_small_pillar_diameter_percent = 60% + +[sla_print:0.05 Normal @ANYCUBIC] +inherits = *common print ANYCUBIC SLA* +layer_height = 0.05 + +########### Materials + +[sla_material:*common ANYCUBIC SLA*] +compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/ +compatible_prints_condition = layer_height == 0.05 +exposure_time = 7 +initial_exposure_time = 40 +initial_layer_height = 0.05 +material_correction = 1,1,1 +material_notes = LIFT_DISTANCE=8.0\nLIFT_SPEED=2.5\nRETRACT_SPEED=3.0\nBOTTOM_LIFT_SPEED=2.0\nBOTTOM_LIFT_DISTANCE=9.0\nDELAY_BEFORE_EXPOSURE=0.5 + +[sla_material:*common 0.05 ANYCUBIC SLA*] +inherits = *common ANYCUBIC SLA* + +[sla_material:Generic Blue Resin @MONO 0.05] +inherits = *common 0.05 ANYCUBIC SLA* +exposure_time = 2.5 +initial_exposure_time = 40 +material_type = Tough +material_vendor = Generic +material_colour = #6080EC +compatible_printers_condition = printer_notes=~/.*PHOTONMONOX.*/ + +########## Printers + +[printer:Anycubic Photon Mono X] +printer_technology = SLA +printer_model = PHOTON MONO X +printer_variant = default +default_sla_material_profile = Generic Blue Resin @MONO 0.05 +default_sla_print_profile = 0.05 Normal @ANYCUBIC +thumbnails = 224x168 +sla_archive_format = pwmx +bed_shape = 1.48x1.02,193.48x1.02,193.48x121.02,1.48x121.02 +display_height = 120 +display_orientation = landscape +display_mirror_x = 1 +display_mirror_y = 0 +display_pixels_x = 3840 +display_pixels_y = 2400 +display_width = 192 +max_print_height = 245 +elefant_foot_compensation = 0.2 +elefant_foot_min_width = 0.2 +min_exposure_time = 1 +max_exposure_time = 120 +min_initial_exposure_time = 1 +max_initial_exposure_time = 300 +printer_correction = 1,1,1 +gamma_correction = 1 +area_fill = 45 +printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.'\nPRINTER_VENDOR_ANYCUBIC\nPRINTER_MODEL_PHOTONMONOX\n From 0bd3112b7a7840b7c75178ca8deb6b2b5a16d51a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 18 Mar 2022 15:45:42 +0100 Subject: [PATCH 19/46] Reworked custom gcode toolpaths generation --- src/libslic3r/GCode/GCodeProcessor.cpp | 6 +++--- src/libslic3r/GCode/GCodeProcessor.hpp | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 43a5f1eb0a..3569f6322d 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -1206,7 +1206,6 @@ void GCodeProcessor::reset() m_extruded_last_z = 0.0f; m_first_layer_height = 0.0f; - m_processing_start_custom_gcode = false; m_g1_line_id = 0; m_layer_id = 0; m_cp_color.reset(); @@ -1810,7 +1809,6 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers set_extrusion_role(ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()))); if (m_extrusion_role == erExternalPerimeter) m_seams_detector.activate(true); - m_processing_start_custom_gcode = (m_extrusion_role == erCustom && m_g1_line_id == 0); return; } @@ -2516,6 +2514,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (m_forced_height > 0.0f) m_height = m_forced_height; + else if (m_layer_id == 0) + m_height = (m_end_position[Z] <= double(m_first_layer_height)) ? m_end_position[Z] : m_first_layer_height; else { if (m_end_position[Z] > m_extruded_last_z + EPSILON) m_height = m_end_position[Z] - m_extruded_last_z; @@ -3269,7 +3269,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type) m_extrusion_role, m_extruder_id, m_cp_color.current, - Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z] - m_z_offset) + m_extruder_offsets[m_extruder_id], + Vec3f(m_end_position[X], m_end_position[Y], m_end_position[Z] - m_z_offset) + m_extruder_offsets[m_extruder_id], static_cast(m_end_position[E] - m_start_position[E]), m_feedrate, m_width, diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 5ca8f0b026..9faa795784 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -547,7 +547,6 @@ namespace Slic3r { ExtruderTemps m_extruder_temps; float m_extruded_last_z; float m_first_layer_height; // mm - bool m_processing_start_custom_gcode; unsigned int m_g1_line_id; unsigned int m_layer_id; CpColor m_cp_color; From 93d703518d588720ff1333e7cd5919fab1a7df50 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 21 Mar 2022 08:53:55 +0100 Subject: [PATCH 20/46] Tech ENABLE_PROCESS_G2_G3_LINES - Improved detection of layer zs for gcode produced by other slicers --- src/libslic3r/GCode/GCodeProcessor.cpp | 21 +++++++++++++++++---- src/libslic3r/GCode/GCodeProcessor.hpp | 7 +++++++ src/slic3r/GUI/GCodeViewer.cpp | 20 +++++++++++++------- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 340515d5ff..0851f38ac2 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -37,7 +37,7 @@ static const float DEFAULT_FILAMENT_DENSITY = 1.245f; static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero(); #if ENABLE_PROCESS_G2_G3_LINES -static const std::string INTERNAL_G2G3_TAG = "!#!#! from G2/G3 expansion !#!#!"; +static const std::string INTERNAL_G2G3_TAG = "!#!#! internal only - from G2/G3 expansion !#!#!"; #endif // ENABLE_PROCESS_G2_G3_LINES namespace Slic3r { @@ -2782,7 +2782,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1; // store move +#if ENABLE_PROCESS_G2_G3_LINES + store_move_vertex(type, line.comment() == INTERNAL_G2G3_TAG); +#else store_move_vertex(type); +#endif // ENABLE_PROCESS_G2_G3_LINES } #if ENABLE_PROCESS_G2_G3_LINES @@ -2897,7 +2901,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc return ret; }; - auto fake_g1_line = [](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) { + auto internal_only_g1_line = [](const AxisCoords& target, bool has_z, const std::optional& feedrate, const std::optional& extrusion) { std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str(); if (has_z) ret += (boost::format(" Z%1%") % target[Z]).str(); @@ -2969,7 +2973,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc arc_target[Z] += z_per_segment; arc_target[E] += extruder_per_segment; - gcode += fake_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion); + gcode += internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion); prev_target = arc_target; // feedrate is constant, we do not need to repeat it @@ -2977,7 +2981,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc } // Ensure last segment arrives at target location. - gcode += fake_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion); + gcode += internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion); // process fake gcode lines GCodeReader parser; @@ -3489,7 +3493,11 @@ void GCodeProcessor::process_T(const std::string_view command) } } +#if ENABLE_PROCESS_G2_G3_LINES +void GCodeProcessor::store_move_vertex(EMoveType type, bool internal_only) +#else void GCodeProcessor::store_move_vertex(EMoveType type) +#endif // ENABLE_PROCESS_G2_G3_LINES { m_last_line_id = (type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ? m_line_id + 1 : @@ -3509,7 +3517,12 @@ void GCodeProcessor::store_move_vertex(EMoveType type) m_mm3_per_mm, m_fan_speed, m_extruder_temps[m_extruder_id], +#if ENABLE_PROCESS_G2_G3_LINES + static_cast(m_result.moves.size()), + internal_only +#else static_cast(m_result.moves.size()) +#endif // ENABLE_PROCESS_G2_G3_LINES }); // stores stop time placeholders for later use diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 3a26348014..4b406b5556 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -113,6 +113,9 @@ namespace Slic3r { float fan_speed{ 0.0f }; // percentage float temperature{ 0.0f }; // Celsius degrees float time{ 0.0f }; // s +#if ENABLE_PROCESS_G2_G3_LINES + bool internal_only{ false }; +#endif // ENABLE_PROCESS_G2_G3_LINES float volumetric_rate() const { return feedrate * mm3_per_mm; } }; @@ -751,7 +754,11 @@ namespace Slic3r { void process_T(const GCodeReader::GCodeLine& line); void process_T(const std::string_view command); +#if ENABLE_PROCESS_G2_G3_LINES + void store_move_vertex(EMoveType type, bool internal_only = false); +#else void store_move_vertex(EMoveType type); +#endif // ENABLE_PROCESS_G2_G3_LINES void set_extrusion_role(ExtrusionRole role); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 5372d4565b..a1be81ced2 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2284,13 +2284,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result) size_t move_id = i - seams_count; if (move.type == EMoveType::Extrude) { - // layers zs - const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back(); - const double z = static_cast(move.position.z()); - if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z) - m_layers.append(z, { last_travel_s_id, move_id }); - else - m_layers.get_ranges().back().last = move_id; +#if ENABLE_PROCESS_G2_G3_LINES + if (move.extrusion_role != erNone && !move.internal_only) { +#endif // ENABLE_PROCESS_G2_G3_LINES + // layers zs + const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back(); + const double z = static_cast(move.position.z()); + if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z) + m_layers.append(z, { last_travel_s_id, move_id }); + else + m_layers.get_ranges().back().last = move_id; +#if ENABLE_PROCESS_G2_G3_LINES + } +#endif // ENABLE_PROCESS_G2_G3_LINES // extruder ids m_extruder_ids.emplace_back(move.extruder_id); // roles From 4964d6ecd56133237fc9999b677a71ae5fff2817 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 21 Mar 2022 11:31:32 +0100 Subject: [PATCH 21/46] ENABLE_GL_IMGUI_SHADERS - Fixes in ImGuiWrapper::render_draw_data() --- src/slic3r/GUI/ImGuiWrapper.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index 613b168415..e659a386bd 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -1528,19 +1528,15 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glLoadIdentity()); #endif // ENABLE_GL_IMGUI_SHADERS -#if ENABLE_GL_IMGUI_SHADERS // Will project scissor/clipping rectangles into framebuffer space - const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + const ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) -#else - const ImVec2 pos = draw_data->DisplayPos; -#endif // ENABLE_GL_IMGUI_SHADERS // Render command lists for (int n = 0; n < draw_data->CmdListsCount; ++n) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; - const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; + const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; #if ENABLE_GL_IMGUI_SHADERS const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert); const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx); @@ -1596,18 +1592,20 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)))); #else - const ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y); - if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) { - // Apply scissor/clipping rectangle - glsafe(::glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y))); + // Project scissor/clipping rectangles into framebuffer space + const ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); + const ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); + if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) + continue; - // Bind texture, Draw - glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); - glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)))); - } + // Apply scissor/clipping rectangle (Y is inverted in OpenGL) + glsafe(::glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y))); + + // Bind texture, Draw + glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); + glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset)); #endif // ENABLE_GL_IMGUI_SHADERS } - idx_buffer += pcmd->ElemCount; } #if ENABLE_GL_IMGUI_SHADERS From 76d1d4949bbd0964717f8112aae992a1267c5eb4 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 21 Mar 2022 13:10:47 +0100 Subject: [PATCH 22/46] Tech ENABLE_GL_SHADERS_ATTRIBUTES - Added shaders for glsl version 140 --- resources/shaders/110/background.fs | 11 +++ .../{background_attr.vs => 110/background.vs} | 0 resources/shaders/110/flat.fs | 8 ++ .../shaders/{flat_attr.vs => 110/flat.vs} | 4 +- resources/shaders/110/flat_texture.fs | 10 +++ .../flat_texture.vs} | 6 +- resources/shaders/110/gouraud.fs | 86 +++++++++++++++++++ .../{gouraud_attr.vs => 110/gouraud.vs} | 6 +- resources/shaders/110/gouraud_light.fs | 12 +++ .../gouraud_light.vs} | 6 +- .../shaders/110/gouraud_light_instanced.fs | 12 +++ .../gouraud_light_instanced.vs} | 8 +- resources/shaders/{ => 110}/imgui.fs | 0 resources/shaders/{ => 110}/imgui.vs | 0 .../{mm_contour_attr.fs => 110/mm_contour.fs} | 0 .../{mm_contour_attr.vs => 110/mm_contour.vs} | 4 +- .../{mm_gouraud_attr.fs => 110/mm_gouraud.fs} | 0 .../{mm_gouraud_attr.vs => 110/mm_gouraud.vs} | 4 +- resources/shaders/110/printbed.fs | 34 ++++++++ .../{printbed_attr.vs => 110/printbed.vs} | 6 +- resources/shaders/110/toolpaths_cog.fs | 19 ++++ .../toolpaths_cog.vs} | 6 +- .../shaders/110/variable_layer_height.fs | 41 +++++++++ .../variable_layer_height.vs} | 8 +- resources/shaders/140/background.fs | 11 +++ resources/shaders/140/background.vs | 12 +++ resources/shaders/140/flat.fs | 8 ++ resources/shaders/140/flat.vs | 11 +++ resources/shaders/140/flat_texture.fs | 10 +++ resources/shaders/140/flat_texture.vs | 15 ++++ resources/shaders/140/gouraud.fs | 86 +++++++++++++++++++ resources/shaders/140/gouraud.vs | 77 +++++++++++++++++ resources/shaders/140/gouraud_light.fs | 12 +++ resources/shaders/140/gouraud_light.vs | 45 ++++++++++ .../shaders/140/gouraud_light_instanced.fs | 12 +++ .../shaders/140/gouraud_light_instanced.vs | 50 +++++++++++ resources/shaders/140/imgui.fs | 11 +++ resources/shaders/140/imgui.vs | 17 ++++ resources/shaders/140/mm_contour.fs | 13 +++ resources/shaders/140/mm_contour.vs | 11 +++ resources/shaders/140/mm_gouraud.fs | 63 ++++++++++++++ resources/shaders/140/mm_gouraud.vs | 28 ++++++ resources/shaders/140/printbed.fs | 34 ++++++++ resources/shaders/140/printbed.vs | 15 ++++ resources/shaders/140/toolpaths_cog.fs | 19 ++++ resources/shaders/140/toolpaths_cog.vs | 47 ++++++++++ .../shaders/140/variable_layer_height.fs | 41 +++++++++ .../shaders/140/variable_layer_height.vs | 60 +++++++++++++ src/slic3r/GUI/3DBed.cpp | 16 ---- src/slic3r/GUI/3DScene.cpp | 6 -- src/slic3r/GUI/GCodeViewer.cpp | 34 +------- src/slic3r/GUI/GLCanvas3D.cpp | 49 +---------- src/slic3r/GUI/GLModel.cpp | 4 - src/slic3r/GUI/GLSelectionRectangle.cpp | 4 - src/slic3r/GUI/GLShadersManager.cpp | 27 +++--- src/slic3r/GUI/GLTexture.cpp | 4 - src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 8 -- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 12 --- src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 8 -- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 4 - .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 9 +- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 16 ---- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 26 +----- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 8 -- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 36 -------- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 13 +-- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 4 - src/slic3r/GUI/MeshUtils.cpp | 4 - src/slic3r/GUI/Selection.cpp | 12 --- 69 files changed, 994 insertions(+), 309 deletions(-) create mode 100644 resources/shaders/110/background.fs rename resources/shaders/{background_attr.vs => 110/background.vs} (100%) create mode 100644 resources/shaders/110/flat.fs rename resources/shaders/{flat_attr.vs => 110/flat.vs} (100%) create mode 100644 resources/shaders/110/flat_texture.fs rename resources/shaders/{flat_texture_attr.vs => 110/flat_texture.vs} (100%) create mode 100644 resources/shaders/110/gouraud.fs rename resources/shaders/{gouraud_attr.vs => 110/gouraud.vs} (100%) create mode 100644 resources/shaders/110/gouraud_light.fs rename resources/shaders/{gouraud_light_attr.vs => 110/gouraud_light.vs} (100%) create mode 100644 resources/shaders/110/gouraud_light_instanced.fs rename resources/shaders/{gouraud_light_instanced_attr.vs => 110/gouraud_light_instanced.vs} (100%) rename resources/shaders/{ => 110}/imgui.fs (100%) rename resources/shaders/{ => 110}/imgui.vs (100%) rename resources/shaders/{mm_contour_attr.fs => 110/mm_contour.fs} (100%) rename resources/shaders/{mm_contour_attr.vs => 110/mm_contour.vs} (100%) rename resources/shaders/{mm_gouraud_attr.fs => 110/mm_gouraud.fs} (100%) rename resources/shaders/{mm_gouraud_attr.vs => 110/mm_gouraud.vs} (100%) create mode 100644 resources/shaders/110/printbed.fs rename resources/shaders/{printbed_attr.vs => 110/printbed.vs} (100%) create mode 100644 resources/shaders/110/toolpaths_cog.fs rename resources/shaders/{toolpaths_cog_attr.vs => 110/toolpaths_cog.vs} (100%) create mode 100644 resources/shaders/110/variable_layer_height.fs rename resources/shaders/{variable_layer_height_attr.vs => 110/variable_layer_height.vs} (100%) create mode 100644 resources/shaders/140/background.fs create mode 100644 resources/shaders/140/background.vs create mode 100644 resources/shaders/140/flat.fs create mode 100644 resources/shaders/140/flat.vs create mode 100644 resources/shaders/140/flat_texture.fs create mode 100644 resources/shaders/140/flat_texture.vs create mode 100644 resources/shaders/140/gouraud.fs create mode 100644 resources/shaders/140/gouraud.vs create mode 100644 resources/shaders/140/gouraud_light.fs create mode 100644 resources/shaders/140/gouraud_light.vs create mode 100644 resources/shaders/140/gouraud_light_instanced.fs create mode 100644 resources/shaders/140/gouraud_light_instanced.vs create mode 100644 resources/shaders/140/imgui.fs create mode 100644 resources/shaders/140/imgui.vs create mode 100644 resources/shaders/140/mm_contour.fs create mode 100644 resources/shaders/140/mm_contour.vs create mode 100644 resources/shaders/140/mm_gouraud.fs create mode 100644 resources/shaders/140/mm_gouraud.vs create mode 100644 resources/shaders/140/printbed.fs create mode 100644 resources/shaders/140/printbed.vs create mode 100644 resources/shaders/140/toolpaths_cog.fs create mode 100644 resources/shaders/140/toolpaths_cog.vs create mode 100644 resources/shaders/140/variable_layer_height.fs create mode 100644 resources/shaders/140/variable_layer_height.vs diff --git a/resources/shaders/110/background.fs b/resources/shaders/110/background.fs new file mode 100644 index 0000000000..b148440898 --- /dev/null +++ b/resources/shaders/110/background.fs @@ -0,0 +1,11 @@ +#version 110 + +uniform vec4 top_color; +uniform vec4 bottom_color; + +varying vec2 tex_coord; + +void main() +{ + gl_FragColor = mix(bottom_color, top_color, tex_coord.y); +} diff --git a/resources/shaders/background_attr.vs b/resources/shaders/110/background.vs similarity index 100% rename from resources/shaders/background_attr.vs rename to resources/shaders/110/background.vs diff --git a/resources/shaders/110/flat.fs b/resources/shaders/110/flat.fs new file mode 100644 index 0000000000..ab656998df --- /dev/null +++ b/resources/shaders/110/flat.fs @@ -0,0 +1,8 @@ +#version 110 + +uniform vec4 uniform_color; + +void main() +{ + gl_FragColor = uniform_color; +} diff --git a/resources/shaders/flat_attr.vs b/resources/shaders/110/flat.vs similarity index 100% rename from resources/shaders/flat_attr.vs rename to resources/shaders/110/flat.vs index 370eedb72d..d9063f0c70 100644 --- a/resources/shaders/flat_attr.vs +++ b/resources/shaders/110/flat.vs @@ -1,10 +1,10 @@ #version 110 -attribute vec3 v_position; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; +attribute vec3 v_position; + void main() { gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); diff --git a/resources/shaders/110/flat_texture.fs b/resources/shaders/110/flat_texture.fs new file mode 100644 index 0000000000..ffe193b1c0 --- /dev/null +++ b/resources/shaders/110/flat_texture.fs @@ -0,0 +1,10 @@ +#version 110 + +uniform sampler2D uniform_texture; + +varying vec2 tex_coord; + +void main() +{ + gl_FragColor = texture2D(uniform_texture, tex_coord); +} diff --git a/resources/shaders/flat_texture_attr.vs b/resources/shaders/110/flat_texture.vs similarity index 100% rename from resources/shaders/flat_texture_attr.vs rename to resources/shaders/110/flat_texture.vs index e59a99da35..dc4868b04d 100644 --- a/resources/shaders/flat_texture_attr.vs +++ b/resources/shaders/110/flat_texture.vs @@ -1,11 +1,11 @@ #version 110 -attribute vec3 v_position; -attribute vec2 v_tex_coord; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; +attribute vec3 v_position; +attribute vec2 v_tex_coord; + varying vec2 tex_coord; void main() diff --git a/resources/shaders/110/gouraud.fs b/resources/shaders/110/gouraud.fs new file mode 100644 index 0000000000..0742f6cc88 --- /dev/null +++ b/resources/shaders/110/gouraud.fs @@ -0,0 +1,86 @@ +#version 110 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); +const float EPSILON = 0.0001; + +struct PrintVolumeDetection +{ + // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid + int type; + // type = 0 (rectangle): + // x = min.x, y = min.y, z = max.x, w = max.y + // type = 1 (circle): + // x = center.x, y = center.y, z = radius + vec4 xy_data; + // x = min z, y = max z + vec2 z_data; +}; + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; + +uniform vec4 uniform_color; +uniform SlopeDetection slope; + +uniform bool offset_depth_buffer; + +#ifdef ENABLE_ENVIRONMENT_MAP + uniform sampler2D environment_tex; + uniform bool use_environment_tex; +#endif // ENABLE_ENVIRONMENT_MAP + +uniform PrintVolumeDetection print_volume; + +varying vec3 clipping_planes_dots; + +// x = diffuse, y = specular; +varying vec2 intensity; + +varying vec4 world_pos; +varying float world_normal_z; +varying vec3 eye_normal; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + + if (slope.actived && world_normal_z < slope.normal_z - EPSILON) { + color = vec3(0.7, 0.7, 1.0); + alpha = 1.0; + } + + // if the fragment is outside the print volume -> use darker color + vec3 pv_check_min = ZERO; + vec3 pv_check_max = ZERO; + if (print_volume.type == 0) { + // rectangle + pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); + pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); + } + else if (print_volume.type == 1) { + // circle + float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); + pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); + pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); + } + color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; + +#ifdef ENABLE_ENVIRONMENT_MAP + if (use_environment_tex) + gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); + else +#endif + gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); + + // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already + // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values + // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos. + gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0); +} diff --git a/resources/shaders/gouraud_attr.vs b/resources/shaders/110/gouraud.vs similarity index 100% rename from resources/shaders/gouraud_attr.vs rename to resources/shaders/110/gouraud.vs index 87e524c14a..70f71f886b 100644 --- a/resources/shaders/gouraud_attr.vs +++ b/resources/shaders/110/gouraud.vs @@ -25,9 +25,6 @@ struct SlopeDetection mat3 volume_world_normal_matrix; }; -attribute vec3 v_position; -attribute vec3 v_normal; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; uniform mat3 normal_matrix; @@ -39,6 +36,9 @@ uniform vec2 z_range; // Clipping plane - general orientation. Used by the SLA gizmo. uniform vec4 clipping_plane; +attribute vec3 v_position; +attribute vec3 v_normal; + // x = diffuse, y = specular; varying vec2 intensity; diff --git a/resources/shaders/110/gouraud_light.fs b/resources/shaders/110/gouraud_light.fs new file mode 100644 index 0000000000..970185a00e --- /dev/null +++ b/resources/shaders/110/gouraud_light.fs @@ -0,0 +1,12 @@ +#version 110 + +uniform vec4 uniform_color; +uniform float emission_factor; + +// x = tainted, y = specular; +varying vec2 intensity; + +void main() +{ + gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); +} diff --git a/resources/shaders/gouraud_light_attr.vs b/resources/shaders/110/gouraud_light.vs similarity index 100% rename from resources/shaders/gouraud_light_attr.vs rename to resources/shaders/110/gouraud_light.vs index 2e1b5fb429..a03653b8a3 100644 --- a/resources/shaders/gouraud_light_attr.vs +++ b/resources/shaders/110/gouraud_light.vs @@ -14,13 +14,13 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 -attribute vec3 v_position; -attribute vec3 v_normal; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; uniform mat3 normal_matrix; +attribute vec3 v_position; +attribute vec3 v_normal; + // x = tainted, y = specular; varying vec2 intensity; diff --git a/resources/shaders/110/gouraud_light_instanced.fs b/resources/shaders/110/gouraud_light_instanced.fs new file mode 100644 index 0000000000..970185a00e --- /dev/null +++ b/resources/shaders/110/gouraud_light_instanced.fs @@ -0,0 +1,12 @@ +#version 110 + +uniform vec4 uniform_color; +uniform float emission_factor; + +// x = tainted, y = specular; +varying vec2 intensity; + +void main() +{ + gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); +} diff --git a/resources/shaders/gouraud_light_instanced_attr.vs b/resources/shaders/110/gouraud_light_instanced.vs similarity index 100% rename from resources/shaders/gouraud_light_instanced_attr.vs rename to resources/shaders/110/gouraud_light_instanced.vs index 7069feb65e..87748ce6f0 100644 --- a/resources/shaders/gouraud_light_instanced_attr.vs +++ b/resources/shaders/110/gouraud_light_instanced.vs @@ -14,6 +14,10 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + // vertex attributes attribute vec3 v_position; attribute vec3 v_normal; @@ -21,10 +25,6 @@ attribute vec3 v_normal; attribute vec3 i_offset; attribute vec2 i_scales; -uniform mat4 view_model_matrix; -uniform mat4 projection_matrix; -uniform mat3 normal_matrix; - // x = tainted, y = specular; varying vec2 intensity; diff --git a/resources/shaders/imgui.fs b/resources/shaders/110/imgui.fs similarity index 100% rename from resources/shaders/imgui.fs rename to resources/shaders/110/imgui.fs diff --git a/resources/shaders/imgui.vs b/resources/shaders/110/imgui.vs similarity index 100% rename from resources/shaders/imgui.vs rename to resources/shaders/110/imgui.vs diff --git a/resources/shaders/mm_contour_attr.fs b/resources/shaders/110/mm_contour.fs similarity index 100% rename from resources/shaders/mm_contour_attr.fs rename to resources/shaders/110/mm_contour.fs diff --git a/resources/shaders/mm_contour_attr.vs b/resources/shaders/110/mm_contour.vs similarity index 100% rename from resources/shaders/mm_contour_attr.vs rename to resources/shaders/110/mm_contour.vs index 370eedb72d..d9063f0c70 100644 --- a/resources/shaders/mm_contour_attr.vs +++ b/resources/shaders/110/mm_contour.vs @@ -1,10 +1,10 @@ #version 110 -attribute vec3 v_position; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; +attribute vec3 v_position; + void main() { gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); diff --git a/resources/shaders/mm_gouraud_attr.fs b/resources/shaders/110/mm_gouraud.fs similarity index 100% rename from resources/shaders/mm_gouraud_attr.fs rename to resources/shaders/110/mm_gouraud.fs diff --git a/resources/shaders/mm_gouraud_attr.vs b/resources/shaders/110/mm_gouraud.vs similarity index 100% rename from resources/shaders/mm_gouraud_attr.vs rename to resources/shaders/110/mm_gouraud.vs index 76101b7670..10c25239f9 100644 --- a/resources/shaders/mm_gouraud_attr.vs +++ b/resources/shaders/110/mm_gouraud.vs @@ -2,8 +2,6 @@ const vec3 ZERO = vec3(0.0, 0.0, 0.0); -attribute vec3 v_position; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; @@ -13,6 +11,8 @@ uniform vec2 z_range; // Clipping plane - general orientation. Used by the SLA gizmo. uniform vec4 clipping_plane; +attribute vec3 v_position; + varying vec3 clipping_planes_dots; varying vec4 model_pos; diff --git a/resources/shaders/110/printbed.fs b/resources/shaders/110/printbed.fs new file mode 100644 index 0000000000..833dff08f4 --- /dev/null +++ b/resources/shaders/110/printbed.fs @@ -0,0 +1,34 @@ +#version 110 + +const vec3 back_color_dark = vec3(0.235, 0.235, 0.235); +const vec3 back_color_light = vec3(0.365, 0.365, 0.365); + +uniform sampler2D texture; +uniform bool transparent_background; +uniform bool svg_source; + +varying vec2 tex_coord; + +vec4 svg_color() +{ + // takes foreground from texture + vec4 fore_color = texture2D(texture, tex_coord); + + // calculates radial gradient + vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5))))); + + // blends foreground with background + return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0); +} + +vec4 non_svg_color() +{ + // takes foreground from texture + vec4 color = texture2D(texture, tex_coord); + return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); +} + +void main() +{ + gl_FragColor = svg_source ? svg_color() : non_svg_color(); +} \ No newline at end of file diff --git a/resources/shaders/printbed_attr.vs b/resources/shaders/110/printbed.vs similarity index 100% rename from resources/shaders/printbed_attr.vs rename to resources/shaders/110/printbed.vs index e59a99da35..dc4868b04d 100644 --- a/resources/shaders/printbed_attr.vs +++ b/resources/shaders/110/printbed.vs @@ -1,11 +1,11 @@ #version 110 -attribute vec3 v_position; -attribute vec2 v_tex_coord; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; +attribute vec3 v_position; +attribute vec2 v_tex_coord; + varying vec2 tex_coord; void main() diff --git a/resources/shaders/110/toolpaths_cog.fs b/resources/shaders/110/toolpaths_cog.fs new file mode 100644 index 0000000000..668fe03ecf --- /dev/null +++ b/resources/shaders/110/toolpaths_cog.fs @@ -0,0 +1,19 @@ +#version 110 + +const vec4 BLACK = vec4(vec3(0.1), 1.0); +const vec4 WHITE = vec4(vec3(1.0), 1.0); + +const float emission_factor = 0.25; + +uniform vec3 world_center; + +// x = tainted, y = specular; +varying vec2 intensity; +varying vec3 world_position; + +void main() +{ + vec3 delta = world_position - world_center; + vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE; + gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0); +} diff --git a/resources/shaders/toolpaths_cog_attr.vs b/resources/shaders/110/toolpaths_cog.vs similarity index 100% rename from resources/shaders/toolpaths_cog_attr.vs rename to resources/shaders/110/toolpaths_cog.vs index 5951238b71..38d2f79444 100644 --- a/resources/shaders/toolpaths_cog_attr.vs +++ b/resources/shaders/110/toolpaths_cog.vs @@ -14,13 +14,13 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 -attribute vec3 v_position; -attribute vec3 v_normal; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; uniform mat3 normal_matrix; +attribute vec3 v_position; +attribute vec3 v_normal; + // x = tainted, y = specular; varying vec2 intensity; varying vec3 world_position; diff --git a/resources/shaders/110/variable_layer_height.fs b/resources/shaders/110/variable_layer_height.fs new file mode 100644 index 0000000000..693c1c6a0b --- /dev/null +++ b/resources/shaders/110/variable_layer_height.fs @@ -0,0 +1,41 @@ +#version 110 + +#define M_PI 3.1415926535897932384626433832795 + +// 2D texture (1D texture split by the rows) of color along the object Z axis. +uniform sampler2D z_texture; +// Scaling from the Z texture rows coordinate to the normalized texture row coordinate. +uniform float z_to_texture_row; +uniform float z_texture_row_to_normalized; +uniform float z_cursor; +uniform float z_cursor_band_width; + +// x = tainted, y = specular; +varying vec2 intensity; + +varying float object_z; + +void main() +{ + float object_z_row = z_to_texture_row * object_z; + // Index of the row in the texture. + float z_texture_row = floor(object_z_row); + // Normalized coordinate from 0. to 1. + float z_texture_col = object_z_row - z_texture_row; + float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25; + // Calculate level of detail from the object Z coordinate. + // This makes the slowly sloping surfaces to be shown with high detail (with stripes), + // and the vertical surfaces to be shown with low detail (no stripes) + float z_in_cells = object_z_row * 190.; + // Gradient of Z projected on the screen. + float dx_vtc = dFdx(z_in_cells); + float dy_vtc = dFdy(z_in_cells); + float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.); + // Sample the Z texture. Texture coordinates are normalized to <0, 1>. + vec4 color = vec4(0.25, 0.25, 0.25, 1.0); + if (z_texture_row >= 0.0) + color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.), + texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod); + // Mix the final color. + gl_FragColor = vec4(vec3(intensity.y), 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend); +} diff --git a/resources/shaders/variable_layer_height_attr.vs b/resources/shaders/110/variable_layer_height.vs similarity index 100% rename from resources/shaders/variable_layer_height_attr.vs rename to resources/shaders/110/variable_layer_height.vs index 40609bd0d9..e6c88fa809 100644 --- a/resources/shaders/variable_layer_height_attr.vs +++ b/resources/shaders/110/variable_layer_height.vs @@ -14,16 +14,16 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 -attribute vec3 v_position; -attribute vec3 v_normal; -attribute vec2 v_tex_coord; - uniform mat4 view_model_matrix; uniform mat4 projection_matrix; uniform mat3 normal_matrix; uniform mat4 volume_world_matrix; uniform float object_max_z; +attribute vec3 v_position; +attribute vec3 v_normal; +attribute vec2 v_tex_coord; + // x = tainted, y = specular; varying vec2 intensity; diff --git a/resources/shaders/140/background.fs b/resources/shaders/140/background.fs new file mode 100644 index 0000000000..c21f3a70cd --- /dev/null +++ b/resources/shaders/140/background.fs @@ -0,0 +1,11 @@ +#version 140 + +uniform vec4 top_color; +uniform vec4 bottom_color; + +in vec2 tex_coord; + +void main() +{ + gl_FragColor = mix(bottom_color, top_color, tex_coord.y); +} diff --git a/resources/shaders/140/background.vs b/resources/shaders/140/background.vs new file mode 100644 index 0000000000..13609b3a21 --- /dev/null +++ b/resources/shaders/140/background.vs @@ -0,0 +1,12 @@ +#version 140 + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coord; + +void main() +{ + tex_coord = v_tex_coord; + gl_Position = vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/flat.fs b/resources/shaders/140/flat.fs new file mode 100644 index 0000000000..e74124dcae --- /dev/null +++ b/resources/shaders/140/flat.fs @@ -0,0 +1,8 @@ +#version 140 + +uniform vec4 uniform_color; + +void main() +{ + gl_FragColor = uniform_color; +} diff --git a/resources/shaders/140/flat.vs b/resources/shaders/140/flat.vs new file mode 100644 index 0000000000..7042671de2 --- /dev/null +++ b/resources/shaders/140/flat.vs @@ -0,0 +1,11 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; + +void main() +{ + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/flat_texture.fs b/resources/shaders/140/flat_texture.fs new file mode 100644 index 0000000000..7db62b6822 --- /dev/null +++ b/resources/shaders/140/flat_texture.fs @@ -0,0 +1,10 @@ +#version 140 + +uniform sampler2D uniform_texture; + +in vec2 tex_coord; + +void main() +{ + gl_FragColor = texture2D(uniform_texture, tex_coord); +} diff --git a/resources/shaders/140/flat_texture.vs b/resources/shaders/140/flat_texture.vs new file mode 100644 index 0000000000..57d8ca3b7c --- /dev/null +++ b/resources/shaders/140/flat_texture.vs @@ -0,0 +1,15 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coord; + +void main() +{ + tex_coord = v_tex_coord; + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs new file mode 100644 index 0000000000..7651380d7d --- /dev/null +++ b/resources/shaders/140/gouraud.fs @@ -0,0 +1,86 @@ +#version 140 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); +const float EPSILON = 0.0001; + +struct PrintVolumeDetection +{ + // 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid + int type; + // type = 0 (rectangle): + // x = min.x, y = min.y, z = max.x, w = max.y + // type = 1 (circle): + // x = center.x, y = center.y, z = radius + vec4 xy_data; + // x = min z, y = max z + vec2 z_data; +}; + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; + +uniform vec4 uniform_color; +uniform SlopeDetection slope; + +uniform bool offset_depth_buffer; + +#ifdef ENABLE_ENVIRONMENT_MAP + uniform sampler2D environment_tex; + uniform bool use_environment_tex; +#endif // ENABLE_ENVIRONMENT_MAP + +uniform PrintVolumeDetection print_volume; + +in vec3 clipping_planes_dots; + +// x = diffuse, y = specular; +in vec2 intensity; + +in vec4 world_pos; +in float world_normal_z; +in vec3 eye_normal; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + + if (slope.actived && world_normal_z < slope.normal_z - EPSILON) { + color = vec3(0.7, 0.7, 1.0); + alpha = 1.0; + } + + // if the fragment is outside the print volume -> use darker color + vec3 pv_check_min = ZERO; + vec3 pv_check_max = ZERO; + if (print_volume.type == 0) { + // rectangle + pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x); + pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y); + } + else if (print_volume.type == 1) { + // circle + float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy); + pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x); + pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y); + } + color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color; + +#ifdef ENABLE_ENVIRONMENT_MAP + if (use_environment_tex) + gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); + else +#endif + gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); + + // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already + // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values + // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos. + gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0); +} diff --git a/resources/shaders/140/gouraud.vs b/resources/shaders/140/gouraud.vs new file mode 100644 index 0000000000..aaf251c42d --- /dev/null +++ b/resources/shaders/140/gouraud.vs @@ -0,0 +1,77 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) +//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION) +//#define LIGHT_FRONT_SHININESS 5.0 + +#define INTENSITY_AMBIENT 0.3 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +struct SlopeDetection +{ + bool actived; + float normal_z; + mat3 volume_world_normal_matrix; +}; + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; +uniform mat4 volume_world_matrix; +uniform SlopeDetection slope; + +// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. +uniform vec2 z_range; +// Clipping plane - general orientation. Used by the SLA gizmo. +uniform vec4 clipping_plane; + +in vec3 v_position; +in vec3 v_normal; + +// x = diffuse, y = specular; +out vec2 intensity; + +out vec3 clipping_planes_dots; + +out vec4 world_pos; +out float world_normal_z; +out vec3 eye_normal; + +void main() +{ + // First transform the normal into camera space and normalize the result. + eye_normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + // Point in homogenous coordinates. + world_pos = volume_world_matrix * vec4(v_position, 1.0); + + // z component of normal vector in world coordinate used for slope shading + world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0; + + gl_Position = projection_matrix * position; + // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. + clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); +} diff --git a/resources/shaders/140/gouraud_light.fs b/resources/shaders/140/gouraud_light.fs new file mode 100644 index 0000000000..de616e066a --- /dev/null +++ b/resources/shaders/140/gouraud_light.fs @@ -0,0 +1,12 @@ +#version 140 + +uniform vec4 uniform_color; +uniform float emission_factor; + +// x = tainted, y = specular; +in vec2 intensity; + +void main() +{ + gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); +} diff --git a/resources/shaders/140/gouraud_light.vs b/resources/shaders/140/gouraud_light.vs new file mode 100644 index 0000000000..b75a844058 --- /dev/null +++ b/resources/shaders/140/gouraud_light.vs @@ -0,0 +1,45 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +in vec3 v_position; +in vec3 v_normal; + +// x = tainted, y = specular; +out vec2 intensity; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/140/gouraud_light_instanced.fs b/resources/shaders/140/gouraud_light_instanced.fs new file mode 100644 index 0000000000..de616e066a --- /dev/null +++ b/resources/shaders/140/gouraud_light_instanced.fs @@ -0,0 +1,12 @@ +#version 140 + +uniform vec4 uniform_color; +uniform float emission_factor; + +// x = tainted, y = specular; +in vec2 intensity; + +void main() +{ + gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); +} diff --git a/resources/shaders/140/gouraud_light_instanced.vs b/resources/shaders/140/gouraud_light_instanced.vs new file mode 100644 index 0000000000..b6b9ab8be7 --- /dev/null +++ b/resources/shaders/140/gouraud_light_instanced.vs @@ -0,0 +1,50 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +// vertex attributes +in vec3 v_position; +in vec3 v_normal; +// instance attributes +in vec3 i_offset; +in vec2 i_scales; + +// x = tainted, y = specular; +out vec2 intensity; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 eye_normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0); + vec4 eye_position = view_model_matrix * world_position; + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + gl_Position = projection_matrix * eye_position; +} diff --git a/resources/shaders/140/imgui.fs b/resources/shaders/140/imgui.fs new file mode 100644 index 0000000000..8e7999fdfa --- /dev/null +++ b/resources/shaders/140/imgui.fs @@ -0,0 +1,11 @@ +#version 110 + +uniform sampler2D Texture; + +in vec2 Frag_UV; +in vec4 Frag_Color; + +void main() +{ + gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st); +} \ No newline at end of file diff --git a/resources/shaders/140/imgui.vs b/resources/shaders/140/imgui.vs new file mode 100644 index 0000000000..fd743bdf2d --- /dev/null +++ b/resources/shaders/140/imgui.vs @@ -0,0 +1,17 @@ +#version 140 + +uniform mat4 ProjMtx; + +in vec2 Position; +in vec2 UV; +in vec4 Color; + +out vec2 Frag_UV; +out vec4 Frag_Color; + +void main() +{ + Frag_UV = UV; + Frag_Color = Color; + gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0); +} \ No newline at end of file diff --git a/resources/shaders/140/mm_contour.fs b/resources/shaders/140/mm_contour.fs new file mode 100644 index 0000000000..3681d76c18 --- /dev/null +++ b/resources/shaders/140/mm_contour.fs @@ -0,0 +1,13 @@ +#version 140 + +const float EPSILON = 0.0001; + +uniform vec4 uniform_color; + +void main() +{ + gl_FragColor = uniform_color; + // Values inside depth buffer for fragments of the contour of a selected area are offset + // by small epsilon to solve z-fighting between painted triangles and contour lines. + gl_FragDepth = gl_FragCoord.z - EPSILON; +} diff --git a/resources/shaders/140/mm_contour.vs b/resources/shaders/140/mm_contour.vs new file mode 100644 index 0000000000..7042671de2 --- /dev/null +++ b/resources/shaders/140/mm_contour.vs @@ -0,0 +1,11 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; + +void main() +{ + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/mm_gouraud.fs b/resources/shaders/140/mm_gouraud.fs new file mode 100644 index 0000000000..e59d844f26 --- /dev/null +++ b/resources/shaders/140/mm_gouraud.fs @@ -0,0 +1,63 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); +const float EPSILON = 0.0001; + +uniform vec4 uniform_color; + +uniform bool volume_mirrored; + +uniform mat4 view_model_matrix; +uniform mat3 normal_matrix; + +in vec3 clipping_planes_dots; +in vec4 model_pos; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + vec3 color = uniform_color.rgb; + float alpha = uniform_color.a; + + vec3 triangle_normal = normalize(cross(dFdx(model_pos.xyz), dFdy(model_pos.xyz))); +#ifdef FLIP_TRIANGLE_NORMALS + triangle_normal = -triangle_normal; +#endif + + if (volume_mirrored) + triangle_normal = -triangle_normal; + + // First transform the normal into camera space and normalize the result. + vec3 eye_normal = normalize(normal_matrix * triangle_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); + + // x = diffuse, y = specular; + vec2 intensity = vec2(0.0); + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec3 position = (view_model_matrix * model_pos).xyz; + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); +} diff --git a/resources/shaders/140/mm_gouraud.vs b/resources/shaders/140/mm_gouraud.vs new file mode 100644 index 0000000000..30223f4eec --- /dev/null +++ b/resources/shaders/140/mm_gouraud.vs @@ -0,0 +1,28 @@ +#version 140 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +uniform mat4 volume_world_matrix; +// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. +uniform vec2 z_range; +// Clipping plane - general orientation. Used by the SLA gizmo. +uniform vec4 clipping_plane; + +in vec3 v_position; + +out vec3 clipping_planes_dots; +out vec4 model_pos; + +void main() +{ + model_pos = vec4(v_position, 1.0); + // Point in homogenous coordinates. + vec4 world_pos = volume_world_matrix * model_pos; + + gl_Position = projection_matrix * view_model_matrix * model_pos; + // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. + clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); +} diff --git a/resources/shaders/140/printbed.fs b/resources/shaders/140/printbed.fs new file mode 100644 index 0000000000..73ff8f6909 --- /dev/null +++ b/resources/shaders/140/printbed.fs @@ -0,0 +1,34 @@ +#version 140 + +const vec3 back_color_dark = vec3(0.235, 0.235, 0.235); +const vec3 back_color_light = vec3(0.365, 0.365, 0.365); + +uniform sampler2D texture; +uniform bool transparent_background; +uniform bool svg_source; + +in vec2 tex_coord; + +vec4 svg_color() +{ + // takes foreground from texture + vec4 fore_color = texture2D(texture, tex_coord); + + // calculates radial gradient + vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5))))); + + // blends foreground with background + return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0); +} + +vec4 non_svg_color() +{ + // takes foreground from texture + vec4 color = texture2D(texture, tex_coord); + return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); +} + +void main() +{ + gl_FragColor = svg_source ? svg_color() : non_svg_color(); +} \ No newline at end of file diff --git a/resources/shaders/140/printbed.vs b/resources/shaders/140/printbed.vs new file mode 100644 index 0000000000..57d8ca3b7c --- /dev/null +++ b/resources/shaders/140/printbed.vs @@ -0,0 +1,15 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; + +in vec3 v_position; +in vec2 v_tex_coord; + +out vec2 tex_coord; + +void main() +{ + tex_coord = v_tex_coord; + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/toolpaths_cog.fs b/resources/shaders/140/toolpaths_cog.fs new file mode 100644 index 0000000000..1c745dda99 --- /dev/null +++ b/resources/shaders/140/toolpaths_cog.fs @@ -0,0 +1,19 @@ +#version 140 + +const vec4 BLACK = vec4(vec3(0.1), 1.0); +const vec4 WHITE = vec4(vec3(1.0), 1.0); + +const float emission_factor = 0.25; + +uniform vec3 world_center; + +// x = tainted, y = specular; +in vec2 intensity; +in vec3 world_position; + +void main() +{ + vec3 delta = world_position - world_center; + vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE; + gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0); +} diff --git a/resources/shaders/140/toolpaths_cog.vs b/resources/shaders/140/toolpaths_cog.vs new file mode 100644 index 0000000000..ef676a3751 --- /dev/null +++ b/resources/shaders/140/toolpaths_cog.vs @@ -0,0 +1,47 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; + +in vec3 v_position; +in vec3 v_normal; + +// x = tainted, y = specular; +out vec2 intensity; +out vec3 world_position; + +void main() +{ + // First transform the normal into camera space and normalize the result. + vec3 normal = normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + world_position = v_position; + gl_Position = projection_matrix * position; +} diff --git a/resources/shaders/140/variable_layer_height.fs b/resources/shaders/140/variable_layer_height.fs new file mode 100644 index 0000000000..5fa7e6835f --- /dev/null +++ b/resources/shaders/140/variable_layer_height.fs @@ -0,0 +1,41 @@ +#version 140 + +#define M_PI 3.1415926535897932384626433832795 + +// 2D texture (1D texture split by the rows) of color along the object Z axis. +uniform sampler2D z_texture; +// Scaling from the Z texture rows coordinate to the normalized texture row coordinate. +uniform float z_to_texture_row; +uniform float z_texture_row_to_normalized; +uniform float z_cursor; +uniform float z_cursor_band_width; + +// x = tainted, y = specular; +in vec2 intensity; + +in float object_z; + +void main() +{ + float object_z_row = z_to_texture_row * object_z; + // Index of the row in the texture. + float z_texture_row = floor(object_z_row); + // Normalized coordinate from 0. to 1. + float z_texture_col = object_z_row - z_texture_row; + float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25; + // Calculate level of detail from the object Z coordinate. + // This makes the slowly sloping surfaces to be shown with high detail (with stripes), + // and the vertical surfaces to be shown with low detail (no stripes) + float z_in_cells = object_z_row * 190.; + // Gradient of Z projected on the screen. + float dx_vtc = dFdx(z_in_cells); + float dy_vtc = dFdy(z_in_cells); + float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.); + // Sample the Z texture. Texture coordinates are normalized to <0, 1>. + vec4 color = vec4(0.25, 0.25, 0.25, 1.0); + if (z_texture_row >= 0.0) + color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.), + texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod); + // Mix the final color. + gl_FragColor = vec4(vec3(intensity.y), 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend); +} diff --git a/resources/shaders/140/variable_layer_height.vs b/resources/shaders/140/variable_layer_height.vs new file mode 100644 index 0000000000..dd463b9c7a --- /dev/null +++ b/resources/shaders/140/variable_layer_height.vs @@ -0,0 +1,60 @@ +#version 140 + +#define INTENSITY_CORRECTION 0.6 + +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) +//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION) +//#define LIGHT_FRONT_SHININESS 5.0 + +#define INTENSITY_AMBIENT 0.3 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat3 normal_matrix; +uniform mat4 volume_world_matrix; +uniform float object_max_z; + +in vec3 v_position; +in vec3 v_normal; +in vec2 v_tex_coord; + +// x = tainted, y = specular; +out vec2 intensity; + +out float object_z; + +void main() +{ + // ===================================================== + // NOTE: + // when object_max_z > 0.0 we are rendering the overlay + // when object_max_z == 0.0 we are rendering the volumes + // ===================================================== + + // First transform the normal into camera space and normalize the result. + vec3 normal = (object_max_z > 0.0) ? vec3(0.0, 0.0, 1.0) : normalize(normal_matrix * v_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; + vec4 position = view_model_matrix * vec4(v_position, 1.0); + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular) + NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); + + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + + // Scaled to widths of the Z texture. + object_z = (object_max_z > 0.0) ? object_max_z * v_tex_coord.y : (volume_world_matrix * vec4(v_position, 1.0)).z; + + gl_Position = projection_matrix * position; +} diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 3cbebfff8c..66fa8fb92a 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -130,11 +130,7 @@ void Bed3D::Axes::render() if (!m_arrow.is_initialized()) m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length)); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -620,11 +616,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas) #if ENABLE_LEGACY_OPENGL_REMOVAL init_triangles(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("printbed_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("printbed"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -748,11 +740,7 @@ void Bed3D::render_model() } if (!m_model.get_filename().empty()) { -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); shader->set_uniform("emission_factor", 0.0f); @@ -816,11 +804,7 @@ void Bed3D::render_default(bool bottom, bool picking) init_gridlines(); init_triangles(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 50e488686e..c9fb05439e 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1085,14 +1085,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab return; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat_attr"); - GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat_attr"); - assert(boost::algorithm::iends_with(shader->get_name(), "_attr")); -#else GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat"); GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_LEGACY_OPENGL_REMOVAL if (type == ERenderType::Transparent) { diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 5372d4565b..acb1ba4d00 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -184,11 +184,7 @@ void GCodeViewer::COG::render() init(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -331,11 +327,7 @@ void GCodeViewer::SequentialView::Marker::render() if (!m_visible) return; -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -703,11 +695,7 @@ void GCodeViewer::init() #if !DISABLE_GCODEVIEWER_INSTANCED_MODELS if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel; -#if ENABLE_GL_SHADERS_ATTRIBUTES - buffer.shader = "gouraud_light_instanced_attr"; -#else buffer.shader = "gouraud_light_instanced"; -#endif // ENABLE_GL_SHADERS_ATTRIBUTES buffer.model.model.init_from(diamond(16)); buffer.model.color = option_color(type); buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel; @@ -716,12 +704,7 @@ void GCodeViewer::init() #endif // !DISABLE_GCODEVIEWER_INSTANCED_MODELS buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel; buffer.vertices.format = VBuffer::EFormat::PositionNormal3; -#if ENABLE_GL_SHADERS_ATTRIBUTES - buffer.shader = "gouraud_light_attr"; -#else buffer.shader = "gouraud_light"; -#endif // ENABLE_GL_SHADERS_ATTRIBUTES - buffer.model.data = diamond(16); buffer.model.color = option_color(type); buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel; @@ -734,18 +717,14 @@ void GCodeViewer::init() case EMoveType::Extrude: { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; buffer.vertices.format = VBuffer::EFormat::PositionNormal3; -#if ENABLE_GL_SHADERS_ATTRIBUTES - buffer.shader = "gouraud_light_attr"; -#else buffer.shader = "gouraud_light"; -#endif // ENABLE_GL_SHADERS_ATTRIBUTES break; } case EMoveType::Travel: { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line; #if ENABLE_GL_SHADERS_ATTRIBUTES buffer.vertices.format = VBuffer::EFormat::Position; - buffer.shader = "flat_attr"; + buffer.shader = "flat"; #else buffer.vertices.format = VBuffer::EFormat::PositionNormal3; buffer.shader = "toolpaths_lines"; @@ -3161,11 +3140,8 @@ void GCodeViewer::render_toolpaths() const int position_id = shader->get_attrib_location("v_position"); const int normal_id = shader->get_attrib_location("v_normal"); #else - switch (buffer.render_primitive_type) { - case TBuffer::ERenderPrimitiveType::Point: shader_init_as_points(*shader); break; - case TBuffer::ERenderPrimitiveType::Line: shader_init_as_lines(*shader); break; - default: break; - } + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Line) + shader_init_as_lines(*shader); #endif // ENABLE_GL_SHADERS_ATTRIBUTES const int uniform_color = shader->get_uniform_location("uniform_color"); @@ -3322,11 +3298,7 @@ void GCodeViewer::render_shells() if (!m_shells.visible || m_shells.volumes.empty()) return; -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 91add7c567..1649d2082a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -161,11 +161,7 @@ void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id) bool GLCanvas3D::LayersEditing::is_allowed() const { -#if ENABLE_GL_SHADERS_ATTRIBUTES - return wxGetApp().get_shader("variable_layer_height_attr") != nullptr && m_z_texture_id > 0; -#else return wxGetApp().get_shader("variable_layer_height") != nullptr && m_z_texture_id > 0; -#endif // ENABLE_GL_SHADERS_ATTRIBUTES } bool GLCanvas3D::LayersEditing::is_enabled() const @@ -328,11 +324,7 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas) bool GLCanvas3D::LayersEditing::is_initialized() const { -#if ENABLE_GL_SHADERS_ATTRIBUTES - return wxGetApp().get_shader("variable_layer_height_attr") != nullptr; -#else return wxGetApp().get_shader("variable_layer_height") != nullptr; -#endif // ENABLE_GL_SHADERS_ATTRIBUTES } std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) const @@ -375,11 +367,8 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3 return; const float cnv_inv_width = 1.0f / cnv_width; - - GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr"); -#else - GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height"); #endif // ENABLE_GL_SHADERS_ATTRIBUTES + GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height"); if (shader == nullptr) return; @@ -550,11 +539,7 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect) m_profile.profile.init_from(std::move(init_data)); } -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -594,11 +579,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G if (current_shader != nullptr) current_shader->stop_using(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -1075,11 +1056,7 @@ void GLCanvas3D::SequentialPrintClearance::render() const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f }; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -4608,11 +4585,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const camera.apply_projection(volumes_box, near_z, far_z); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -5551,11 +5524,7 @@ void GLCanvas3D::_render_background() m_background.init_from(std::move(init_data)); } -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("background_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("background"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); shader->set_uniform("top_color", use_error_color ? ERROR_BG_LIGHT_COLOR : DEFAULT_BG_LIGHT_COLOR); @@ -5681,11 +5650,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type) m_volumes.set_show_non_manifold_edges(!m_gizmos.is_hiding_instances() && m_gizmos.get_current_type() != GLGizmosManager::Simplify); #endif // ENABLE_SHOW_NON_MANIFOLD_EDGES -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); @@ -5910,11 +5875,7 @@ void GLCanvas3D::_render_overlays() void GLCanvas3D::_render_volumes_for_picking() const { #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -6137,11 +6098,7 @@ void GLCanvas3D::_render_camera_target() } } -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -6322,11 +6279,7 @@ void GLCanvas3D::_render_sla_slices() } #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index b81287ecee..4297a90910 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -935,11 +935,7 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance GLShaderProgram* shader = wxGetApp().get_current_shader(); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced_attr")) -#else if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced")) -#endif // ENABLE_GL_SHADERS_ATTRIBUTES return; // vertex attributes diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index 19327b33a7..a8be0f84e2 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -131,11 +131,7 @@ namespace GUI { glsafe(::glEnable(GL_LINE_STIPPLE)); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 9f0b03ea0e..a01c39864a 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -35,14 +35,15 @@ std::pair GLShadersManager::init() #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_GL_SHADERS_ATTRIBUTES + const std::string prefix = !GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/"; // imgui shader - valid &= append_shader("imgui", { "imgui.vs", "imgui.fs" }); + valid &= append_shader("imgui", { prefix + "imgui.vs", prefix + "imgui.fs" }); // basic shader, used to render all what was previously rendered using the immediate mode - valid &= append_shader("flat_attr", { "flat_attr.vs", "flat.fs" }); + valid &= append_shader("flat", { prefix + "flat.vs", prefix + "flat.fs" }); // basic shader for textures, used to render textures - valid &= append_shader("flat_texture_attr", { "flat_texture_attr.vs", "flat_texture.fs" }); + valid &= append_shader("flat_texture", { prefix + "flat_texture.vs", prefix + "flat_texture.fs" }); // used to render 3D scene background - valid &= append_shader("background_attr", { "background_attr.vs", "background.fs" }); + valid &= append_shader("background", { prefix + "background.vs", prefix + "background.fs" }); #else // basic shader, used to render all what was previously rendered using the immediate mode valid &= append_shader("flat", { "flat.vs", "flat.fs" }); @@ -55,16 +56,16 @@ std::pair GLShadersManager::init() #if ENABLE_SHOW_TOOLPATHS_COG // used to render toolpaths center of gravity #if ENABLE_GL_SHADERS_ATTRIBUTES - valid &= append_shader("toolpaths_cog_attr", { "toolpaths_cog_attr.vs", "toolpaths_cog.fs" }); + valid &= append_shader("toolpaths_cog", { prefix + "toolpaths_cog.vs", prefix + "toolpaths_cog.fs" }); #else valid &= append_shader("toolpaths_cog", { "toolpaths_cog.vs", "toolpaths_cog.fs" }); #endif // ENABLE_GL_SHADERS_ATTRIBUTES #endif // ENABLE_SHOW_TOOLPATHS_COG #if ENABLE_GL_SHADERS_ATTRIBUTES // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview - valid &= append_shader("gouraud_light_attr", { "gouraud_light_attr.vs", "gouraud_light.fs" }); + valid &= append_shader("gouraud_light", { prefix + "gouraud_light.vs", prefix + "gouraud_light.fs" }); // used to render printbed - valid &= append_shader("printbed_attr", { "printbed_attr.vs", "printbed.fs" }); + valid &= append_shader("printbed", { prefix + "printbed.vs", prefix + "printbed.fs" }); #else // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" }); @@ -74,14 +75,14 @@ std::pair GLShadersManager::init() // used to render options in gcode preview if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { #if ENABLE_GL_SHADERS_ATTRIBUTES - valid &= append_shader("gouraud_light_instanced_attr", { "gouraud_light_instanced_attr.vs", "gouraud_light_instanced.fs" }); + valid &= append_shader("gouraud_light_instanced", { prefix + "gouraud_light_instanced.vs", prefix + "gouraud_light_instanced.fs" }); #else valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); #endif // ENABLE_GL_SHADERS_ATTRIBUTES } #if ENABLE_GL_SHADERS_ATTRIBUTES // used to render objects in 3d editor - valid &= append_shader("gouraud_attr", { "gouraud_attr.vs", "gouraud.fs" } + valid &= append_shader("gouraud", { prefix + "gouraud.vs", prefix + "gouraud.fs" } #else // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); @@ -94,9 +95,9 @@ std::pair GLShadersManager::init() ); #if ENABLE_GL_SHADERS_ATTRIBUTES // used to render variable layers heights in 3d editor - valid &= append_shader("variable_layer_height_attr", { "variable_layer_height_attr.vs", "variable_layer_height.fs" }); + valid &= append_shader("variable_layer_height", { prefix + "variable_layer_height.vs", prefix + "variable_layer_height.fs" }); // used to render highlight contour around selected triangles inside the multi-material gizmo - valid &= append_shader("mm_contour_attr", { "mm_contour_attr.vs", "mm_contour_attr.fs" }); + valid &= append_shader("mm_contour", { prefix + "mm_contour.vs", prefix + "mm_contour.fs" }); #else // used to render variable layers heights in 3d editor valid &= append_shader("variable_layer_height", { "variable_layer_height.vs", "variable_layer_height.fs" }); @@ -111,9 +112,9 @@ std::pair GLShadersManager::init() // triangle normals inside fragment shader have the right direction. #if ENABLE_GL_SHADERS_ATTRIBUTES if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) - valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" }, { "FLIP_TRIANGLE_NORMALS"sv }); + valid &= append_shader("mm_gouraud", { prefix + "mm_gouraud.vs", prefix + "mm_gouraud.fs" }, { "FLIP_TRIANGLE_NORMALS"sv }); else - valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" }); + valid &= append_shader("mm_gouraud", { prefix + "mm_gouraud.vs", prefix + "mm_gouraud.fs" }); #else if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12) valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv}); diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp index 064ca1a18b..137a0a1096 100644 --- a/src/slic3r/GUI/GLTexture.cpp +++ b/src/slic3r/GUI/GLTexture.cpp @@ -358,11 +358,7 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right, GLModel model; model.init_from(std::move(init_data)); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_texture_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat_texture"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 83aed42893..aacecb6efe 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -134,11 +134,7 @@ void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const void GLGizmoBase::render_grabbers(float size) const { -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; shader->start_using(); @@ -153,11 +149,7 @@ void GLGizmoBase::render_grabbers(float size) const void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 5c9b08a93c..9a87d5a459 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -107,11 +107,7 @@ void GLGizmoCut::on_render() glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); const Vec3d diff = plane_center - m_old_center; @@ -197,11 +193,7 @@ void GLGizmoCut::on_render() shader->stop_using(); } -#if ENABLE_GL_SHADERS_ATTRIBUTES - shader = wxGetApp().get_shader("gouraud_light_attr"); -#else shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else glsafe(::glColor3f(1.0, 1.0, 0.0)); ::glBegin(GL_LINES); @@ -222,11 +214,7 @@ void GLGizmoCut::on_render() } #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - shader = wxGetApp().get_shader("flat_attr"); -#else shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index 48c81bc5a1..aa291f6231 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -105,11 +105,7 @@ void GLGizmoFlatten::on_render() const Selection& selection = m_parent.get_selection(); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -165,11 +161,7 @@ void GLGizmoFlatten::on_render_for_picking() const Selection& selection = m_parent.get_selection(); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index e979297df7..88b319f252 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -104,11 +104,7 @@ void GLGizmoHollow::on_render_for_picking() void GLGizmoHollow::render_points(const Selection& selection, bool picking) { #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 49eb8cb95b..308100d7fe 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -170,11 +170,7 @@ void GLGizmoMmuSegmentation::data_changed() void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const { ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - auto* shader = wxGetApp().get_shader("mm_gouraud_attr"); -#else auto *shader = wxGetApp().get_shader("mm_gouraud"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (!shader) return; shader->start_using(); @@ -598,16 +594,13 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui) auto *shader = wxGetApp().get_current_shader(); if (!shader) return; + assert(shader->get_name() == "mm_gouraud"); #if ENABLE_GL_SHADERS_ATTRIBUTES - assert(shader->get_name() == "mm_gouraud_attr"); - const Camera& camera = wxGetApp().plater()->get_camera(); const Transform3d view_model_matrix = camera.get_view_matrix() * matrix; shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); -#else - assert(shader->get_name() == "mm_gouraud"); #endif // ENABLE_GL_SHADERS_ATTRIBUTES for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 18acf6e9be..a798122ec1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -154,11 +154,7 @@ void GLGizmoMove3D::on_render() if (m_hover_id == -1) { #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -199,11 +195,7 @@ void GLGizmoMove3D::on_render() else { // draw axis #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); @@ -217,11 +209,7 @@ void GLGizmoMove3D::on_render() shader->stop_using(); } -#if ENABLE_GL_SHADERS_ATTRIBUTES - shader = wxGetApp().get_shader("gouraud_light_attr"); -#else shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data())); ::glBegin(GL_LINES); @@ -286,11 +274,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size)); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); #endif // ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 03d60440ad..01dc595148 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -80,11 +80,7 @@ GLGizmoPainterBase::ClippingPlaneDataWrapper GLGizmoPainterBase::get_clipping_pl void GLGizmoPainterBase::render_triangles(const Selection& selection) const { -#if ENABLE_GL_SHADERS_ATTRIBUTES - auto* shader = wxGetApp().get_shader("gouraud_attr"); -#else auto* shader = wxGetApp().get_shader("gouraud"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (! shader) return; shader->start_using(); @@ -250,11 +246,7 @@ void GLGizmoPainterBase::render_cursor_circle() m_circle.init_from(std::move(init_data)); } -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = GUI::wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -292,11 +284,7 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const #endif // ENABLE_LEGACY_OPENGL_REMOVAL } -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -927,11 +915,9 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) auto* shader = wxGetApp().get_current_shader(); if (! shader) return; -#if ENABLE_GL_SHADERS_ATTRIBUTES - assert(shader->get_name() == "gouraud_attr"); -#else + assert(shader->get_name() == "gouraud"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES + ScopeGuard guard([shader]() { if (shader) shader->set_uniform("offset_depth_buffer", false);}); shader->set_uniform("offset_depth_buffer", true); for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color), @@ -1288,11 +1274,7 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) if (curr_shader != nullptr) curr_shader->stop_using(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); @@ -1375,11 +1357,7 @@ void TriangleSelectorGUI::render_paint_contour() if (curr_shader != nullptr) curr_shader->stop_using(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - auto* contour_shader = wxGetApp().get_shader("mm_contour_attr"); -#else auto* contour_shader = wxGetApp().get_shader("mm_contour"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (contour_shader != nullptr) { contour_shader->start_using(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 1d817b58bc..6bec8be50e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -172,11 +172,7 @@ void GLGizmoRotate::on_render() glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f)); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); @@ -576,11 +572,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick const double size = m_dragging ? double(m_grabbers.front().get_dragging_half_size(mean_size)) : double(m_grabbers.front().get_half_size(mean_size)); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 373a2396d8..26c9251b4a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -265,11 +265,7 @@ void GLGizmoScale3D::on_render() if (m_hover_id == -1) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -316,11 +312,7 @@ void GLGizmoScale3D::on_render() else if (m_hover_id == 0 || m_hover_id == 1) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -333,11 +325,7 @@ void GLGizmoScale3D::on_render() } // draw grabbers -#if ENABLE_GL_SHADERS_ATTRIBUTES - shader = wxGetApp().get_shader("gouraud_light_attr"); -#else shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else // draw connection glsafe(::glColor4fv(m_grabbers[0].color.data())); @@ -357,11 +345,7 @@ void GLGizmoScale3D::on_render() else if (m_hover_id == 2 || m_hover_id == 3) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -374,11 +358,7 @@ void GLGizmoScale3D::on_render() } // draw grabbers -#if ENABLE_GL_SHADERS_ATTRIBUTES - shader = wxGetApp().get_shader("gouraud_light_attr"); -#else shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else // draw connection glsafe(::glColor4fv(m_grabbers[2].color.data())); @@ -398,11 +378,7 @@ void GLGizmoScale3D::on_render() else if (m_hover_id == 4 || m_hover_id == 5) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -415,11 +391,7 @@ void GLGizmoScale3D::on_render() } // draw grabbers -#if ENABLE_GL_SHADERS_ATTRIBUTES - shader = wxGetApp().get_shader("gouraud_light_attr"); -#else shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else // draw connection glsafe(::glColor4fv(m_grabbers[4].color.data())); @@ -439,11 +411,7 @@ void GLGizmoScale3D::on_render() else if (m_hover_id >= 6) { #if ENABLE_LEGACY_OPENGL_REMOVAL // draw connections -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES @@ -459,11 +427,7 @@ void GLGizmoScale3D::on_render() } // draw grabbers -#if ENABLE_GL_SHADERS_ATTRIBUTES - shader = wxGetApp().get_shader("gouraud_light_attr"); -#else shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES #else // draw connection glsafe(::glColor4fv(m_drag_color.data())); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 1a383187c6..bce1123e00 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -737,14 +737,11 @@ void GLGizmoSimplify::on_render() GLModel &glmodel = it->second; const Transform3d trafo_matrix = selected_volume->world_matrix(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - auto* gouraud_shader = wxGetApp().get_shader("gouraud_light_attr"); -#else +#if !ENABLE_GL_SHADERS_ATTRIBUTES glsafe(::glPushMatrix()); glsafe(::glMultMatrixd(trafo_matrix.data())); - - auto *gouraud_shader = wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES +#endif // !ENABLE_GL_SHADERS_ATTRIBUTES + auto* gouraud_shader = wxGetApp().get_shader("gouraud_light"); glsafe(::glPushAttrib(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST)); gouraud_shader->start_using(); @@ -759,11 +756,7 @@ void GLGizmoSimplify::on_render() gouraud_shader->stop_using(); if (m_show_wireframe) { -#if ENABLE_GL_SHADERS_ATTRIBUTES - auto* contour_shader = wxGetApp().get_shader("mm_contour_attr"); -#else auto *contour_shader = wxGetApp().get_shader("mm_contour"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES contour_shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES contour_shader->set_uniform("view_model_matrix", view_model_matrix); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 4007f0cb0b..7c61673b45 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -130,11 +130,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) return; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index e7e9ba2fbe..bbdcdeb346 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -87,11 +87,7 @@ void MeshClipper::render_cut() if (curr_shader != nullptr) curr_shader->stop_using(); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader != nullptr) { shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 68a052341a..7ccc6fc256 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1275,11 +1275,7 @@ void Selection::render_center(bool gizmo_is_dragging) return; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -1324,11 +1320,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field) return; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat_attr" : "gouraud_light_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; @@ -2020,11 +2012,7 @@ void Selection::render_bounding_box(const BoundingBoxf3 & box, float* color) con glsafe(::glLineWidth(2.0f * m_scale_factor)); -#if ENABLE_GL_SHADERS_ATTRIBUTES - GLShaderProgram* shader = wxGetApp().get_shader("flat_attr"); -#else GLShaderProgram* shader = wxGetApp().get_shader("flat"); -#endif // ENABLE_GL_SHADERS_ATTRIBUTES if (shader == nullptr) return; From c1e54675f53a100402b75a30b3061dd780d75955 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 21 Mar 2022 17:15:39 +0100 Subject: [PATCH 23/46] Prevent hard crash in rare circumstances --- src/slic3r/GUI/Jobs/BusyCursorJob.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Jobs/BusyCursorJob.hpp b/src/slic3r/GUI/Jobs/BusyCursorJob.hpp index 530213b1d5..8504d1eb93 100644 --- a/src/slic3r/GUI/Jobs/BusyCursorJob.hpp +++ b/src/slic3r/GUI/Jobs/BusyCursorJob.hpp @@ -4,6 +4,7 @@ #include "Job.hpp" #include +#include namespace Slic3r { namespace GUI { @@ -16,7 +17,11 @@ struct CursorSetterRAII } ~CursorSetterRAII() { - ctl.call_on_main_thread([] { wxEndBusyCursor(); }); + try { + ctl.call_on_main_thread([] { wxEndBusyCursor(); }); + } catch(...) { + BOOST_LOG_TRIVIAL(error) << "Can't revert cursor from busy to normal"; + } } }; From 9be3d926c5ff8debf25f22e2d53dd1410bfcdd79 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 22 Mar 2022 08:18:39 +0100 Subject: [PATCH 24/46] Tech ENABLE_LEGACY_OPENGL_REMOVAL - A few refactorings and fixes --- resources/shaders/140/flat_texture.fs | 2 +- resources/shaders/140/gouraud.fs | 2 +- resources/shaders/140/imgui.fs | 4 ++-- resources/shaders/140/printbed.fs | 4 ++-- .../shaders/140/variable_layer_height.fs | 4 ++-- src/slic3r/GUI/GLModel.cpp | 21 ++++++++++--------- src/slic3r/GUI/ImGuiWrapper.cpp | 19 ++++++++++------- 7 files changed, 30 insertions(+), 26 deletions(-) diff --git a/resources/shaders/140/flat_texture.fs b/resources/shaders/140/flat_texture.fs index 7db62b6822..dec946721e 100644 --- a/resources/shaders/140/flat_texture.fs +++ b/resources/shaders/140/flat_texture.fs @@ -6,5 +6,5 @@ in vec2 tex_coord; void main() { - gl_FragColor = texture2D(uniform_texture, tex_coord); + gl_FragColor = texture(uniform_texture, tex_coord); } diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs index 7651380d7d..beb3a947bb 100644 --- a/resources/shaders/140/gouraud.fs +++ b/resources/shaders/140/gouraud.fs @@ -74,7 +74,7 @@ void main() #ifdef ENABLE_ENVIRONMENT_MAP if (use_environment_tex) - gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); + gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha); else #endif gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); diff --git a/resources/shaders/140/imgui.fs b/resources/shaders/140/imgui.fs index 8e7999fdfa..4b2571749f 100644 --- a/resources/shaders/140/imgui.fs +++ b/resources/shaders/140/imgui.fs @@ -1,4 +1,4 @@ -#version 110 +#version 140 uniform sampler2D Texture; @@ -7,5 +7,5 @@ in vec4 Frag_Color; void main() { - gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st); + gl_FragColor = Frag_Color * texture(Texture, Frag_UV.st); } \ No newline at end of file diff --git a/resources/shaders/140/printbed.fs b/resources/shaders/140/printbed.fs index 73ff8f6909..86edd0daf4 100644 --- a/resources/shaders/140/printbed.fs +++ b/resources/shaders/140/printbed.fs @@ -12,7 +12,7 @@ in vec2 tex_coord; vec4 svg_color() { // takes foreground from texture - vec4 fore_color = texture2D(texture, tex_coord); + vec4 fore_color = texture(texture, tex_coord); // calculates radial gradient vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5))))); @@ -24,7 +24,7 @@ vec4 svg_color() vec4 non_svg_color() { // takes foreground from texture - vec4 color = texture2D(texture, tex_coord); + vec4 color = texture(texture, tex_coord); return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); } diff --git a/resources/shaders/140/variable_layer_height.fs b/resources/shaders/140/variable_layer_height.fs index 5fa7e6835f..cf1fc309cc 100644 --- a/resources/shaders/140/variable_layer_height.fs +++ b/resources/shaders/140/variable_layer_height.fs @@ -34,8 +34,8 @@ void main() // Sample the Z texture. Texture coordinates are normalized to <0, 1>. vec4 color = vec4(0.25, 0.25, 0.25, 1.0); if (z_texture_row >= 0.0) - color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.), - texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod); + color = mix(texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5 )), -10000.), + texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)), 10000.), lod); // Mix the final color. gl_FragColor = vec4(vec3(intensity.y), 1.0) + intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend); } diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 4297a90910..9c9d695260 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -861,7 +861,7 @@ void GLModel::render(const std::pair& range) #if ENABLE_GL_SHADERS_ATTRIBUTES position_id = shader->get_attrib_location("v_position"); if (position_id != -1) { - glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format))); + glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(position_id)); } #else @@ -873,7 +873,7 @@ void GLModel::render(const std::pair& range) #if ENABLE_GL_SHADERS_ATTRIBUTES normal_id = shader->get_attrib_location("v_normal"); if (normal_id != -1) { - glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format))); + glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(normal_id)); } #else @@ -885,7 +885,7 @@ void GLModel::render(const std::pair& range) #if ENABLE_GL_SHADERS_ATTRIBUTES tex_coord_id = shader->get_attrib_location("v_tex_coord"); if (tex_coord_id != -1) { - glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::tex_coord_offset_bytes(data.format))); + glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::tex_coord_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(tex_coord_id)); } #else @@ -930,7 +930,7 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const #endif // ENABLE_LEGACY_OPENGL_REMOVAL { - if (instances_vbo == 0) + if (instances_vbo == 0 || instances_count == 0) return; GLShaderProgram* shader = wxGetApp().get_current_shader(); @@ -970,11 +970,12 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instances_vbo)); #if ENABLE_LEGACY_OPENGL_REMOVAL - glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0)); + const size_t instance_stride = 5 * sizeof(float); + glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, instance_stride, (const void*)0)); glsafe(::glEnableVertexAttribArray(offset_id)); glsafe(::glVertexAttribDivisor(offset_id, 1)); - glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)(3 * sizeof(float)))); + glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, instance_stride, (const void*)(3 * sizeof(float)))); glsafe(::glEnableVertexAttribArray(scales_id)); glsafe(::glVertexAttribDivisor(scales_id, 1)); #else @@ -996,8 +997,6 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance const GLenum mode = get_primitive_mode(data.format); const GLenum index_type = get_index_type(data); - shader->set_uniform("uniform_color", data.color); - const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format); const bool position = Geometry::has_position(data.format); const bool normal = Geometry::has_normal(data.format); @@ -1005,15 +1004,17 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id)); if (position) { - glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format))); + glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(position_id)); } if (normal) { - glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format))); + glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format))); glsafe(::glEnableVertexAttribArray(normal_id)); } + shader->set_uniform("uniform_color", data.color); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id)); glsafe(::glDrawElementsInstanced(mode, indices_count(), index_type, (const void*)0, instances_count)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index e659a386bd..d5dfa276ce 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -1475,10 +1475,10 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) // We are using the OpenGL fixed pipeline to make the example code simpler to read! // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill. - GLint last_texture; glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture)); - GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode)); - GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport)); - GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box)); + GLint last_texture; glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture)); + GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode)); + GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport)); + GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box)); GLint last_texture_env_mode; glsafe(::glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_texture_env_mode)); glsafe(::glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT)); glsafe(::glEnable(GL_BLEND)); @@ -1553,17 +1553,17 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) const int position_id = shader->get_attrib_location("Position"); if (position_id != -1) { - glsafe(::glVertexAttribPointer(position_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos))); + glsafe(::glVertexAttribPointer(position_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, pos))); glsafe(::glEnableVertexAttribArray(position_id)); } const int uv_id = shader->get_attrib_location("UV"); if (uv_id != -1) { - glsafe(::glVertexAttribPointer(uv_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv))); + glsafe(::glVertexAttribPointer(uv_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, uv))); glsafe(::glEnableVertexAttribArray(uv_id)); } const int color_id = shader->get_attrib_location("Color"); if (color_id != -1) { - glsafe(::glVertexAttribPointer(color_id, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col))); + glsafe(::glVertexAttribPointer(color_id, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, col))); glsafe(::glEnableVertexAttribArray(color_id)); } #else @@ -1637,11 +1637,14 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data) glsafe(::glPopMatrix()); #endif // !ENABLE_GL_IMGUI_SHADERS glsafe(::glPopAttrib()); - glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1])); + glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); + glsafe(::glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]))); glsafe(::glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3])); glsafe(::glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3])); #if ENABLE_GL_IMGUI_SHADERS + shader->stop_using(); + if (curr_shader != nullptr) curr_shader->start_using(); #endif // ENABLE_GL_IMGUI_SHADERS From a0630420d9ed417a8848718702a6b01cc3c1975f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 22 Mar 2022 15:20:51 +0100 Subject: [PATCH 25/46] Tech ENABLE_LEGACY_OPENGL_REMOVAL - Calculation of camera projection matrix --- src/slic3r/GUI/Camera.cpp | 56 ++++++++++++++++++++++++++++------- src/slic3r/GUI/Camera.hpp | 2 ++ src/slic3r/GUI/GLCanvas3D.cpp | 6 ++++ 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 44b0cd84a1..d6272aea55 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -109,12 +109,14 @@ void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h) glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data())); } +#if !ENABLE_LEGACY_OPENGL_REMOVAL void Camera::apply_view_matrix() { glsafe(::glMatrixMode(GL_MODELVIEW)); glsafe(::glLoadIdentity()); glsafe(::glMultMatrixd(m_view_matrix.data())); } +#endif // !ENABLE_LEGACY_OPENGL_REMOVAL void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double far_z) { @@ -123,9 +125,11 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa const double old_distance = m_distance; m_frustrum_zs = calc_tight_frustrum_zs_around(box); +#if !ENABLE_LEGACY_OPENGL_REMOVAL if (m_distance != old_distance) // the camera has been moved re-apply view matrix apply_view_matrix(); +#endif // !ENABLE_LEGACY_OPENGL_REMOVAL if (near_z > 0.0) m_frustrum_zs.first = std::max(std::min(m_frustrum_zs.first, near_z), FrustrumMinNearZ); @@ -159,6 +163,35 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa } } +#if ENABLE_LEGACY_OPENGL_REMOVAL + switch (m_type) + { + default: + case EType::Ortho: + { + const double dz = m_frustrum_zs.second - m_frustrum_zs.first; + const double zz = m_frustrum_zs.first + m_frustrum_zs.second; + m_projection_matrix.matrix() << 1.0 / w, 0.0, 0.0, 0.0, + 0.0, 1.0 / h, 0.0, 0.0, + 0.0, 0.0, -2.0 / dz, -zz / dz, + 0.0, 0.0, 0.0, 1.0; + break; + } + case EType::Perspective: + { + const double n = m_frustrum_zs.first; + const double f = m_frustrum_zs.second; + const double dz = f - n; + const double zz = n + f; + const double fn = n * f; + m_projection_matrix.matrix() << n / w, 0.0, 0.0, 0.0, + 0.0, n / h, 0.0, 0.0, + 0.0, 0.0, -zz / dz, -2.0 * fn / dz, + 0.0, 0.0, -1.0, 0.0; + break; + } + } +#else glsafe(::glMatrixMode(GL_PROJECTION)); glsafe(::glLoadIdentity()); @@ -179,6 +212,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa glsafe(::glGetDoublev(GL_PROJECTION_MATRIX, m_projection_matrix.data())); glsafe(::glMatrixMode(GL_MODELVIEW)); +#endif // ENABLE_LEGACY_OPENGL_REMOVAL } void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor) @@ -298,8 +332,8 @@ std::pair Camera::calc_tight_frustrum_zs_around(const BoundingBo // box in eye space const BoundingBoxf3 eye_box = box.transformed(m_view_matrix); - near_z = -eye_box.max(2); - far_z = -eye_box.min(2); + near_z = -eye_box.max.z(); + far_z = -eye_box.min.z(); // apply margin near_z -= FrustrumZMargin; @@ -465,19 +499,19 @@ void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up m_distance = (position - target).norm(); const Vec3d new_position = m_target + m_distance * unit_z; - m_view_matrix(0, 0) = unit_x(0); - m_view_matrix(0, 1) = unit_x(1); - m_view_matrix(0, 2) = unit_x(2); + m_view_matrix(0, 0) = unit_x.x(); + m_view_matrix(0, 1) = unit_x.y(); + m_view_matrix(0, 2) = unit_x.z(); m_view_matrix(0, 3) = -unit_x.dot(new_position); - m_view_matrix(1, 0) = unit_y(0); - m_view_matrix(1, 1) = unit_y(1); - m_view_matrix(1, 2) = unit_y(2); + m_view_matrix(1, 0) = unit_y.x(); + m_view_matrix(1, 1) = unit_y.y(); + m_view_matrix(1, 2) = unit_y.z(); m_view_matrix(1, 3) = -unit_y.dot(new_position); - m_view_matrix(2, 0) = unit_z(0); - m_view_matrix(2, 1) = unit_z(1); - m_view_matrix(2, 2) = unit_z(2); + m_view_matrix(2, 0) = unit_z.x(); + m_view_matrix(2, 1) = unit_z.y(); + m_view_matrix(2, 2) = unit_z.z(); m_view_matrix(2, 3) = -unit_z.dot(new_position); m_view_matrix(3, 0) = 0.0; diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index a61eb44ec5..a1d7426882 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -92,7 +92,9 @@ public: double get_fov() const; void apply_viewport(int x, int y, unsigned int w, unsigned int h); +#if !ENABLE_LEGACY_OPENGL_REMOVAL void apply_view_matrix(); +#endif // !ENABLE_LEGACY_OPENGL_REMOVAL // Calculates and applies the projection matrix tighting the frustrum z range around the given box. // If larger z span is needed, pass the desired values of near and far z (negative values are ignored) void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1649d2082a..5539d681c4 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1662,13 +1662,17 @@ void GLCanvas3D::render() camera.requires_zoom_to_bed = false; } +#if !ENABLE_LEGACY_OPENGL_REMOVAL camera.apply_view_matrix(); +#endif // !ENABLE_LEGACY_OPENGL_REMOVAL camera.apply_projection(_max_bounding_box(true, true)); +#if !ENABLE_LEGACY_OPENGL_REMOVAL GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; glsafe(::glLightfv(GL_LIGHT1, GL_POSITION, position_cam)); GLfloat position_top[4] = { -0.5f, -0.5f, 1.0f, 0.0f }; glsafe(::glLightfv(GL_LIGHT0, GL_POSITION, position_top)); +#endif // !ENABLE_LEGACY_OPENGL_REMOVAL wxGetApp().imgui()->new_frame(); @@ -4561,7 +4565,9 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const camera.set_scene_box(scene_bounding_box()); camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); camera.zoom_to_box(volumes_box); +#if !ENABLE_LEGACY_OPENGL_REMOVAL camera.apply_view_matrix(); +#endif // !ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_GL_SHADERS_ATTRIBUTES const Transform3d& view_matrix = camera.get_view_matrix(); From 86641a481e0ad107eb5539205f0f449e61036814 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 22 Mar 2022 15:35:02 +0100 Subject: [PATCH 26/46] Fixed typo --- resources/shaders/140/printbed.fs | 9 +++++---- src/slic3r/GUI/GLShadersManager.cpp | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/resources/shaders/140/printbed.fs b/resources/shaders/140/printbed.fs index 86edd0daf4..6d927a749c 100644 --- a/resources/shaders/140/printbed.fs +++ b/resources/shaders/140/printbed.fs @@ -3,16 +3,17 @@ const vec3 back_color_dark = vec3(0.235, 0.235, 0.235); const vec3 back_color_light = vec3(0.365, 0.365, 0.365); -uniform sampler2D texture; +uniform sampler2D in_texture; uniform bool transparent_background; uniform bool svg_source; in vec2 tex_coord; +out vec4 frag_color; vec4 svg_color() { // takes foreground from texture - vec4 fore_color = texture(texture, tex_coord); + vec4 fore_color = texture(in_texture, tex_coord); // calculates radial gradient vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5))))); @@ -24,11 +25,11 @@ vec4 svg_color() vec4 non_svg_color() { // takes foreground from texture - vec4 color = texture(texture, tex_coord); + vec4 color = texture(in_texture, tex_coord); return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a); } void main() { - gl_FragColor = svg_source ? svg_color() : non_svg_color(); + frag_color = svg_source ? svg_color() : non_svg_color(); } \ No newline at end of file diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index a01c39864a..ab8dfb3e77 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -35,7 +35,7 @@ std::pair GLShadersManager::init() #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_GL_SHADERS_ATTRIBUTES - const std::string prefix = !GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/"; + const std::string prefix = GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/"; // imgui shader valid &= append_shader("imgui", { prefix + "imgui.vs", prefix + "imgui.fs" }); // basic shader, used to render all what was previously rendered using the immediate mode From 1d2339fbce896bff37c59f3040cce334a67cedb3 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 23 Mar 2022 08:18:23 +0100 Subject: [PATCH 27/46] Follow-up of a0630420d9ed417a8848718702a6b01cc3c1975f - Fixed warning --- src/slic3r/GUI/Camera.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index d6272aea55..77ce27a799 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -123,7 +123,9 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa double w = 0.0; double h = 0.0; +#if !ENABLE_LEGACY_OPENGL_REMOVAL const double old_distance = m_distance; +#endif // !ENABLE_LEGACY_OPENGL_REMOVAL m_frustrum_zs = calc_tight_frustrum_zs_around(box); #if !ENABLE_LEGACY_OPENGL_REMOVAL if (m_distance != old_distance) From 43124979e5665f6029d8f5a01704aa98c9064d2f Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 12 Jan 2022 16:21:16 +0100 Subject: [PATCH 28/46] app updater feature checks online version file offers download of new version of slicer download with notification opens instalator or target folder --- src/slic3r/CMakeLists.txt | 3 + src/slic3r/GUI/GUI_App.cpp | 149 +++++- src/slic3r/GUI/GUI_App.hpp | 10 +- src/slic3r/GUI/NotificationManager.cpp | 142 ++++- src/slic3r/GUI/NotificationManager.hpp | 34 +- src/slic3r/GUI/UpdateDialogs.cpp | 103 ++++ src/slic3r/GUI/UpdateDialogs.hpp | 48 ++ src/slic3r/Utils/AppUpdater.cpp | 694 +++++++++++++++++++++++++ src/slic3r/Utils/AppUpdater.hpp | 62 +++ src/slic3r/Utils/Http.cpp | 1 - src/slic3r/Utils/MacUtils.mm | 18 + src/slic3r/Utils/PresetUpdater.cpp | 18 +- src/slic3r/Utils/PresetUpdater.hpp | 4 +- 13 files changed, 1250 insertions(+), 36 deletions(-) create mode 100644 src/slic3r/Utils/AppUpdater.cpp create mode 100644 src/slic3r/Utils/AppUpdater.hpp create mode 100644 src/slic3r/Utils/MacUtils.mm diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index aa6268d885..ef7687f00f 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -213,6 +213,8 @@ set(SLIC3R_GUI_SOURCES GUI/DesktopIntegrationDialog.hpp GUI/HintNotification.cpp GUI/HintNotification.hpp + Utils/AppUpdater.cpp + Utils/AppUpdater.hpp Utils/Http.cpp Utils/Http.hpp Utils/FixModelByWin10.cpp @@ -250,6 +252,7 @@ if (APPLE) list(APPEND SLIC3R_GUI_SOURCES Utils/RetinaHelperImpl.mm Utils/MacDarkMode.mm + Utils/MacUtils.mm GUI/RemovableDriveManagerMM.mm GUI/RemovableDriveManagerMM.h GUI/Mouse3DHandlerMac.mm diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index ee91994252..3c0d52bd1e 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -57,6 +57,7 @@ #include "../Utils/PrintHost.hpp" #include "../Utils/Process.hpp" #include "../Utils/MacDarkMode.hpp" +#include "../Utils/AppUpdater.hpp" #include "slic3r/Config/Snapshot.hpp" #include "ConfigSnapshotDialog.hpp" #include "FirmwareDialog.hpp" @@ -816,18 +817,13 @@ void GUI_App::post_init() CallAfter([this] { bool cw_showed = this->config_wizard_startup(); this->preset_updater->sync(preset_bundle); + this->app_version_check(); if (! cw_showed) { // The CallAfter is needed as well, without it, GL extensions did not show. // Also, we only want to show this when the wizard does not, so the new user // sees something else than "we want something" on the first start. show_send_system_info_dialog_if_needed(); } - #ifdef _WIN32 - // Run external updater on Windows if version check is enabled. - if (this->preset_updater->version_check_enabled() && ! run_updater_win()) - // "prusaslicer-updater.exe" was not started, run our own update check. - #endif // _WIN32 - this->preset_updater->slic3r_update_notify(); }); } @@ -853,6 +849,8 @@ GUI_App::GUI_App(EAppMode mode) { //app config initializes early becasuse it is used in instance checking in PrusaSlicer.cpp this->init_app_config(); + // init app downloader after path to datadir is set + m_app_updater = std::make_unique(); } GUI_App::~GUI_App() @@ -1242,21 +1240,7 @@ bool GUI_App::on_init_inner() #endif // __WXMSW__ preset_updater = new PresetUpdater(); - Bind(EVT_SLIC3R_VERSION_ONLINE, [this](const wxCommandEvent& evt) { - app_config->set("version_online", into_u8(evt.GetString())); - app_config->save(); - std::string opt = app_config->get("notify_release"); - if (this->plater_ != nullptr && (opt == "all" || opt == "release")) { - if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) { - this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable - , NotificationManager::NotificationLevel::ImportantNotificationLevel - , Slic3r::format(_u8L("New release version %1% is available."), evt.GetString()) - , _u8L("See Download page.") - , [](wxEvtHandler* evnthndlr) {wxGetApp().open_web_page_localized("https://www.prusa3d.com/slicerweb"); return true; } - ); - } - } - }); + Bind(EVT_SLIC3R_VERSION_ONLINE, &GUI_App::on_version_read, this); Bind(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, [this](const wxCommandEvent& evt) { app_config->save(); if (this->plater_ != nullptr && app_config->get("notify_release") == "all") { @@ -1272,6 +1256,18 @@ bool GUI_App::on_init_inner() } } }); + Bind(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, [this](const wxCommandEvent& evt) { + if (this->plater_ != nullptr) + this->plater_->get_notification_manager()->set_download_progress_percentage((float)std::stoi(into_u8(evt.GetString())) / 100.f ); + }); + + Bind(EVT_SLIC3R_APP_DOWNLOAD_FAILED, [this](const wxCommandEvent& evt) { + if (this->plater_ != nullptr) + this->plater_->get_notification_manager()->close_notification_of_type(NotificationType::AppDownload); + show_error(nullptr, evt.GetString()); + }); + + } else { #ifdef __WXMSW__ @@ -2282,7 +2278,8 @@ void GUI_App::add_config_menu(wxMenuBar *menu) local_menu->Append(config_id_base + ConfigMenuWizard, config_wizard_name + dots, config_wizard_tooltip); local_menu->Append(config_id_base + ConfigMenuSnapshots, _L("&Configuration Snapshots") + dots, _L("Inspect / activate configuration snapshots")); local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _L("Take Configuration &Snapshot"), _L("Capture a configuration snapshot")); - local_menu->Append(config_id_base + ConfigMenuUpdate, _L("Check for Configuration Updates"), _L("Check for configuration updates")); + local_menu->Append(config_id_base + ConfigMenuUpdateConf, _L("Check for Configuration Updates"), _L("Check for configuration updates")); + local_menu->Append(config_id_base + ConfigMenuUpdateApp, _L("Check for Application Updates"), _L("Check for new version of application")); #if defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION) //if (DesktopIntegrationDialog::integration_possible()) local_menu->Append(config_id_base + ConfigMenuDesktopIntegration, _L("Desktop Integration"), _L("Desktop Integration")); @@ -2324,9 +2321,12 @@ void GUI_App::add_config_menu(wxMenuBar *menu) case ConfigMenuWizard: run_wizard(ConfigWizard::RR_USER); break; - case ConfigMenuUpdate: + case ConfigMenuUpdateConf: check_updates(true); break; + case ConfigMenuUpdateApp: + app_updater(true); + break; #ifdef __linux__ case ConfigMenuDesktopIntegration: show_desktop_integration_dialog(); @@ -3266,5 +3266,108 @@ void GUI_App::associate_gcode_files() } #endif // __WXMSW__ + +void GUI_App::on_version_read(wxCommandEvent& evt) +{ + + app_config->set("version_online", into_u8(evt.GetString())); + app_config->save(); + std::string opt = app_config->get("notify_release"); + if (this->plater_ == nullptr || (opt != "all" && opt != "release")) { + return; + } + if (*Semver::parse(SLIC3R_VERSION) >= *Semver::parse(into_u8(evt.GetString()))) { + return; + } + // notification + /* + this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable + , NotificationManager::NotificationLevel::ImportantNotificationLevel + , Slic3r::format(_u8L("New release version %1% is available."), evt.GetString()) + , _u8L("See Download page.") + , [](wxEvtHandler* evnthndlr) {wxGetApp().open_web_page_localized("https://www.prusa3d.com/slicerweb"); return true; } + ); + */ + // updater + + app_updater(false); +} + +void GUI_App::app_updater(bool from_user) +{ + DownloadAppData app_data = m_app_updater->get_app_data(); + + if (from_user && (!app_data.version || *app_data.version <= *Semver::parse(SLIC3R_VERSION))) + { + BOOST_LOG_TRIVIAL(info) << "There is no newer version online."; + MsgNoAppUpdates no_update_dialog; + no_update_dialog.ShowModal(); + return; + + } + + assert(!app_data.url.empty()); + assert(!app_data.target_path.empty()); + + // dialog with new version info + AppUpdateAvailableDialog dialog(*Semver::parse(SLIC3R_VERSION), *app_data.version); + auto dialog_result = dialog.ShowModal(); + // checkbox "do not show again" + if (dialog.disable_version_check()) { + app_config->set("notify_release", "none"); + } + // Doesn't wish to update + if (dialog_result != wxID_OK) { + return; + } + // dialog with new version download (installer or app dependent on system) + AppUpdateDownloadDialog dwnld_dlg(*app_data.version); + dialog_result = dwnld_dlg.ShowModal(); + // Doesn't wish to download + if (dialog_result != wxID_OK) { + return; + } + // Save as dialog + if (dwnld_dlg.select_download_path()) { + std::string extension = app_data.target_path.filename().extension().string(); + wxString wildcard; + if (!extension.empty()) { + extension = extension.substr(1); + wxString wxext = boost::nowide::widen(extension); + wildcard = GUI::format_wxstr("%1% Files (*.%2%)|*.%2%", wxext.Upper(), wxext); + } + wxFileDialog save_dlg( + plater() + , _L("Save as:") + , boost::nowide::widen(m_app_updater->get_default_dest_folder()) + , boost::nowide::widen(AppUpdater::get_filename_from_url(app_data.url)) + , wildcard + , wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + // Canceled + if (save_dlg.ShowModal() != wxID_OK) { + return; + // set path + } else { + app_data.target_path = boost::filesystem::path(save_dlg.GetPath().ToUTF8().data()); + } + } + if (boost::filesystem::exists(app_data.target_path)) + { + BOOST_LOG_TRIVIAL(error) << "App download: File on target path already exists and will be overwritten. Path: " << app_data.target_path; + } + // start download + this->plater_->get_notification_manager()->push_download_progress_notification(_utf8("Download"), std::bind(&AppUpdater::cancel_callback, this->m_app_updater.get())); + app_data.start_after = dwnld_dlg.run_after_download(); + m_app_updater->set_app_data(std::move(app_data)); + m_app_updater->sync_download(); +} + +void GUI_App::app_version_check() +{ + std::string version_check_url = app_config->version_check_url(); + m_app_updater->sync_version(version_check_url); +} + } // GUI } //Slic3r diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index f93728d2e3..4df41c607d 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -32,6 +32,7 @@ class PresetUpdater; class ModelObject; class PrintHostJobQueue; class Model; +class AppUpdater; namespace GUI{ @@ -81,7 +82,8 @@ enum ConfigMenuIDs { ConfigMenuWizard, ConfigMenuSnapshots, ConfigMenuTakeSnapshot, - ConfigMenuUpdate, + ConfigMenuUpdateConf, + ConfigMenuUpdateApp, ConfigMenuDesktopIntegration, ConfigMenuPreferences, ConfigMenuModeSimple, @@ -156,6 +158,7 @@ private: std::unique_ptr m_imgui; std::unique_ptr m_printhost_job_queue; std::unique_ptr m_other_instance_message_handler; + std::unique_ptr m_app_updater; std::unique_ptr m_single_instance_checker; std::string m_instance_hash_string; size_t m_instance_hash_int; @@ -360,6 +363,11 @@ private: // Returns true if the configuration is fine. // Returns true if the configuration is not compatible and the user decided to rather close the slicer instead of reconfiguring. bool check_updates(const bool verbose); + void on_version_read(wxCommandEvent& evt); + // if the data from version file are already downloaded, shows dialogs to start download of new version of app + void app_updater(bool from_user); + // inititate read of version file online in separate thread + void app_version_check(); bool m_datadir_redefined { false }; }; diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 6e9bc267fd..9374ea17fa 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -819,6 +819,120 @@ void NotificationManager::ProgressBarNotification::render_bar(ImGuiWrapper& imgu imgui.text(text.c_str()); } } +//------ProgressBarWithCancelNotification---------------- + +void NotificationManager::ProgressBarWithCancelNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) +{ + if (m_percentage < 0.f || m_percentage >= 1.f) + render_close_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); + else + render_cancel_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); +} +void NotificationManager::ProgressBarWithCancelNotification::render_close_button_inner(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) +{ + ImVec2 win_size(win_size_x, win_size_y); + ImVec2 win_pos(win_pos_x, win_pos_y); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); + push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); + push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); + + + std::string button_text; + button_text = ImGui::CloseNotifButton; + + if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y), + ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)), + true)) + { + button_text = ImGui::CloseNotifHoverButton; + } + ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str()); + ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f); + ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f); + ImGui::SetCursorPosY(win_size.y / 2 - button_size.y); + if (imgui.button(button_text.c_str(), button_size.x, button_size.y)) + { + close(); + } + + //invisible large button + ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f); + ImGui::SetCursorPosY(0); + if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0))) + { + close(); + } + ImGui::PopStyleColor(5); + +} + +void NotificationManager::ProgressBarWithCancelNotification::render_cancel_button_inner(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) +{ + ImVec2 win_size(win_size_x, win_size_y); + ImVec2 win_pos(win_pos_x, win_pos_y); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f)); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f)); + push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); + push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f)); + + + std::string button_text; + button_text = ImGui::CancelButton; + + if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y), + ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)), + true)) + { + button_text = ImGui::CancelHoverButton; + } + ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str()); + ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f); + ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f); + ImGui::SetCursorPosY(win_size.y / 2 - button_size.y); + if (imgui.button(button_text.c_str(), button_size.x, button_size.y)) + { + on_cancel_button(); + } + + //invisible large button + ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f); + ImGui::SetCursorPosY(0); + if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0))) + { + on_cancel_button(); + } + ImGui::PopStyleColor(5); + +} + +void NotificationManager::ProgressBarWithCancelNotification::on_cancel_button() +{ + if (m_cancel_callback) { + if (m_cancel_callback()) { + close(); + } + } +} + +void NotificationManager::ProgressBarWithCancelNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y) +{ + ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y); + std::string text; + if (m_percentage < 0.f) { + text = _u8L("ERROR"); + } else { + std::stringstream stream; + stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "%"; + text = stream.str(); + } + ImGui::SetCursorPosX(m_left_indentation); + ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4)); + imgui.text(text.c_str()); +} + //------PrintHostUploadNotification---------------- void NotificationManager::PrintHostUploadNotification::init() { @@ -1653,11 +1767,37 @@ void NotificationManager::upload_job_notification_show_error(int id, const std:: } } +void NotificationManager::push_download_progress_notification(const std::string& text, std::function cancel_callback) +{ + // If already exists, change text and reset progress + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::AppDownload) { + notification->update({ NotificationType::AppDownload, NotificationLevel::ProgressBarNotificationLevel, 10, text }); + auto* pbwcn = dynamic_cast(notification.get()); + pbwcn->set_percentage(0.0f); + pbwcn->set_cancel_callback(cancel_callback); + return; + } + } + // push new one + NotificationData data{ NotificationType::AppDownload, NotificationLevel::ProgressBarNotificationLevel, 10, text }; + push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, cancel_callback), 0); +} +void NotificationManager::set_download_progress_percentage(float percentage) +{ + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::AppDownload) { + dynamic_cast(notification.get())->set_percentage(percentage); + return; + } + } +} + void NotificationManager::init_slicing_progress_notification(std::function cancel_callback) { for (std::unique_ptr& notification : m_pop_notifications) { if (notification->get_type() == NotificationType::SlicingProgress) { - dynamic_cast(notification.get())->set_cancel_callback(cancel_callback); + dynamic_cast(notification.get())->set_cancel_callback(cancel_callback); return; } } diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 9265cb55e4..6d0ac9ed44 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -78,6 +78,8 @@ enum class NotificationType ProgressBar, // Progress bar with info from Print Host Upload Queue dialog. PrintHostUpload, + // Progress bar of download next version app. + AppDownload, // Progress bar with cancel button, cannot be closed // On end of slicing and G-code processing (the full G-code preview is available), // contains a hyperlink to export the G-code to a removable media or hdd. @@ -203,6 +205,9 @@ public: void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage); void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host); void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host); + // Download App progress + void push_download_progress_notification(const std::string& text, std::function cancel_callback); + void set_download_progress_percentage(float percentage); // slicing progress void init_slicing_progress_notification(std::function cancel_callback); void set_slicing_progress_began(); @@ -459,7 +464,34 @@ private: }; - + class ProgressBarWithCancelNotification : public ProgressBarNotification + { + public: + ProgressBarWithCancelNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, std::function cancel_callback) + : ProgressBarNotification(n, id_provider, evt_handler) + , m_cancel_callback(cancel_callback) + { + } + void set_percentage(float percent) override { m_percentage = percent; if(m_percentage >= 1.f) m_state = EState::FadingOut; else m_state = EState::NotFading; } + void set_cancel_callback(std::function cancel_callback) { m_cancel_callback = cancel_callback; } + protected: + void render_close_button(ImGuiWrapper& imgui, + const float win_size_x, const float win_size_y, + const float win_pos_x, const float win_pos_y) override; + void render_close_button_inner(ImGuiWrapper& imgui, + const float win_size_x, const float win_size_y, + const float win_pos_x, const float win_pos_y); + void render_cancel_button_inner(ImGuiWrapper& imgui, + const float win_size_x, const float win_size_y, + const float win_pos_x, const float win_pos_y); + void render_bar(ImGuiWrapper& imgui, + const float win_size_x, const float win_size_y, + const float win_pos_x, const float win_pos_y) override; + void on_cancel_button(); + + std::function m_cancel_callback; + long m_hover_time{ 0 }; + }; class PrintHostUploadNotification : public ProgressBarNotification { diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index f80975ce52..031d64037a 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -88,6 +88,89 @@ bool MsgUpdateSlic3r::disable_version_check() const return cbox->GetValue(); } + wxSize AppUpdateAvailableDialog::AUAD_size; +// AppUpdater +AppUpdateAvailableDialog::AppUpdateAvailableDialog(const Semver& ver_current, const Semver& ver_online) + : MsgDialog(nullptr, _(L("App Update available")), wxString::Format(_(L("New version of %s is available.\nDo you wish to download it?")), SLIC3R_APP_NAME)) +{ + auto* versions = new wxFlexGridSizer(1, 0, VERT_SPACING); + versions->Add(new wxStaticText(this, wxID_ANY, _(L("Current version:")))); + versions->Add(new wxStaticText(this, wxID_ANY, ver_current.to_string())); + versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:")))); + versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string())); + content_sizer->Add(versions); + content_sizer->AddSpacer(VERT_SPACING); + + cbox = new wxCheckBox(this, wxID_ANY, _(L("Don't notify about new releases any more"))); + content_sizer->Add(cbox); + content_sizer->AddSpacer(VERT_SPACING); + + AUAD_size = content_sizer->GetSize(); + + + add_button(wxID_CANCEL); + + if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) { + btn_ok->SetLabel(_L("Next")); + } + + finalize(); +} + +AppUpdateAvailableDialog::~AppUpdateAvailableDialog() {} + + +bool AppUpdateAvailableDialog::disable_version_check() const +{ + return cbox->GetValue(); +} + +// AppUpdateDownloadDialog +AppUpdateDownloadDialog::AppUpdateDownloadDialog( const Semver& ver_online) + : MsgDialog(nullptr, _(L("App Update download")), wxString::Format(_(L("New version of %s is available.")), SLIC3R_APP_NAME)) +{ + + auto* versions = new wxFlexGridSizer(2, 0, VERT_SPACING); + versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:")))); + versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string())); + content_sizer->Add(versions); + content_sizer->AddSpacer(VERT_SPACING); +#ifndef __linux__ + cbox_run = new wxCheckBox(this, wxID_ANY, _(L("Run installer after download."))); + content_sizer->Add(cbox_run); +#endif + content_sizer->AddSpacer(VERT_SPACING); + cbox_path = new wxCheckBox(this, wxID_ANY, _(L("Select path for downloaded file."))); + content_sizer->Add(cbox_path); + content_sizer->AddSpacer(VERT_SPACING); + + content_sizer->SetMinSize(AppUpdateAvailableDialog::AUAD_size); + + add_button(wxID_CANCEL); + + if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) { + btn_ok->SetLabel(_L("Download")); + } + + finalize(); +} + +AppUpdateDownloadDialog::~AppUpdateDownloadDialog() {} + + +bool AppUpdateDownloadDialog::run_after_download() const +{ +#ifndef __linux__ + return cbox_run->GetValue(); +#endif + return false; +} + +bool AppUpdateDownloadDialog::select_download_path() const +{ + return cbox_path->GetValue(); +} + // MsgUpdateConfig MsgUpdateConfig::MsgUpdateConfig(const std::vector &updates, bool force_before_wizard/* = false*/) : @@ -314,5 +397,25 @@ MsgNoUpdates::MsgNoUpdates() : MsgNoUpdates::~MsgNoUpdates() {} +// MsgNoAppUpdates +MsgNoAppUpdates::MsgNoAppUpdates() : + MsgDialog(nullptr, _(L("App update")), _(L("No updates available")), wxICON_ERROR | wxOK) +{ + + auto* text = new wxStaticText(this, wxID_ANY, wxString::Format( + _(L( + "%s has no version updates available." + )), + SLIC3R_APP_NAME + )); + text->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); + content_sizer->Add(text); + content_sizer->AddSpacer(VERT_SPACING); + + finalize(); +} + +MsgNoAppUpdates::~MsgNoAppUpdates() {} + } } diff --git a/src/slic3r/GUI/UpdateDialogs.hpp b/src/slic3r/GUI/UpdateDialogs.hpp index 435a8ccbd8..fbc21a558f 100644 --- a/src/slic3r/GUI/UpdateDialogs.hpp +++ b/src/slic3r/GUI/UpdateDialogs.hpp @@ -37,6 +37,42 @@ private: }; +class AppUpdateAvailableDialog : public MsgDialog +{ +public: + AppUpdateAvailableDialog(const Semver& ver_current, const Semver& ver_online); + AppUpdateAvailableDialog(AppUpdateAvailableDialog&&) = delete; + AppUpdateAvailableDialog(const AppUpdateAvailableDialog&) = delete; + AppUpdateAvailableDialog& operator=(AppUpdateAvailableDialog&&) = delete; + AppUpdateAvailableDialog& operator=(const AppUpdateAvailableDialog&) = delete; + virtual ~AppUpdateAvailableDialog(); + + // Tells whether the user checked the "don't bother me again" checkbox + bool disable_version_check() const; + static wxSize AUAD_size; +private: + wxCheckBox* cbox; +}; + +class AppUpdateDownloadDialog : public MsgDialog +{ +public: + AppUpdateDownloadDialog(const Semver& ver_online); + AppUpdateDownloadDialog(AppUpdateDownloadDialog&&) = delete; + AppUpdateDownloadDialog(const AppUpdateDownloadDialog&) = delete; + AppUpdateDownloadDialog& operator=(AppUpdateDownloadDialog&&) = delete; + AppUpdateDownloadDialog& operator=(const AppUpdateDownloadDialog&) = delete; + virtual ~AppUpdateDownloadDialog(); + + // Tells whether the user checked the "don't bother me again" checkbox + bool run_after_download() const; + bool select_download_path() const; + +private: + wxCheckBox* cbox_run; + wxCheckBox* cbox_path; +}; + // Confirmation dialog informing about configuration update. Lists updated bundles & their versions. class MsgUpdateConfig : public MsgDialog { @@ -129,6 +165,18 @@ public: ~MsgNoUpdates(); }; +// Informs about absence of new version online. +class MsgNoAppUpdates : public MsgDialog +{ +public: + MsgNoAppUpdates(); + MsgNoAppUpdates(MsgNoAppUpdates&&) = delete; + MsgNoAppUpdates(const MsgNoAppUpdates&) = delete; + MsgNoAppUpdates& operator=(MsgNoUpdates&&) = delete; + MsgNoAppUpdates& operator=(const MsgNoAppUpdates&) = delete; + ~MsgNoAppUpdates(); +}; + } } diff --git a/src/slic3r/Utils/AppUpdater.cpp b/src/slic3r/Utils/AppUpdater.cpp new file mode 100644 index 0000000000..3d5e7a8ae7 --- /dev/null +++ b/src/slic3r/Utils/AppUpdater.cpp @@ -0,0 +1,694 @@ +#include "AppUpdater.hpp" + +#include +#include +#include +#include + +#include "slic3r/GUI/format.hpp" +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/GUI.hpp" +#include "slic3r/Utils/Http.hpp" + +#ifdef _WIN32 +#include +#include +#include +#include +#include +#endif // _WIN32 + + +namespace Slic3r { + +namespace { + +#ifdef _WIN32 + bool run_file(const boost::filesystem::path& path) + { + // find updater exe + if (boost::filesystem::exists(path)) { + // run updater. Original args: /silent -restartapp prusa-slicer.exe -startappfirst + + // Using quoted string as mentioned in CreateProcessW docs, silent execution parameter. + std::wstring wcmd = L"\"" + path.wstring(); + + // additional information + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + // set the size of the structures + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + // start the program up + if (CreateProcessW(NULL, // the path + wcmd.data(), // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses) + )) { + // Close process and thread handles. + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return true; + } + else { + BOOST_LOG_TRIVIAL(error) << "Failed to run " << wcmd; + } + } + return false; + } + + std::string get_downloads_path() + { + std::string ret; + PWSTR path = NULL; + HRESULT hr = SHGetKnownFolderPath(FOLDERID_Downloads, 0, NULL, &path); + if (SUCCEEDED(hr)) { + ret = boost::nowide::narrow(path); + } + CoTaskMemFree(path); + return ret; + } + + bool open_folder(const boost::filesystem::path& path) + { + // this command can run the installer exe as well, but is it better than CreateProcessW? + ShellExecuteW(NULL, NULL, path.wstring().c_str(), NULL, NULL, SW_SHOWNORMAL); + return true; + } + +#elif __linux__ + bool run_file(const boost::filesystem::path& path) + { + return false; + } + + std::string get_downloads_path() + { + wxString command = "xdg-user-dir DOWNLOAD"; + wxArrayString output; + + //Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, + // because they may mess up the environment expected by the file manager. + // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. + if (wxGetEnv("APPIMAGE", nullptr)) { + // We're running from AppImage + wxEnvVariableHashMap env_vars; + wxGetEnvMap(&env_vars); + + env_vars.erase("APPIMAGE"); + env_vars.erase("APPDIR"); + env_vars.erase("LD_LIBRARY_PATH"); + env_vars.erase("LD_PRELOAD"); + env_vars.erase("UNION_PRELOAD"); + + wxExecuteEnv exec_env; + exec_env.env = std::move(env_vars); + + wxString owd; + if (wxGetEnv("OWD", &owd)) { + // This is the original work directory from which the AppImage image was run, + // set it as CWD for the child process: + exec_env.cwd = std::move(owd); + } + + ::wxExecute(command, output, 0, &exec_env); + + } else { + // Looks like we're NOT running from AppImage, we'll make no changes to the environment. + ::wxExecute(command, output); + } + if (output.GetCount() > 0) { + return boost::nowide::narrow(output[0]); + } + return std::string(); + } + + bool open_folder(const boost::filesystem::path& path) + { + if (boost::filesystem::is_directory(path)) { + const char *argv[] = { "xdg-open", path.string().c_str(), nullptr }; + + // Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, + // because they may mess up the environment expected by the file manager. + // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. + if (wxGetEnv("APPIMAGE", nullptr)) { + // We're running from AppImage + wxEnvVariableHashMap env_vars; + wxGetEnvMap(&env_vars); + + env_vars.erase("APPIMAGE"); + env_vars.erase("APPDIR"); + env_vars.erase("LD_LIBRARY_PATH"); + env_vars.erase("LD_PRELOAD"); + env_vars.erase("UNION_PRELOAD"); + + wxExecuteEnv exec_env; + exec_env.env = std::move(env_vars); + + wxString owd; + if (wxGetEnv("OWD", &owd)) { + // This is the original work directory from which the AppImage image was run, + // set it as CWD for the child process: + exec_env.cwd = std::move(owd); + } + + ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, &exec_env); + + } else { + // Looks like we're NOT running from AppImage, we'll make no changes to the environment. + ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, nullptr); + } + return true; + } + return false; + } + +#elif __APPLE__ + bool run_file(const boost::filesystem::path& path) + { + if (boost::filesystem::exists(path)) { + // attach downloaded dmg file + const char* argv1[] = { "hdiutil", "attach", path.string().c_str(), nullptr }; + ::wxExecute(const_cast(argv1), wxEXEC_ASYNC, nullptr); + // open inside attached as a folder in finder + const char* argv2[] = { "open", "/Volumes/PrusaSlicer", nullptr }; + ::wxExecute(const_cast(argv2), wxEXEC_ASYNC, nullptr); + return true; + } + return false; + } + + std::string get_downloads_path() + { + // call objective-c implementation + return get_downloads_path_mac(); + } + + bool open_folder(const boost::filesystem::path& path) + { + + if (boost::filesystem::is_directory(path)) { + const char* argv[] = { "open", path.string().c_str(), nullptr }; + ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); + return true; + } + return false; + } +#endif +} // namespace + +wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); +wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); +wxDEFINE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, wxCommandEvent); +wxDEFINE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_FAILED, wxCommandEvent); + +// priv handles all operations in separate thread +// 1) download version file and parse it. +// 2) download new app file and open in folder / run it. +struct AppUpdater::priv { + priv(); + // Download file. What happens with the data is specified in completefn. + bool http_get_file(const std::string& url + , size_t size_limit + , std::function progress_fn + , std::function completefn + , std::string& error_message + ) const; + + // Download installer / app + boost::filesystem::path download_file(const DownloadAppData& data) const; + // Run file in m_last_dest_path + bool run_downloaded_file(boost::filesystem::path path); + // gets version file via http + void version_check(const std::string& version_check_url); +#if 0 + // parsing of Prusaslicer.version2 + void parse_version_string_old(const std::string& body) const; +#endif + // parses ini tree of version file, saves to m_online_version_data and queue event(s) to UI + void parse_version_string(const std::string& body); + // thread + std::thread m_thread; + std::atomic_bool m_cancel; + std::mutex m_data_mutex; + // read only variable used to init m_online_version_data.target_path + boost::filesystem::path m_default_dest_folder; // readonly + // DownloadAppData read / write needs to be locked by m_data_mutex + DownloadAppData m_online_version_data; + DownloadAppData get_app_data(); + void set_app_data(DownloadAppData data); +}; + +AppUpdater::priv::priv() : + m_cancel (false) +#ifdef __linux__ + , m_default_dest_folder (boost::filesystem::path("/tmp")) +#else + , m_default_dest_folder (boost::filesystem::path(data_dir()) / "cache") +#endif //_WIN32 +{ + boost::filesystem::path downloads_path = boost::filesystem::path(get_downloads_path()); + if (!downloads_path.empty()) { + m_default_dest_folder = std::move(downloads_path); + } + BOOST_LOG_TRIVIAL(error) << "Default download path: " << m_default_dest_folder; + +} + +bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, std::function progress_fn, std::function complete_fn, std::string& error_message) const +{ + bool res = false; + Http::get(url) + .size_limit(size_limit) + .on_progress([&, progress_fn](Http::Progress progress, bool& cancel) { + // progress function returns true as success (to continue) + cancel = (this->m_cancel ? true : !progress_fn(std::move(progress))); + if (cancel) { + error_message = GUI::format("Error getting: `%1%`: Download was canceled.", + url); + BOOST_LOG_TRIVIAL(debug) << "AppUpdater::priv::http_get_file message: "<< error_message; + } + }) + .on_error([&](std::string body, std::string error, unsigned http_status) { + error_message = GUI::format("Error getting: `%1%`: HTTP %2%, %3%", + url, + http_status, + error); + BOOST_LOG_TRIVIAL(error) << error_message; + }) + .on_complete([&](std::string body, unsigned /* http_status */) { + assert(complete_fn != nullptr); + res = complete_fn(body, error_message); + }) + .perform_sync(); + + return res; +} + +boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& data) const +{ + boost::filesystem::path dest_path; + size_t last_gui_progress = 0; + size_t expected_size = data.size; + dest_path = data.target_path; + assert(!dest_path.empty()); + if (dest_path.empty()) + { + BOOST_LOG_TRIVIAL(error) << "Download from " << data.url << " could not start. Destination path is empty."; + return boost::filesystem::path(); + } + std::string error_message; + bool res = http_get_file(data.url, 80 * 1024 * 1024 //TODO: what value here + // on_progress + , [&last_gui_progress, expected_size](Http::Progress progress) { + // size check + if (progress.dltotal > 0 && progress.dltotal > expected_size) { + std::string message = GUI::format("Downloading new %1% has failed. The file has incorrect file size. Aborting download.\nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal); + BOOST_LOG_TRIVIAL(error) << message; + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); + evt->SetString(message); + GUI::wxGetApp().QueueEvent(evt); + return false; + } else if (progress.dltotal > 0 && progress.dltotal < expected_size) { + BOOST_LOG_TRIVIAL(error) << GUI::format("Downloading new %1% has incorrect size. The download will continue. \nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal);; + } + // progress event + size_t gui_progress = progress.dltotal > 0 ? 100 * progress.dlnow / progress.dltotal : 0; + //BOOST_LOG_TRIVIAL(error) << "App download " << gui_progress << "% " << progress.dlnow << " of " << progress.dltotal; + if (last_gui_progress < gui_progress && (last_gui_progress != 0 || gui_progress != 100)) { + last_gui_progress = gui_progress; + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS); + evt->SetString(GUI::from_u8(std::to_string(gui_progress))); + GUI::wxGetApp().QueueEvent(evt); + } + return true; + } + // on_complete + , [dest_path, expected_size](std::string body, std::string& error_message){ + // Size check. Does always 1 char == 1 byte? + size_t body_size = body.size(); + if (body_size != expected_size) { + BOOST_LOG_TRIVIAL(error) << "Downloaded file has wrong size. Expected size: " << expected_size << " Downloaded size: " << body_size; + return false; + } + boost::filesystem::path tmp_path = dest_path; + tmp_path += format(".%1%%2%", get_current_pid(), ".download"); + try + { + boost::filesystem::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc); + file.write(body.c_str(), body.size()); + file.close(); + boost::filesystem::rename(tmp_path, dest_path); + } + catch (const std::exception&) + { + BOOST_LOG_TRIVIAL(error) << "Failed to write and move " << tmp_path << " to " << dest_path; + return false; + } + return true; + } + , error_message + ); + if (!res) + { + if (this->m_cancel) + { + BOOST_LOG_TRIVIAL(error) << error_message; + } else { + std::string message = GUI::format("Downloading new %1% has failed:\n%2%", SLIC3R_APP_NAME, error_message); + BOOST_LOG_TRIVIAL(error) << message; + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); + evt->SetString(message); + GUI::wxGetApp().QueueEvent(evt); + } + return boost::filesystem::path(); + } + + return dest_path; +} + +bool AppUpdater::priv::run_downloaded_file(boost::filesystem::path path) +{ + assert(!path.empty()); + bool res = run_file(path); + BOOST_LOG_TRIVIAL(error) << "Running "<< path.string() << " was " << res; + return res; +} + +void AppUpdater::priv::version_check(const std::string& version_check_url) +{ + assert(!version_check_url.empty()); + std::string error_message; + bool res = http_get_file(version_check_url, 1024 + // on_progress + , [](Http::Progress progress) { return true; } + // on_complete + , [&](std::string body, std::string& error_message) { + boost::trim(body); + parse_version_string(body); + return true; + } + , error_message + ); + if (!res) + BOOST_LOG_TRIVIAL(error) << "Failed to download version file: " << error_message; +} + +void AppUpdater::priv::parse_version_string(const std::string& body) +{ + size_t start = body.find('['); + if (start == std::string::npos) { +#if 0 + BOOST_LOG_TRIVIAL(error) << "Could not find property tree in version file. Starting old parsing."; + parse_version_string_old(body); + return; +#endif // 0 + BOOST_LOG_TRIVIAL(error) << "Could not find property tree in version file. Checking for application update has failed."; + return; + } + std::string tree_string = body.substr(start); + boost::property_tree::ptree tree; + std::stringstream ss(tree_string); + try { + boost::property_tree::read_ini(ss, tree); + } catch (const boost::property_tree::ini_parser::ini_parser_error& err) { + //throw Slic3r::RuntimeError(format("Failed reading version file property tree Error: \"%1%\" at line %2%. \nTree:\n%3%", err.message(), err.line(), tree_string).c_str()); + BOOST_LOG_TRIVIAL(error) << format("Failed reading version file property tree Error: \"%1%\" at line %2%. \nTree:\n%3%", err.message(), err.line(), tree_string); + return; + } + + DownloadAppData new_data; + + for (const auto& section : tree) { + std::string section_name = section.first; + + // online release version info + if (section_name == +#ifdef _WIN32 + "release:win64" +#elif __linux__ + "release:linux" +#else + "release:osx" +#endif + ) { + for (const auto& data : section.second) { + if (data.first == "url") { + new_data.url = data.second.data(); + new_data.target_path = m_default_dest_folder / AppUpdater::get_filename_from_url(new_data.url); + BOOST_LOG_TRIVIAL(error) << format("parsing version string: url: %1%", new_data.url); + } else if (data.first == "size"){ + new_data.size = std::stoi(data.second.data()); + BOOST_LOG_TRIVIAL(error) << format("parsing version string: expected size: %1%", new_data.size); + } + } + } + + // released versions - to be send to UI layer + if (section_name == "common") { + std::vector prerelease_versions; + for (const auto& data : section.second) { + // release version - save and send to UI layer + if (data.first == "release") { + std::string version = data.second.data(); + boost::optional release_version = Semver::parse(version); + if (!release_version) { + BOOST_LOG_TRIVIAL(error) << format("Received invalid contents from version file: Not a correct semver: `%1%`", version); + return; + } + new_data.version = release_version; + // Send after all data is read + /* + BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version)); + GUI::wxGetApp().QueueEvent(evt); + */ + // prerelease versions - write down to be sorted and send to UI layer + } else if (data.first == "alpha") { + prerelease_versions.emplace_back(data.second.data()); + } else if (data.first == "beta") { + prerelease_versions.emplace_back(data.second.data()); + } else if (data.first == "rc") { + prerelease_versions.emplace_back(data.second.data()); + } + } + // find recent version that is newer than last full release. + boost::optional recent_version; + std::string version_string; + for (const std::string& ver_string : prerelease_versions) { + boost::optional ver = Semver::parse(ver_string); + if (ver && *new_data.version < *ver && ((recent_version && *recent_version < *ver) || !recent_version)) { + recent_version = ver; + version_string = ver_string; + } + } + // send prerelease version to UI layer + if (recent_version) { + BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version_string); + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version_string)); + GUI::wxGetApp().QueueEvent(evt); + } + } + } + assert(!new_data.url.empty()); + assert(new_data.version); + // save + set_app_data(new_data); + // send + std::string version = new_data.version.get().to_string(); + BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version)); + GUI::wxGetApp().QueueEvent(evt); +} + +#if 0 +void AppUpdater::priv::parse_version_string_old(const std::string& body) const +{ + + // release version + std::string version; + const auto first_nl_pos = body.find_first_of("\n\r"); + if (first_nl_pos != std::string::npos) + version = body.substr(0, first_nl_pos); + else + version = body; + boost::optional release_version = Semver::parse(version); + if (!release_version) { + BOOST_LOG_TRIVIAL(error) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version); + return; + } + BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version)); + GUI::wxGetApp().QueueEvent(evt); + + // alpha / beta version + std::vector prerelease_versions; + size_t nexn_nl_pos = first_nl_pos; + while (nexn_nl_pos != std::string::npos && body.size() > nexn_nl_pos + 1) { + const auto last_nl_pos = nexn_nl_pos; + nexn_nl_pos = body.find_first_of("\n\r", last_nl_pos + 1); + std::string line; + if (nexn_nl_pos == std::string::npos) + line = body.substr(last_nl_pos + 1); + else + line = body.substr(last_nl_pos + 1, nexn_nl_pos - last_nl_pos - 1); + + // alpha + if (line.substr(0, 6) == "alpha=") { + version = line.substr(6); + if (!Semver::parse(version)) { + BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for alpha release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version); + return; + } + prerelease_versions.emplace_back(version); + // beta + } + else if (line.substr(0, 5) == "beta=") { + version = line.substr(5); + if (!Semver::parse(version)) { + BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for beta release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version); + return; + } + prerelease_versions.emplace_back(version); + } + } + // find recent version that is newer than last full release. + boost::optional recent_version; + for (const std::string& ver_string : prerelease_versions) { + boost::optional ver = Semver::parse(ver_string); + if (ver && *release_version < *ver && ((recent_version && *recent_version < *ver) || !recent_version)) { + recent_version = ver; + version = ver_string; + } + } + if (recent_version) { + BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE); + evt->SetString(GUI::from_u8(version)); + GUI::wxGetApp().QueueEvent(evt); + } +} +#endif // 0 + +DownloadAppData AppUpdater::priv::get_app_data() +{ + const std::lock_guard lock(m_data_mutex); + DownloadAppData ret_val(m_online_version_data); + return ret_val; +} + +void AppUpdater::priv::set_app_data(DownloadAppData data) +{ + const std::lock_guard lock(m_data_mutex); + m_online_version_data = data; +} + +AppUpdater::AppUpdater() + :p(new priv()) +{ +} +AppUpdater::~AppUpdater() +{ + if (p && p->m_thread.joinable()) { + // This will stop transfers being done by the thread, if any. + // Cancelling takes some time, but should complete soon enough. + p->m_cancel = true; + p->m_thread.join(); + } +} +void AppUpdater::sync_download() +{ + assert(p); + // join thread first - it could have been in sync_version + if (p->m_thread.joinable()) { + // This will stop transfers being done by the thread, if any. + // Cancelling takes some time, but should complete soon enough. + p->m_cancel = true; + p->m_thread.join(); + } + p->m_cancel = false; + + DownloadAppData input_data = p->get_app_data(); + assert(!input_data.url.empty()); + + p->m_thread = std::thread( + [this, input_data]() { + if (boost::filesystem::path dest_path = p->download_file(input_data); boost::filesystem::exists(dest_path)){ + if (input_data.start_after) { + p->run_downloaded_file(std::move(dest_path)); + } else { + open_folder(dest_path.parent_path()); + } + } + }); +} + +void AppUpdater::sync_version(const std::string& version_check_url) +{ + assert(p); + // join thread first - it could have been in sync_download + if (p->m_thread.joinable()) { + // This will stop transfers being done by the thread, if any. + // Cancelling takes some time, but should complete soon enough. + p->m_cancel = true; + p->m_thread.join(); + } + p->m_cancel = false; + p->m_thread = std::thread( + [this, version_check_url]() { + p->version_check(version_check_url); + }); +} + +void AppUpdater::cancel() +{ + p->m_cancel = true; +} +bool AppUpdater::cancel_callback() +{ + cancel(); + return true; +} + +std::string AppUpdater::get_default_dest_folder() +{ + return p->m_default_dest_folder.string(); +} + +std::string AppUpdater::get_filename_from_url(const std::string& url) +{ + size_t slash = url.rfind('/'); + return (slash != std::string::npos ? url.substr(slash + 1) : url); +} + +std::string AppUpdater::get_file_extension_from_url(const std::string& url) +{ + size_t dot = url.rfind('.'); + return (dot != std::string::npos ? url.substr(dot) : url); +} + +void AppUpdater::set_app_data(DownloadAppData data) +{ + p->set_app_data(std::move(data)); +} + +DownloadAppData AppUpdater::get_app_data() +{ + return p->get_app_data(); +} + + +} //namespace Slic3r diff --git a/src/slic3r/Utils/AppUpdater.hpp b/src/slic3r/Utils/AppUpdater.hpp new file mode 100644 index 0000000000..2cdcb900bb --- /dev/null +++ b/src/slic3r/Utils/AppUpdater.hpp @@ -0,0 +1,62 @@ +#ifndef slic3r_AppUpdate_hpp_ +#define slic3r_AppUpdate_hpp_ + +#include +#include +#include "libslic3r/Utils.hpp" +#include "wx/event.h" + +//class boost::filesystem::path; + +namespace Slic3r { + +#ifdef __APPLE__ +// implmented at MacUtils.mm +std::string get_downloads_path_mac(); +#endif //__APPLE__ + +struct DownloadAppData +{ + std::string url; + bool start_after; + boost::optional version; + size_t size; + boost::filesystem::path target_path; +}; + +class AppUpdater +{ +public: + AppUpdater(); + ~AppUpdater(); + AppUpdater(AppUpdater&&) = delete; + AppUpdater(const AppUpdater&) = delete; + AppUpdater& operator=(AppUpdater&&) = delete; + AppUpdater& operator=(const AppUpdater&) = delete; + + // downloads app file + void sync_download(); + // downloads version file + void sync_version(const std::string& version_check_url); + void cancel(); + bool cancel_callback(); + + std::string get_default_dest_folder(); + + static std::string get_filename_from_url(const std::string& url); + static std::string get_file_extension_from_url(const std::string& url); + + // mutex access + void set_app_data(DownloadAppData data); + DownloadAppData get_app_data(); +private: + struct priv; + std::unique_ptr p; +}; + +wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); +wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); +wxDECLARE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, wxCommandEvent); +wxDECLARE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_FAILED, wxCommandEvent); +} //namespace Slic3r +#endif diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp index 63c26f7217..68ddda0410 100644 --- a/src/slic3r/Utils/Http.cpp +++ b/src/slic3r/Utils/Http.cpp @@ -207,7 +207,6 @@ size_t Http::priv::writecb(void *data, size_t size, size_t nmemb, void *userp) auto self = static_cast(userp); const char *cdata = static_cast(data); const size_t realsize = size * nmemb; - const size_t limit = self->limit > 0 ? self->limit : DEFAULT_SIZE_LIMIT; if (self->buffer.size() + realsize > limit) { // This makes curl_easy_perform return CURLE_WRITE_ERROR diff --git a/src/slic3r/Utils/MacUtils.mm b/src/slic3r/Utils/MacUtils.mm new file mode 100644 index 0000000000..31a28f14e4 --- /dev/null +++ b/src/slic3r/Utils/MacUtils.mm @@ -0,0 +1,18 @@ +#import "AppUpdater.hpp" + +#import + +namespace Slic3r { + +// AppUpdater.hpp +std::string get_downloads_path_mac() +{ + // 1) + NSArray * paths = NSSearchPathForDirectoriesInDomains (NSDownloadsDirectory, NSUserDomainMask, YES); + NSString * desktopPath = [paths objectAtIndex:0]; + return std::string([desktopPath UTF8String]); + // 2) + //[NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Downloads"]]; + //return std::string(); +} +} diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 2b458df537..40f068155a 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -136,8 +136,8 @@ struct Updates }; -wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); -wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); +//wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); +//wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); struct PresetUpdater::priv { @@ -162,8 +162,8 @@ struct PresetUpdater::priv void set_download_prefs(AppConfig *app_config); bool get_file(const std::string &url, const fs::path &target_path) const; void prune_tmps() const; - void sync_version() const; - void parse_version_string(const std::string& body) const; +// void sync_version() const; +// void parse_version_string(const std::string& body) const; void sync_config(const VendorMap vendors); void check_install_indices() const; @@ -238,6 +238,8 @@ void PresetUpdater::priv::prune_tmps() const } } +// moved to app updater + /* // Get Slic3rPE version available online, save in AppConfig. void PresetUpdater::priv::sync_version() const { @@ -257,7 +259,7 @@ void PresetUpdater::priv::sync_version() const http_status, error); }) - .on_complete([&](std::string body, unsigned /* http_status */) { + .on_complete([&](std::string body, unsigned ) { boost::trim(body); parse_version_string(body); }) @@ -268,6 +270,7 @@ void PresetUpdater::priv::sync_version() const // Version string must contain release version on first line. Follows non-mandatory alpha / beta releases on following lines (alpha=2.0.0-alpha1). void PresetUpdater::priv::parse_version_string(const std::string& body) const { + // release version std::string version; const auto first_nl_pos = body.find_first_of("\n\r"); @@ -331,8 +334,9 @@ void PresetUpdater::priv::parse_version_string(const std::string& body) const evt->SetString(GUI::from_u8(version)); GUI::wxGetApp().QueueEvent(evt); } + } - +*/ // Download vendor indices. Also download new bundles if an index indicates there's a new one available. // Both are saved in cache. void PresetUpdater::priv::sync_config(const VendorMap vendors) @@ -743,7 +747,7 @@ void PresetUpdater::sync(PresetBundle *preset_bundle) p->thread = std::thread([this, vendors]() { this->p->prune_tmps(); - this->p->sync_version(); +// this->p->sync_version(); this->p->sync_config(std::move(vendors)); }); } diff --git a/src/slic3r/Utils/PresetUpdater.hpp b/src/slic3r/Utils/PresetUpdater.hpp index 97d85a4eae..974a7dcfae 100644 --- a/src/slic3r/Utils/PresetUpdater.hpp +++ b/src/slic3r/Utils/PresetUpdater.hpp @@ -65,7 +65,7 @@ private: std::unique_ptr p; }; -wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); -wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); +//wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); +//wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); } #endif From 0e9a8f24c37eb3acdcdcef335d5446e5ad48e417 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 1 Feb 2022 13:44:40 +0100 Subject: [PATCH 29/46] Added some missing includes (GCC 9.3, without PCH) --- src/slic3r/Utils/AppUpdater.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/Utils/AppUpdater.cpp b/src/slic3r/Utils/AppUpdater.cpp index 3d5e7a8ae7..8b3a2f9f02 100644 --- a/src/slic3r/Utils/AppUpdater.cpp +++ b/src/slic3r/Utils/AppUpdater.cpp @@ -1,7 +1,11 @@ #include "AppUpdater.hpp" +#include +#include + #include #include +#include #include #include From 5a6824273cc5d57ac0de4d62f028b1f8c9b9b70b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 10 Feb 2022 15:39:20 +0100 Subject: [PATCH 30/46] Comments from lm regarding previous commit --- src/slic3r/GUI/GUI_App.cpp | 4 +++- src/slic3r/Utils/AppUpdater.cpp | 31 ++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 3c0d52bd1e..4278766b44 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1242,7 +1242,7 @@ bool GUI_App::on_init_inner() preset_updater = new PresetUpdater(); Bind(EVT_SLIC3R_VERSION_ONLINE, &GUI_App::on_version_read, this); Bind(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, [this](const wxCommandEvent& evt) { - app_config->save(); + app_config->save();//lm:What is the purpose? if (this->plater_ != nullptr && app_config->get("notify_release") == "all") { std::string evt_string = into_u8(evt.GetString()); if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(evt_string)) { @@ -1257,6 +1257,7 @@ bool GUI_App::on_init_inner() } }); Bind(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, [this](const wxCommandEvent& evt) { + //lm:This does not force a render. The progress bar only updateswhen the mouse is moved. if (this->plater_ != nullptr) this->plater_->get_notification_manager()->set_download_progress_percentage((float)std::stoi(into_u8(evt.GetString())) / 100.f ); }); @@ -3354,6 +3355,7 @@ void GUI_App::app_updater(bool from_user) } if (boost::filesystem::exists(app_data.target_path)) { + //lm:UI confirmation dialog? BOOST_LOG_TRIVIAL(error) << "App download: File on target path already exists and will be overwritten. Path: " << app_data.target_path; } // start download diff --git a/src/slic3r/Utils/AppUpdater.cpp b/src/slic3r/Utils/AppUpdater.cpp index 8b3a2f9f02..26bf883de7 100644 --- a/src/slic3r/Utils/AppUpdater.cpp +++ b/src/slic3r/Utils/AppUpdater.cpp @@ -35,7 +35,7 @@ namespace { // run updater. Original args: /silent -restartapp prusa-slicer.exe -startappfirst // Using quoted string as mentioned in CreateProcessW docs, silent execution parameter. - std::wstring wcmd = L"\"" + path.wstring(); + std::wstring wcmd = L"\"" + path.wstring(); //lm: closing quote? // additional information STARTUPINFOW si; @@ -64,7 +64,7 @@ namespace { return true; } else { - BOOST_LOG_TRIVIAL(error) << "Failed to run " << wcmd; + BOOST_LOG_TRIVIAL(error) << "Failed to run " << wcmd; //lm: maybe a UI error message? } } return false; @@ -86,6 +86,8 @@ namespace { { // this command can run the installer exe as well, but is it better than CreateProcessW? ShellExecuteW(NULL, NULL, path.wstring().c_str(), NULL, NULL, SW_SHOWNORMAL); + //lm:I would make it explicit that the folder should be opened. + //lm:Also, this always returns true. return true; } @@ -100,6 +102,9 @@ namespace { wxString command = "xdg-user-dir DOWNLOAD"; wxArrayString output; + //lm:It might be a good idea to make the following a separate function in GUI_Utils or something + // It is already used in four different places in almost the same way. + //Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, // because they may mess up the environment expected by the file manager. // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. @@ -131,7 +136,7 @@ namespace { ::wxExecute(command, output); } if (output.GetCount() > 0) { - return boost::nowide::narrow(output[0]); + return boost::nowide::narrow(output[0]); //lm:I would use wxString::ToUTF8(), although on Linux, nothing at all should work too. } return std::string(); } @@ -141,6 +146,8 @@ namespace { if (boost::filesystem::is_directory(path)) { const char *argv[] = { "xdg-open", path.string().c_str(), nullptr }; + //lm:This is a copy of desktop_open_datadir_folder, it would make sense to instead call it. + // Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, // because they may mess up the environment expected by the file manager. // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. @@ -264,7 +271,7 @@ AppUpdater::priv::priv() : if (!downloads_path.empty()) { m_default_dest_folder = std::move(downloads_path); } - BOOST_LOG_TRIVIAL(error) << "Default download path: " << m_default_dest_folder; + BOOST_LOG_TRIVIAL(error) << "Default download path: " << m_default_dest_folder; //lm:Is this an error? } @@ -277,7 +284,7 @@ bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, // progress function returns true as success (to continue) cancel = (this->m_cancel ? true : !progress_fn(std::move(progress))); if (cancel) { - error_message = GUI::format("Error getting: `%1%`: Download was canceled.", + error_message = GUI::format("Error getting: `%1%`: Download was canceled.", //lm:typo url); BOOST_LOG_TRIVIAL(debug) << "AppUpdater::priv::http_get_file message: "<< error_message; } @@ -311,7 +318,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d return boost::filesystem::path(); } std::string error_message; - bool res = http_get_file(data.url, 80 * 1024 * 1024 //TODO: what value here + bool res = http_get_file(data.url, 80 * 1024 * 1024 //TODO: what value here //lm:I don't know, but larger. The binaries will grow. // on_progress , [&last_gui_progress, expected_size](Http::Progress progress) { // size check @@ -322,7 +329,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d evt->SetString(message); GUI::wxGetApp().QueueEvent(evt); return false; - } else if (progress.dltotal > 0 && progress.dltotal < expected_size) { + } else if (progress.dltotal > 0 && progress.dltotal < expected_size) { //lm:When will this happen? Is that not an error? BOOST_LOG_TRIVIAL(error) << GUI::format("Downloading new %1% has incorrect size. The download will continue. \nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal);; } // progress event @@ -341,6 +348,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d // Size check. Does always 1 char == 1 byte? size_t body_size = body.size(); if (body_size != expected_size) { + //lm:UI message? BOOST_LOG_TRIVIAL(error) << "Downloaded file has wrong size. Expected size: " << expected_size << " Downloaded size: " << body_size; return false; } @@ -366,7 +374,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d { if (this->m_cancel) { - BOOST_LOG_TRIVIAL(error) << error_message; + BOOST_LOG_TRIVIAL(error) << error_message; //lm:Is this an error? } else { std::string message = GUI::format("Downloading new %1% has failed:\n%2%", SLIC3R_APP_NAME, error_message); BOOST_LOG_TRIVIAL(error) << message; @@ -403,6 +411,9 @@ void AppUpdater::priv::version_check(const std::string& version_check_url) } , error_message ); + //lm:In case the internet is not available, it will report no updates if run by user. + // We might save a flag that we don't know or try to run the version_check again, reporting + // the failure. if (!res) BOOST_LOG_TRIVIAL(error) << "Failed to download version file: " << error_message; } @@ -444,6 +455,8 @@ void AppUpdater::priv::parse_version_string(const std::string& body) #else "release:osx" #endif +//lm:Related to the ifdefs. We should also support BSD, which behaves similar to Linux in most cases. +// Unless you have a reason not to, I would consider doing _WIN32, elif __APPLE__, else ... Not just here. ) { for (const auto& data : section.second) { if (data.first == "url") { @@ -517,7 +530,7 @@ void AppUpdater::priv::parse_version_string(const std::string& body) GUI::wxGetApp().QueueEvent(evt); } -#if 0 +#if 0 //lm:is this meant to be ressurected? void AppUpdater::priv::parse_version_string_old(const std::string& body) const { From 1f362afb2422f7f32c917754a6ce55ef8df50200 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 18 Feb 2022 16:11:17 +0100 Subject: [PATCH 31/46] Fixes after CR Most important: Change Download dialog to select path there. Every user query triggers new download of version file, possibly stops former download (with dialog). Some functions refactored. --- src/slic3r/GUI/GUI.cpp | 165 ++++++++++++---- src/slic3r/GUI/GUI.hpp | 18 ++ src/slic3r/GUI/GUI_App.cpp | 111 +++-------- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/NotificationManager.cpp | 7 +- src/slic3r/GUI/NotificationManager.hpp | 2 + src/slic3r/GUI/UpdateDialogs.cpp | 52 ++++- src/slic3r/GUI/UpdateDialogs.hpp | 8 +- src/slic3r/Utils/AppUpdater.cpp | 251 ++++++++----------------- src/slic3r/Utils/AppUpdater.hpp | 6 +- src/slic3r/Utils/PresetUpdater.cpp | 106 ----------- 11 files changed, 316 insertions(+), 412 deletions(-) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index a0b674e27e..1d32832aa4 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -476,50 +476,135 @@ void about() void desktop_open_datadir_folder() { + boost::filesystem::path path(data_dir()); + desktop_open_folder(std::move(path)); +} + +void desktop_open_folder(const boost::filesystem::path& path) +{ + if (!boost::filesystem::is_directory(path)) + return; + // Execute command to open a file explorer, platform dependent. - // FIXME: The const_casts aren't needed in wxWidgets 3.1, remove them when we upgrade. - - const auto path = data_dir(); #ifdef _WIN32 - const wxString widepath = from_u8(path); - const wchar_t *argv[] = { L"explorer", widepath.GetData(), nullptr }; - ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); + const wxString widepath = path.wstring(); + const wchar_t* argv[] = { L"explorer", widepath.GetData(), nullptr }; + ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); #elif __APPLE__ - const char *argv[] = { "open", path.data(), nullptr }; - ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); + const char* argv[] = { "open", path.string(), nullptr }; + ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); #else - const char *argv[] = { "xdg-open", path.data(), nullptr }; - - // Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, - // because they may mess up the environment expected by the file manager. - // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. - if (wxGetEnv("APPIMAGE", nullptr)) { - // We're running from AppImage - wxEnvVariableHashMap env_vars; - wxGetEnvMap(&env_vars); - - env_vars.erase("APPIMAGE"); - env_vars.erase("APPDIR"); - env_vars.erase("LD_LIBRARY_PATH"); - env_vars.erase("LD_PRELOAD"); - env_vars.erase("UNION_PRELOAD"); - - wxExecuteEnv exec_env; - exec_env.env = std::move(env_vars); - - wxString owd; - if (wxGetEnv("OWD", &owd)) { - // This is the original work directory from which the AppImage image was run, - // set it as CWD for the child process: - exec_env.cwd = std::move(owd); - } - - ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, &exec_env); - } else { - // Looks like we're NOT running from AppImage, we'll make no changes to the environment. - ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, nullptr); - } + const char* argv[] = { "xdg-open", path.string().c_str(), nullptr }; + desktop_execute(argv); #endif } -} } +#ifdef __linux__ +namespace { +wxExecuteEnv get_appimage_exec_env() +{ + // If we're running in an AppImage container, we need to remove AppImage's env vars, + // because they may mess up the environment expected by the file manager. + // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. + wxEnvVariableHashMap env_vars; + wxGetEnvMap(&env_vars); + + env_vars.erase("APPIMAGE"); + env_vars.erase("APPDIR"); + env_vars.erase("LD_LIBRARY_PATH"); + env_vars.erase("LD_PRELOAD"); + env_vars.erase("UNION_PRELOAD"); + + wxExecuteEnv exec_env; + exec_env.env = std::move(env_vars); + + wxString owd; + if (wxGetEnv("OWD", &owd)) { + // This is the original work directory from which the AppImage image was run, + // set it as CWD for the child process: + exec_env.cwd = std::move(owd); + } + return exec_env; +} +} // namespace +void desktop_execute(const char* argv[]) +{ + if (sizeof(argv) == 0) + return; + + // Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, + // because they may mess up the environment expected by the file manager. + // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. + if (wxGetEnv("APPIMAGE", nullptr)) { + // We're running from AppImage + wxExecuteEnv exec_env = get_appimage_exec_env(); + ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, &exec_env); + } + else { + // Looks like we're NOT running from AppImage, we'll make no changes to the environment. + ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, nullptr); + } +} +void desktop_execute_get_result(wxString command, wxArrayString& output) +{ + output.Clear(); + //Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, + // because they may mess up the environment expected by the file manager. + // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. + if (wxGetEnv("APPIMAGE", nullptr)) { + // We're running from AppImage + wxExecuteEnv exec_env = get_appimage_exec_env(); + ::wxExecute(command, output, 0, &exec_env); + } else { + // Looks like we're NOT running from AppImage, we'll make no changes to the environment. + ::wxExecute(command, output); + } +} +#endif // __linux__ + +#ifdef _WIN32 +bool create_process(const boost::filesystem::path& path, const std::wstring& cmd_opt, std::string& error_msg) +{ + // find updater exe + if (boost::filesystem::exists(path)) { + // Using quoted string as mentioned in CreateProcessW docs. + std::wstring wcmd = L"\"" + path.wstring() + L"\""; + if (!cmd_opt.empty()) + wcmd += L" " + cmd_opt; + + // additional information + STARTUPINFOW si; + PROCESS_INFORMATION pi; + + // set the size of the structures + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + // start the program up + if (CreateProcessW(NULL, // the path + wcmd.data(), // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses) + )) { + // Close process and thread handles. + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + return true; + } + else + error_msg = "CreateProcessW failed to create process " + boost::nowide::narrow(path.wstring()); + } + else + error_msg = "Executable doesn't exists. Path: " + boost::nowide::narrow(path.wstring()); + return false; +} +#endif //_WIN32 + +} } // namespaces GUI / Slic3r diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 20c8828785..2eb99e7bc7 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -80,6 +80,24 @@ boost::filesystem::path into_path(const wxString &str); extern void about(); // Ask the destop to open the datadir using the default file explorer. extern void desktop_open_datadir_folder(); +// Ask the destop to open the directory specified by path using the default file explorer. +void desktop_open_folder(const boost::filesystem::path& path); + +#ifdef __linux__ +// Calling wxExecute on Linux with proper handling of AppImage's env vars. +// argv example: { "xdg-open", path.c_str(), nullptr } +void desktop_execute(const char* argv[]); +void desktop_execute_get_result(wxString command, wxArrayString& output); +#endif // __linux__ + +#ifdef _WIN32 +// Call CreateProcessW to start external proccess on path +// returns true on success +// path should contain path to the process +// cmd_opt can be empty or contain command line options. Example: L"/silent" +// error_msg will contain error message if create_process return false +bool create_process(const boost::filesystem::path& path, const std::wstring& cmd_opt, std::string& error_msg); +#endif //_WIN32 } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 4278766b44..8110d42dd8 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -431,50 +431,21 @@ bool static check_old_linux_datadir(const wxString& app_name) { } #endif - #ifdef _WIN32 +#if 0 // External Updater is replaced with AppUpdater.cpp static bool run_updater_win() { // find updater exe boost::filesystem::path path_updater = boost::dll::program_location().parent_path() / "prusaslicer-updater.exe"; - if (boost::filesystem::exists(path_updater)) { - // run updater. Original args: /silent -restartapp prusa-slicer.exe -startappfirst - - // Using quoted string as mentioned in CreateProcessW docs, silent execution parameter. - std::wstring wcmd = L"\"" + path_updater.wstring() + L"\" /silent"; - - // additional information - STARTUPINFOW si; - PROCESS_INFORMATION pi; - - // set the size of the structures - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - - // start the program up - if (CreateProcessW(NULL, // the path - wcmd.data(), // Command line - NULL, // Process handle not inheritable - NULL, // Thread handle not inheritable - FALSE, // Set handle inheritance to FALSE - 0, // No creation flags - NULL, // Use parent's environment block - NULL, // Use parent's starting directory - &si, // Pointer to STARTUPINFO structure - &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses) - )) { - // Close process and thread handles. - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return true; - } else { - BOOST_LOG_TRIVIAL(error) << "Failed to start prusaslicer-updater.exe with command " << wcmd; - } - } - return false; + // run updater. Original args: /silent -restartapp prusa-slicer.exe -startappfirst + std::string msg; + bool res = create_process(path_updater, L"/silent", msg); + if (!res) + BOOST_LOG_TRIVIAL(error) << msg; + return res; } -#endif //_WIN32 +#endif // 0 +#endif // _WIN32 struct FileWildcards { std::string_view title; @@ -817,7 +788,7 @@ void GUI_App::post_init() CallAfter([this] { bool cw_showed = this->config_wizard_startup(); this->preset_updater->sync(preset_bundle); - this->app_version_check(); + this->app_version_check(false); if (! cw_showed) { // The CallAfter is needed as well, without it, GL extensions did not show. // Also, we only want to show this when the wizard does not, so the new user @@ -1242,7 +1213,6 @@ bool GUI_App::on_init_inner() preset_updater = new PresetUpdater(); Bind(EVT_SLIC3R_VERSION_ONLINE, &GUI_App::on_version_read, this); Bind(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, [this](const wxCommandEvent& evt) { - app_config->save();//lm:What is the purpose? if (this->plater_ != nullptr && app_config->get("notify_release") == "all") { std::string evt_string = into_u8(evt.GetString()); if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(evt_string)) { @@ -1265,10 +1235,13 @@ bool GUI_App::on_init_inner() Bind(EVT_SLIC3R_APP_DOWNLOAD_FAILED, [this](const wxCommandEvent& evt) { if (this->plater_ != nullptr) this->plater_->get_notification_manager()->close_notification_of_type(NotificationType::AppDownload); - show_error(nullptr, evt.GetString()); + if(!evt.GetString().IsEmpty()) + show_error(nullptr, evt.GetString()); }); - + Bind(EVT_SLIC3R_APP_OPEN_FAILED, [this](const wxCommandEvent& evt) { + show_error(nullptr, evt.GetString()); + }); } else { #ifdef __WXMSW__ @@ -2326,7 +2299,7 @@ void GUI_App::add_config_menu(wxMenuBar *menu) check_updates(true); break; case ConfigMenuUpdateApp: - app_updater(true); + app_version_check(true); break; #ifdef __linux__ case ConfigMenuDesktopIntegration: @@ -3270,7 +3243,6 @@ void GUI_App::associate_gcode_files() void GUI_App::on_version_read(wxCommandEvent& evt) { - app_config->set("version_online", into_u8(evt.GetString())); app_config->save(); std::string opt = app_config->get("notify_release"); @@ -3290,8 +3262,8 @@ void GUI_App::on_version_read(wxCommandEvent& evt) ); */ // updater - - app_updater(false); + // read triggered_by_user that was set when calling GUI_App::app_version_check + app_updater(m_app_updater->get_triggered_by_user()); } void GUI_App::app_updater(bool from_user) @@ -3321,43 +3293,15 @@ void GUI_App::app_updater(bool from_user) if (dialog_result != wxID_OK) { return; } - // dialog with new version download (installer or app dependent on system) - AppUpdateDownloadDialog dwnld_dlg(*app_data.version); + // dialog with new version download (installer or app dependent on system) including path selection + AppUpdateDownloadDialog dwnld_dlg(*app_data.version, app_data.target_path); dialog_result = dwnld_dlg.ShowModal(); // Doesn't wish to download if (dialog_result != wxID_OK) { return; } - // Save as dialog - if (dwnld_dlg.select_download_path()) { - std::string extension = app_data.target_path.filename().extension().string(); - wxString wildcard; - if (!extension.empty()) { - extension = extension.substr(1); - wxString wxext = boost::nowide::widen(extension); - wildcard = GUI::format_wxstr("%1% Files (*.%2%)|*.%2%", wxext.Upper(), wxext); - } - wxFileDialog save_dlg( - plater() - , _L("Save as:") - , boost::nowide::widen(m_app_updater->get_default_dest_folder()) - , boost::nowide::widen(AppUpdater::get_filename_from_url(app_data.url)) - , wildcard - , wxFD_SAVE | wxFD_OVERWRITE_PROMPT - ); - // Canceled - if (save_dlg.ShowModal() != wxID_OK) { - return; - // set path - } else { - app_data.target_path = boost::filesystem::path(save_dlg.GetPath().ToUTF8().data()); - } - } - if (boost::filesystem::exists(app_data.target_path)) - { - //lm:UI confirmation dialog? - BOOST_LOG_TRIVIAL(error) << "App download: File on target path already exists and will be overwritten. Path: " << app_data.target_path; - } + app_data.target_path =dwnld_dlg.get_download_path(); + // start download this->plater_->get_notification_manager()->push_download_progress_notification(_utf8("Download"), std::bind(&AppUpdater::cancel_callback, this->m_app_updater.get())); app_data.start_after = dwnld_dlg.run_after_download(); @@ -3365,10 +3309,17 @@ void GUI_App::app_updater(bool from_user) m_app_updater->sync_download(); } -void GUI_App::app_version_check() +void GUI_App::app_version_check(bool from_user) { + if (from_user) { + if (m_app_updater->get_download_ongoing()) { + MessageDialog msgdlg(nullptr, _L("Download of new version is already ongoing. Do you wish to continue?"), _L("Notice"), wxYES_NO); + if (msgdlg.ShowModal() != wxID_YES) + return; + } + } std::string version_check_url = app_config->version_check_url(); - m_app_updater->sync_version(version_check_url); + m_app_updater->sync_version(version_check_url, from_user); } } // GUI diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 4df41c607d..ce07fb7723 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -367,7 +367,7 @@ private: // if the data from version file are already downloaded, shows dialogs to start download of new version of app void app_updater(bool from_user); // inititate read of version file online in separate thread - void app_version_check(); + void app_version_check(bool from_user); bool m_datadir_redefined { false }; }; diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 9374ea17fa..fc9e5f49c8 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1787,7 +1787,12 @@ void NotificationManager::set_download_progress_percentage(float percentage) { for (std::unique_ptr& notification : m_pop_notifications) { if (notification->get_type() == NotificationType::AppDownload) { - dynamic_cast(notification.get())->set_percentage(percentage); + ProgressBarWithCancelNotification* pbwcn = dynamic_cast(notification.get()); + // if this changes the percentage, it should be shown now + float percent_b4 = pbwcn->get_percentage(); + pbwcn->set_percentage(percentage); + if (pbwcn->get_percentage() != percent_b4) + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); return; } } diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 6d0ac9ed44..72889c8549 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -442,6 +442,7 @@ private: ProgressBarNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) { } virtual void set_percentage(float percent) { m_percentage = percent; } + float get_percentage() const { return m_percentage; } protected: virtual void init() override; virtual void render_text(ImGuiWrapper& imgui, @@ -474,6 +475,7 @@ private: } void set_percentage(float percent) override { m_percentage = percent; if(m_percentage >= 1.f) m_state = EState::FadingOut; else m_state = EState::NotFading; } void set_cancel_callback(std::function cancel_callback) { m_cancel_callback = cancel_callback; } + protected: void render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index 031d64037a..531e99ea25 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -14,11 +14,13 @@ #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" +#include "../Utils/AppUpdater.hpp" #include "GUI.hpp" #include "GUI_App.hpp" #include "I18N.hpp" #include "ConfigWizard.hpp" #include "wxExtensions.hpp" +#include "format.hpp" namespace Slic3r { namespace GUI { @@ -126,23 +128,50 @@ bool AppUpdateAvailableDialog::disable_version_check() const } // AppUpdateDownloadDialog -AppUpdateDownloadDialog::AppUpdateDownloadDialog( const Semver& ver_online) +AppUpdateDownloadDialog::AppUpdateDownloadDialog( const Semver& ver_online, boost::filesystem::path& path) : MsgDialog(nullptr, _(L("App Update download")), wxString::Format(_(L("New version of %s is available.")), SLIC3R_APP_NAME)) { - auto* versions = new wxFlexGridSizer(2, 0, VERT_SPACING); versions->Add(new wxStaticText(this, wxID_ANY, _(L("New version:")))); versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string())); content_sizer->Add(versions); content_sizer->AddSpacer(VERT_SPACING); #ifndef __linux__ - cbox_run = new wxCheckBox(this, wxID_ANY, _(L("Run installer after download."))); + cbox_run = new wxCheckBox(this, wxID_ANY, _(L("Run installer after download. (Otherwise file explorer will be opened)"))); content_sizer->Add(cbox_run); #endif content_sizer->AddSpacer(VERT_SPACING); - cbox_path = new wxCheckBox(this, wxID_ANY, _(L("Select path for downloaded file."))); - content_sizer->Add(cbox_path); content_sizer->AddSpacer(VERT_SPACING); + content_sizer->Add(new wxStaticText(this, wxID_ANY, _(L("Target path:")))); + content_sizer->AddSpacer(VERT_SPACING); + txtctrl_path = new wxTextCtrl(this, wxID_ANY, path.wstring()); + content_sizer->Add(txtctrl_path, 1, wxEXPAND); + content_sizer->AddSpacer(VERT_SPACING); + + wxButton* btn = new wxButton(this, wxID_ANY, _L("Select path")); + content_sizer->Add(btn/*, 1, wxEXPAND*/); + + // button to open file dialog + btn->Bind(wxEVT_BUTTON, ([this, path](wxCommandEvent& e) { + std::string extension = path.filename().extension().string(); + wxString wildcard; + if (!extension.empty()) { + extension = extension.substr(1); + wxString wxext = boost::nowide::widen(extension); + wildcard = GUI::format_wxstr("%1% Files (*.%2%)|*.%2%", wxext.Upper(), wxext); + } + wxFileDialog save_dlg( + this + , _L("Save as:") + , txtctrl_path->GetValue() + , boost::nowide::widen(AppUpdater::get_filename_from_url(txtctrl_path->GetValue().ToUTF8().data())) + , wildcard + , wxFD_SAVE | wxFD_OVERWRITE_PROMPT + ); + if (save_dlg.ShowModal() == wxID_OK) { + txtctrl_path->SetValue(save_dlg.GetPath()); + } + })); content_sizer->SetMinSize(AppUpdateAvailableDialog::AUAD_size); @@ -150,8 +179,17 @@ AppUpdateDownloadDialog::AppUpdateDownloadDialog( const Semver& ver_online) if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) { btn_ok->SetLabel(_L("Download")); + btn_ok->Bind(wxEVT_BUTTON, ([this, path](wxCommandEvent& e){ + if (boost::filesystem::exists(boost::filesystem::path(txtctrl_path->GetValue().ToUTF8().data()))) { + MessageDialog msgdlg(nullptr, GUI::format_wxstr(_L("File %1% already exists. Do you wish to overwrite it?"), txtctrl_path->GetValue()),_L("Notice"), wxYES_NO); + if (msgdlg.ShowModal() != wxID_YES) + return; + } + this->EndModal(wxID_OK); + })); } + finalize(); } @@ -166,9 +204,9 @@ bool AppUpdateDownloadDialog::run_after_download() const return false; } -bool AppUpdateDownloadDialog::select_download_path() const +boost::filesystem::path AppUpdateDownloadDialog::get_download_path() const { - return cbox_path->GetValue(); + return std::move(boost::filesystem::path(txtctrl_path->GetValue().ToUTF8().data())); } // MsgUpdateConfig diff --git a/src/slic3r/GUI/UpdateDialogs.hpp b/src/slic3r/GUI/UpdateDialogs.hpp index fbc21a558f..3d9ab5a535 100644 --- a/src/slic3r/GUI/UpdateDialogs.hpp +++ b/src/slic3r/GUI/UpdateDialogs.hpp @@ -57,7 +57,7 @@ private: class AppUpdateDownloadDialog : public MsgDialog { public: - AppUpdateDownloadDialog(const Semver& ver_online); + AppUpdateDownloadDialog(const Semver& ver_online, boost::filesystem::path& path); AppUpdateDownloadDialog(AppUpdateDownloadDialog&&) = delete; AppUpdateDownloadDialog(const AppUpdateDownloadDialog&) = delete; AppUpdateDownloadDialog& operator=(AppUpdateDownloadDialog&&) = delete; @@ -65,12 +65,12 @@ public: virtual ~AppUpdateDownloadDialog(); // Tells whether the user checked the "don't bother me again" checkbox - bool run_after_download() const; - bool select_download_path() const; + bool run_after_download() const; + boost::filesystem::path get_download_path() const; private: wxCheckBox* cbox_run; - wxCheckBox* cbox_path; + wxTextCtrl* txtctrl_path; }; // Confirmation dialog informing about configuration update. Lists updated bundles & their versions. diff --git a/src/slic3r/Utils/AppUpdater.cpp b/src/slic3r/Utils/AppUpdater.cpp index 26bf883de7..60739ccb39 100644 --- a/src/slic3r/Utils/AppUpdater.cpp +++ b/src/slic3r/Utils/AppUpdater.cpp @@ -14,6 +14,8 @@ #include "slic3r/GUI/GUI.hpp" #include "slic3r/Utils/Http.hpp" +#include "libslic3r/Utils.hpp" + #ifdef _WIN32 #include #include @@ -30,44 +32,16 @@ namespace { #ifdef _WIN32 bool run_file(const boost::filesystem::path& path) { - // find updater exe - if (boost::filesystem::exists(path)) { - // run updater. Original args: /silent -restartapp prusa-slicer.exe -startappfirst - - // Using quoted string as mentioned in CreateProcessW docs, silent execution parameter. - std::wstring wcmd = L"\"" + path.wstring(); //lm: closing quote? - - // additional information - STARTUPINFOW si; - PROCESS_INFORMATION pi; - - // set the size of the structures - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - - // start the program up - if (CreateProcessW(NULL, // the path - wcmd.data(), // Command line - NULL, // Process handle not inheritable - NULL, // Thread handle not inheritable - FALSE, // Set handle inheritance to FALSE - 0, // No creation flags - NULL, // Use parent's environment block - NULL, // Use parent's starting directory - &si, // Pointer to STARTUPINFO structure - &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses) - )) { - // Close process and thread handles. - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - return true; - } - else { - BOOST_LOG_TRIVIAL(error) << "Failed to run " << wcmd; //lm: maybe a UI error message? - } + std::string msg; + bool res = GUI::create_process(path, std::wstring(), msg); + if (!res) { + std::string full_message = GUI::format("Running downloaded instaler of %1% has failed:\n%2%", SLIC3R_APP_NAME, msg); + BOOST_LOG_TRIVIAL(error) << full_message; // lm: maybe UI error msg? // dk: bellow. (maybe some general show error evt would be better?) + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); + evt->SetString(full_message); + GUI::wxGetApp().QueueEvent(evt); } - return false; + return res; } std::string get_downloads_path() @@ -81,108 +55,6 @@ namespace { CoTaskMemFree(path); return ret; } - - bool open_folder(const boost::filesystem::path& path) - { - // this command can run the installer exe as well, but is it better than CreateProcessW? - ShellExecuteW(NULL, NULL, path.wstring().c_str(), NULL, NULL, SW_SHOWNORMAL); - //lm:I would make it explicit that the folder should be opened. - //lm:Also, this always returns true. - return true; - } - -#elif __linux__ - bool run_file(const boost::filesystem::path& path) - { - return false; - } - - std::string get_downloads_path() - { - wxString command = "xdg-user-dir DOWNLOAD"; - wxArrayString output; - - //lm:It might be a good idea to make the following a separate function in GUI_Utils or something - // It is already used in four different places in almost the same way. - - //Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, - // because they may mess up the environment expected by the file manager. - // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. - if (wxGetEnv("APPIMAGE", nullptr)) { - // We're running from AppImage - wxEnvVariableHashMap env_vars; - wxGetEnvMap(&env_vars); - - env_vars.erase("APPIMAGE"); - env_vars.erase("APPDIR"); - env_vars.erase("LD_LIBRARY_PATH"); - env_vars.erase("LD_PRELOAD"); - env_vars.erase("UNION_PRELOAD"); - - wxExecuteEnv exec_env; - exec_env.env = std::move(env_vars); - - wxString owd; - if (wxGetEnv("OWD", &owd)) { - // This is the original work directory from which the AppImage image was run, - // set it as CWD for the child process: - exec_env.cwd = std::move(owd); - } - - ::wxExecute(command, output, 0, &exec_env); - - } else { - // Looks like we're NOT running from AppImage, we'll make no changes to the environment. - ::wxExecute(command, output); - } - if (output.GetCount() > 0) { - return boost::nowide::narrow(output[0]); //lm:I would use wxString::ToUTF8(), although on Linux, nothing at all should work too. - } - return std::string(); - } - - bool open_folder(const boost::filesystem::path& path) - { - if (boost::filesystem::is_directory(path)) { - const char *argv[] = { "xdg-open", path.string().c_str(), nullptr }; - - //lm:This is a copy of desktop_open_datadir_folder, it would make sense to instead call it. - - // Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars, - // because they may mess up the environment expected by the file manager. - // Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure. - if (wxGetEnv("APPIMAGE", nullptr)) { - // We're running from AppImage - wxEnvVariableHashMap env_vars; - wxGetEnvMap(&env_vars); - - env_vars.erase("APPIMAGE"); - env_vars.erase("APPDIR"); - env_vars.erase("LD_LIBRARY_PATH"); - env_vars.erase("LD_PRELOAD"); - env_vars.erase("UNION_PRELOAD"); - - wxExecuteEnv exec_env; - exec_env.env = std::move(env_vars); - - wxString owd; - if (wxGetEnv("OWD", &owd)) { - // This is the original work directory from which the AppImage image was run, - // set it as CWD for the child process: - exec_env.cwd = std::move(owd); - } - - ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, &exec_env); - - } else { - // Looks like we're NOT running from AppImage, we'll make no changes to the environment. - ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr, nullptr); - } - return true; - } - return false; - } - #elif __APPLE__ bool run_file(const boost::filesystem::path& path) { @@ -203,24 +75,30 @@ namespace { // call objective-c implementation return get_downloads_path_mac(); } - - bool open_folder(const boost::filesystem::path& path) - { - - if (boost::filesystem::is_directory(path)) { - const char* argv[] = { "open", path.string().c_str(), nullptr }; - ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); - return true; - } +#else + bool run_file(const boost::filesystem::path& path) + { return false; } -#endif + + std::string get_downloads_path() + { + wxString command = "xdg-user-dir DOWNLOAD"; + wxArrayString output; + GUI::desktop_execute_get_result(command, output); + if (output.GetCount() > 0) { + return output[0].ToUTF8().data(); //lm:I would use wxString::ToUTF8(), although on Linux, nothing at all should work too. + } + return std::string(); + } +#endif // _WIN32 / __apple__ / else } // namespace wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); wxDEFINE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, wxCommandEvent); wxDEFINE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_FAILED, wxCommandEvent); +wxDEFINE_EVENT(EVT_SLIC3R_APP_OPEN_FAILED, wxCommandEvent); // priv handles all operations in separate thread // 1) download version file and parse it. @@ -251,12 +129,19 @@ struct AppUpdater::priv { std::thread m_thread; std::atomic_bool m_cancel; std::mutex m_data_mutex; + // used to tell if notify user hes about to stop ongoing download + std::atomic_bool m_download_ongoing { false }; + bool get_download_ongoing() const { return m_download_ongoing; } // read only variable used to init m_online_version_data.target_path boost::filesystem::path m_default_dest_folder; // readonly // DownloadAppData read / write needs to be locked by m_data_mutex DownloadAppData m_online_version_data; DownloadAppData get_app_data(); - void set_app_data(DownloadAppData data); + void set_app_data(DownloadAppData data); + // set only before version file is downloaded, to keep information to show info dialog about no updates + // should never change during thread run + std::atomic_bool m_triggered_by_user {false}; + bool get_triggered_by_user() const { return m_triggered_by_user; } }; AppUpdater::priv::priv() : @@ -271,7 +156,7 @@ AppUpdater::priv::priv() : if (!downloads_path.empty()) { m_default_dest_folder = std::move(downloads_path); } - BOOST_LOG_TRIVIAL(error) << "Default download path: " << m_default_dest_folder; //lm:Is this an error? + BOOST_LOG_TRIVIAL(trace) << "App updater default download path: " << m_default_dest_folder; //lm:Is this an error? // dk: changed to trace } @@ -284,7 +169,7 @@ bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, // progress function returns true as success (to continue) cancel = (this->m_cancel ? true : !progress_fn(std::move(progress))); if (cancel) { - error_message = GUI::format("Error getting: `%1%`: Download was canceled.", //lm:typo + error_message = GUI::format("Error getting: `%1%`: Download was canceled.", //lm:typo //dk: am i blind? :) url); BOOST_LOG_TRIVIAL(debug) << "AppUpdater::priv::http_get_file message: "<< error_message; } @@ -318,7 +203,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d return boost::filesystem::path(); } std::string error_message; - bool res = http_get_file(data.url, 80 * 1024 * 1024 //TODO: what value here //lm:I don't know, but larger. The binaries will grow. + bool res = http_get_file(data.url, 130 * 1024 * 1024 //2.4.0 windows installer is 65MB //lm:I don't know, but larger. The binaries will grow. // dk: changed to 130, to have 100% more space. We should put this information into version file. // on_progress , [&last_gui_progress, expected_size](Http::Progress progress) { // size check @@ -329,12 +214,13 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d evt->SetString(message); GUI::wxGetApp().QueueEvent(evt); return false; - } else if (progress.dltotal > 0 && progress.dltotal < expected_size) { //lm:When will this happen? Is that not an error? - BOOST_LOG_TRIVIAL(error) << GUI::format("Downloading new %1% has incorrect size. The download will continue. \nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal);; - } + } else if (progress.dltotal > 0 && progress.dltotal < expected_size) { + //lm:When will this happen? Is that not an error? // dk: It is possible error, but we cannot know until the download is finished. Somehow the total size can grow during the download. + BOOST_LOG_TRIVIAL(info) << GUI::format("Downloading new %1% has incorrect size. The download will continue. \nExpected size: %2%\nDownload size: %3%", SLIC3R_APP_NAME, expected_size, progress.dltotal); + } // progress event size_t gui_progress = progress.dltotal > 0 ? 100 * progress.dlnow / progress.dltotal : 0; - //BOOST_LOG_TRIVIAL(error) << "App download " << gui_progress << "% " << progress.dlnow << " of " << progress.dltotal; + BOOST_LOG_TRIVIAL(error) << "App download " << gui_progress << "% " << progress.dlnow << " of " << progress.dltotal; if (last_gui_progress < gui_progress && (last_gui_progress != 0 || gui_progress != 100)) { last_gui_progress = gui_progress; wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS); @@ -348,8 +234,8 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d // Size check. Does always 1 char == 1 byte? size_t body_size = body.size(); if (body_size != expected_size) { - //lm:UI message? - BOOST_LOG_TRIVIAL(error) << "Downloaded file has wrong size. Expected size: " << expected_size << " Downloaded size: " << body_size; + //lm:UI message? // dk: changed. Now it propagates to UI. + error_message = GUI::format("Downloaded file has wrong size. Expected size: %1% Downloaded size: %2%", expected_size, body_size); return false; } boost::filesystem::path tmp_path = dest_path; @@ -363,7 +249,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d } catch (const std::exception&) { - BOOST_LOG_TRIVIAL(error) << "Failed to write and move " << tmp_path << " to " << dest_path; + error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path); return false; } return true; @@ -374,7 +260,9 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d { if (this->m_cancel) { - BOOST_LOG_TRIVIAL(error) << error_message; //lm:Is this an error? + BOOST_LOG_TRIVIAL(info) << error_message; //lm:Is this an error? // dk: changed to info + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); // FAILED with empty msg only closes progress notification + GUI::wxGetApp().QueueEvent(evt); } else { std::string message = GUI::format("Downloading new %1% has failed:\n%2%", SLIC3R_APP_NAME, error_message); BOOST_LOG_TRIVIAL(error) << message; @@ -391,9 +279,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d bool AppUpdater::priv::run_downloaded_file(boost::filesystem::path path) { assert(!path.empty()); - bool res = run_file(path); - BOOST_LOG_TRIVIAL(error) << "Running "<< path.string() << " was " << res; - return res; + return run_file(path); } void AppUpdater::priv::version_check(const std::string& version_check_url) @@ -414,8 +300,16 @@ void AppUpdater::priv::version_check(const std::string& version_check_url) //lm:In case the internet is not available, it will report no updates if run by user. // We might save a flag that we don't know or try to run the version_check again, reporting // the failure. - if (!res) - BOOST_LOG_TRIVIAL(error) << "Failed to download version file: " << error_message; + // dk: changed to download version every time. Dialog will show if m_triggered_by_user. + if (!res) { + std::string message = GUI::format("Downloading %1% version file has failed:\n%2%", SLIC3R_APP_NAME, error_message); + BOOST_LOG_TRIVIAL(error) << message; + if (m_triggered_by_user) { + wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); + evt->SetString(message); + GUI::wxGetApp().QueueEvent(evt); + } + } } void AppUpdater::priv::parse_version_string(const std::string& body) @@ -450,13 +344,14 @@ void AppUpdater::priv::parse_version_string(const std::string& body) if (section_name == #ifdef _WIN32 "release:win64" -#elif __linux__ - "release:linux" -#else +#elif __APPLE__ "release:osx" +#else + "release:linux" #endif //lm:Related to the ifdefs. We should also support BSD, which behaves similar to Linux in most cases. // Unless you have a reason not to, I would consider doing _WIN32, elif __APPLE__, else ... Not just here. +// dk: so its ok now or we need to specify BSD? ) { for (const auto& data : section.second) { if (data.first == "url") { @@ -530,7 +425,7 @@ void AppUpdater::priv::parse_version_string(const std::string& body) GUI::wxGetApp().QueueEvent(evt); } -#if 0 //lm:is this meant to be ressurected? +#if 0 //lm:is this meant to be ressurected? //dk: it is code that parses PrusaSlicer.version2 in 2.4.0, It was deleted from PresetUpdater.cpp and I would keep it here for possible reference. void AppUpdater::priv::parse_version_string_old(const std::string& body) const { @@ -643,17 +538,19 @@ void AppUpdater::sync_download() p->m_thread = std::thread( [this, input_data]() { + p->m_download_ongoing = true; if (boost::filesystem::path dest_path = p->download_file(input_data); boost::filesystem::exists(dest_path)){ if (input_data.start_after) { p->run_downloaded_file(std::move(dest_path)); } else { - open_folder(dest_path.parent_path()); + GUI::desktop_open_folder(dest_path.parent_path()); } } + p->m_download_ongoing = false; }); } -void AppUpdater::sync_version(const std::string& version_check_url) +void AppUpdater::sync_version(const std::string& version_check_url, bool from_user) { assert(p); // join thread first - it could have been in sync_download @@ -663,6 +560,7 @@ void AppUpdater::sync_version(const std::string& version_check_url) p->m_cancel = true; p->m_thread.join(); } + p->m_triggered_by_user = from_user; p->m_cancel = false; p->m_thread = std::thread( [this, version_check_url]() { @@ -707,5 +605,14 @@ DownloadAppData AppUpdater::get_app_data() return p->get_app_data(); } +bool AppUpdater::get_triggered_by_user() const +{ + return p->get_triggered_by_user(); +} + +bool AppUpdater::get_download_ongoing() const +{ + return p->get_download_ongoing(); +} } //namespace Slic3r diff --git a/src/slic3r/Utils/AppUpdater.hpp b/src/slic3r/Utils/AppUpdater.hpp index 2cdcb900bb..16d0d668f1 100644 --- a/src/slic3r/Utils/AppUpdater.hpp +++ b/src/slic3r/Utils/AppUpdater.hpp @@ -37,7 +37,7 @@ public: // downloads app file void sync_download(); // downloads version file - void sync_version(const std::string& version_check_url); + void sync_version(const std::string& version_check_url, bool from_user); void cancel(); bool cancel_callback(); @@ -46,6 +46,9 @@ public: static std::string get_filename_from_url(const std::string& url); static std::string get_file_extension_from_url(const std::string& url); + // atomic bool + bool get_triggered_by_user() const; + bool get_download_ongoing() const; // mutex access void set_app_data(DownloadAppData data); DownloadAppData get_app_data(); @@ -58,5 +61,6 @@ wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); wxDECLARE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_PROGRESS, wxCommandEvent); wxDECLARE_EVENT(EVT_SLIC3R_APP_DOWNLOAD_FAILED, wxCommandEvent); +wxDECLARE_EVENT(EVT_SLIC3R_APP_OPEN_FAILED, wxCommandEvent); } //namespace Slic3r #endif diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 40f068155a..f4863ff20a 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -135,10 +135,6 @@ struct Updates std::vector updates; }; - -//wxDEFINE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); -//wxDEFINE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); - struct PresetUpdater::priv { std::vector index_db; @@ -162,8 +158,6 @@ struct PresetUpdater::priv void set_download_prefs(AppConfig *app_config); bool get_file(const std::string &url, const fs::path &target_path) const; void prune_tmps() const; -// void sync_version() const; -// void parse_version_string(const std::string& body) const; void sync_config(const VendorMap vendors); void check_install_indices() const; @@ -238,105 +232,6 @@ void PresetUpdater::priv::prune_tmps() const } } -// moved to app updater - /* -// Get Slic3rPE version available online, save in AppConfig. -void PresetUpdater::priv::sync_version() const -{ - if (! enabled_version_check) { return; } - - BOOST_LOG_TRIVIAL(info) << format("Downloading %1% online version from: `%2%`", SLIC3R_APP_NAME, version_check_url); - - Http::get(version_check_url) - .size_limit(SLIC3R_VERSION_BODY_MAX) - .on_progress([this](Http::Progress, bool &cancel) { - cancel = this->cancel; - }) - .on_error([&](std::string body, std::string error, unsigned http_status) { - (void)body; - BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%", - version_check_url, - http_status, - error); - }) - .on_complete([&](std::string body, unsigned ) { - boost::trim(body); - parse_version_string(body); - }) - .perform_sync(); -} - -// Parses version string obtained in sync_version() and sends events to UI thread. -// Version string must contain release version on first line. Follows non-mandatory alpha / beta releases on following lines (alpha=2.0.0-alpha1). -void PresetUpdater::priv::parse_version_string(const std::string& body) const -{ - - // release version - std::string version; - const auto first_nl_pos = body.find_first_of("\n\r"); - if (first_nl_pos != std::string::npos) - version = body.substr(0, first_nl_pos); - else - version = body; - boost::optional release_version = Semver::parse(version); - if (!release_version) { - BOOST_LOG_TRIVIAL(error) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version); - return; - } - BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE); - evt->SetString(GUI::from_u8(version)); - GUI::wxGetApp().QueueEvent(evt); - - // alpha / beta version - std::vector prerelease_versions; - size_t nexn_nl_pos = first_nl_pos; - while (nexn_nl_pos != std::string::npos && body.size() > nexn_nl_pos + 1) { - const auto last_nl_pos = nexn_nl_pos; - nexn_nl_pos = body.find_first_of("\n\r", last_nl_pos + 1); - std::string line; - if (nexn_nl_pos == std::string::npos) - line = body.substr(last_nl_pos + 1); - else - line = body.substr(last_nl_pos + 1, nexn_nl_pos - last_nl_pos - 1); - - // alpha - if (line.substr(0, 6) == "alpha=") { - version = line.substr(6); - if (!Semver::parse(version)) { - BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for alpha release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version); - return; - } - prerelease_versions.emplace_back(version); - // beta - } - else if (line.substr(0, 5) == "beta=") { - version = line.substr(5); - if (!Semver::parse(version)) { - BOOST_LOG_TRIVIAL(error) << format("Received invalid contents for beta release from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, version); - return; - } - prerelease_versions.emplace_back(version); - } - } - // find recent version that is newer than last full release. - boost::optional recent_version; - for (const std::string& ver_string : prerelease_versions) { - boost::optional ver = Semver::parse(ver_string); - if (ver && *release_version < *ver && ((recent_version && *recent_version < *ver) || !recent_version)) { - recent_version = ver; - version = ver_string; - } - } - if (recent_version) { - BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, version); - wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE); - evt->SetString(GUI::from_u8(version)); - GUI::wxGetApp().QueueEvent(evt); - } - -} -*/ // Download vendor indices. Also download new bundles if an index indicates there's a new one available. // Both are saved in cache. void PresetUpdater::priv::sync_config(const VendorMap vendors) @@ -747,7 +642,6 @@ void PresetUpdater::sync(PresetBundle *preset_bundle) p->thread = std::thread([this, vendors]() { this->p->prune_tmps(); -// this->p->sync_version(); this->p->sync_config(std::move(vendors)); }); } From 6853f8a3c6251c4cd278dc765fb49195c5d7a8cf Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 18 Feb 2022 16:47:24 +0100 Subject: [PATCH 32/46] MacOS build fixes --- src/slic3r/GUI/GUI.cpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 1d32832aa4..6c52a79a85 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -491,7 +491,7 @@ void desktop_open_folder(const boost::filesystem::path& path) const wchar_t* argv[] = { L"explorer", widepath.GetData(), nullptr }; ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); #elif __APPLE__ - const char* argv[] = { "open", path.string(), nullptr }; + const char* argv[] = { "open", path.string().c_str(), nullptr }; ::wxExecute(const_cast(argv), wxEXEC_ASYNC, nullptr); #else const char* argv[] = { "xdg-open", path.string().c_str(), nullptr }; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 8110d42dd8..76f321d893 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1239,7 +1239,7 @@ bool GUI_App::on_init_inner() show_error(nullptr, evt.GetString()); }); - Bind(EVT_SLIC3R_APP_OPEN_FAILED, [this](const wxCommandEvent& evt) { + Bind(EVT_SLIC3R_APP_OPEN_FAILED, [](const wxCommandEvent& evt) { show_error(nullptr, evt.GetString()); }); } From 3cecd0701173d881c7782b03af076c589292d55a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 23 Mar 2022 11:11:13 +0100 Subject: [PATCH 33/46] Tech ENABLE_LEGACY_OPENGL_REMOVAL - Refactoring of Camera::apply_viewport() --- src/slic3r/GUI/Camera.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 77ce27a799..1370484c3d 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -106,7 +106,11 @@ double Camera::get_fov() const void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h) { glsafe(::glViewport(0, 0, w, h)); +#if ENABLE_LEGACY_OPENGL_REMOVAL + m_viewport = { 0, 0, int(w), int(h) }; +#else glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data())); +#endif // ENABLE_LEGACY_OPENGL_REMOVAL } #if !ENABLE_LEGACY_OPENGL_REMOVAL From 4b4ed423ef0c606d3f95ab5e9ac9dc9f765d4a8e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 23 Mar 2022 13:16:51 +0100 Subject: [PATCH 34/46] Tech ENABLE_LEGACY_OPENGL_REMOVAL - Fix into GLModel::send_to_gpu() --- src/slic3r/GUI/GLModel.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 9c9d695260..75998609be 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -1130,6 +1130,7 @@ bool GLModel::send_to_gpu() glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } else { + data.index_type = Geometry::EIndexType::UINT; glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.indices_size_bytes(), data.indices.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } From 24bcbd9c0ceb4ebd8035a0b69324140dee9d818b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 23 Mar 2022 15:18:24 +0100 Subject: [PATCH 35/46] Optimization in GLCanvas3D::_render_camera_target() --- src/slic3r/GUI/GLCanvas3D.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5539d681c4..51a0f0585a 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6070,35 +6070,34 @@ void GLCanvas3D::_render_camera_target() #if ENABLE_LEGACY_OPENGL_REMOVAL const Vec3f& target = wxGetApp().plater()->get_camera().get_target().cast(); - bool target_changed = !m_camera_target.target.isApprox(target.cast()); m_camera_target.target = target.cast(); for (int i = 0; i < 3; ++i) { - if (!m_camera_target.axis[i].is_initialized() || target_changed) { + if (!m_camera_target.axis[i].is_initialized()) { m_camera_target.axis[i].reset(); GLModel::Geometry init_data; - init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, GLModel::Geometry::EIndexType::USHORT }; + init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 }; init_data.color = (i == X) ? ColorRGBA::X() : ((i == Y) ? ColorRGBA::Y() : ColorRGBA::Z()); init_data.reserve_vertices(2); init_data.reserve_indices(2); // vertices if (i == X) { - init_data.add_vertex(Vec3f(target.x() - half_length, target.y(), target.z())); - init_data.add_vertex(Vec3f(target.x() + half_length, target.y(), target.z())); + init_data.add_vertex(Vec3f(-half_length, 0.0f, 0.0f)); + init_data.add_vertex(Vec3f(+half_length, 0.0f, 0.0f)); } else if (i == Y) { - init_data.add_vertex(Vec3f(target.x(), target.y() - half_length, target.z())); - init_data.add_vertex(Vec3f(target.x(), target.y() + half_length, target.z())); + init_data.add_vertex(Vec3f(0.0f, -half_length, 0.0f)); + init_data.add_vertex(Vec3f(0.0f, +half_length, 0.0f)); } else { - init_data.add_vertex(Vec3f(target.x(), target.y(), target.z() - half_length)); - init_data.add_vertex(Vec3f(target.x(), target.y(), target.z() + half_length)); + init_data.add_vertex(Vec3f(0.0f, 0.0f, -half_length)); + init_data.add_vertex(Vec3f(0.0f, 0.0f, +half_length)); } // indices - init_data.add_ushort_line(0, 1); + init_data.add_line(0, 1); m_camera_target.axis[i].init_from(std::move(init_data)); } @@ -6109,7 +6108,7 @@ void GLCanvas3D::_render_camera_target() shader->start_using(); #if ENABLE_GL_SHADERS_ATTRIBUTES const Camera& camera = wxGetApp().plater()->get_camera(); - shader->set_uniform("view_model_matrix", camera.get_view_matrix()); + shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::assemble_transform(m_camera_target.target)); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #endif // ENABLE_GL_SHADERS_ATTRIBUTES for (int i = 0; i < 3; ++i) { From eae393255008fd2b94e66b613b42c0f6d4c058c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 24 Mar 2022 09:33:26 +0100 Subject: [PATCH 36/46] Added missing includes (GCC11.1 without PCH). --- src/slic3r/GUI/GUI.cpp | 1 + src/slic3r/GUI/GUI.hpp | 1 + src/slic3r/GUI/UpdateDialogs.cpp | 1 + src/slic3r/GUI/UpdateDialogs.hpp | 2 ++ 4 files changed, 5 insertions(+) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 6c52a79a85..72b8283074 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #if __APPLE__ #import diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index 2eb99e7bc7..cb7cf54874 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -13,6 +13,7 @@ class wxWindow; class wxMenuBar; class wxComboCtrl; class wxFileDialog; +class wxArrayString; class wxTopLevelWindow; namespace Slic3r { diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index 531e99ea25..0441e866f3 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include diff --git a/src/slic3r/GUI/UpdateDialogs.hpp b/src/slic3r/GUI/UpdateDialogs.hpp index 3d9ab5a535..2eb4ff8d4f 100644 --- a/src/slic3r/GUI/UpdateDialogs.hpp +++ b/src/slic3r/GUI/UpdateDialogs.hpp @@ -6,6 +6,8 @@ #include #include +#include + #include "libslic3r/Semver.hpp" #include "MsgDialog.hpp" From 11f0dc458933d8078c63430438e0c4b7ab75bc38 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 24 Mar 2022 09:51:42 +0100 Subject: [PATCH 37/46] Tech ENABLE_NEW_CAMERA_MOVEMENTS - Reverted middle mouse dragging to pan the view --- src/slic3r/GUI/GLCanvas3D.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 51a0f0585a..709b77d5b3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3599,9 +3599,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } // do not process the dragging if the left mouse was set down in another canvas #if ENABLE_NEW_CAMERA_MOVEMENTS - else if (evt.LeftIsDown() || evt.MiddleIsDown()) { + else if (evt.LeftIsDown()) { // if dragging over blank area with left button, rotate - if ((any_gizmo_active || evt.CmdDown() || evt.MiddleIsDown() || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) { + if ((any_gizmo_active || evt.CmdDown() || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) { #else // if dragging over blank area with left button, rotate else if (evt.LeftIsDown()) { @@ -3625,13 +3625,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } m_mouse.drag.start_position_3D = Vec3d((double)pos.x(), (double)pos.y(), 0.0); } -#if ENABLE_NEW_CAMERA_MOVEMENTS - else if (evt.RightIsDown()) { - // If dragging with right button, pan. -#else else if (evt.MiddleIsDown() || evt.RightIsDown()) { - // If dragging over blank area with right button, pan. -#endif // ENABLE_NEW_CAMERA_MOVEMENTS + // If dragging over blank area with right/middle button, pan. if (m_mouse.is_start_position_2D_defined()) { // get point in model space at Z = 0 float z = 0.0f; From 94b98e349b65bf3b85839175daffa018ebe5eeaa Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 24 Mar 2022 10:10:17 +0100 Subject: [PATCH 38/46] Tech ENABLE_NEW_RECTANGLE_SELECTION - Fixed SHIFT + left mouse selection/deselection --- src/slic3r/GUI/GLCanvas3D.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 709b77d5b3..6535be25cb 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3438,6 +3438,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #endif // !ENABLE_NEW_RECTANGLE_SELECTION else { #if ENABLE_NEW_RECTANGLE_SELECTION + const bool rectangle_selection_dragging = m_rectangle_selection.is_dragging(); if (evt.LeftDown() && (evt.ShiftDown() || evt.AltDown()) && m_picking_enabled) { if (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports && m_gizmos.get_current_type() != GLGizmosManager::FdmSupports && @@ -3454,8 +3455,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // during the scene manipulation. #if ENABLE_NEW_RECTANGLE_SELECTION - if (m_picking_enabled && (!any_gizmo_active || !evt.ShiftDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) && - !m_rectangle_selection.is_dragging()) { + if (m_picking_enabled && !any_gizmo_active && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled()) && !rectangle_selection_dragging) { #else if (m_picking_enabled && (!any_gizmo_active || !evt.CmdDown()) && (!m_hover_volume_idxs.empty() || !is_layers_editing_enabled())) { #endif // ENABLE_NEW_RECTANGLE_SELECTION From 97a5aa9592f24adc0e811e678c74597bde21776d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 23 Mar 2022 16:47:52 +0100 Subject: [PATCH 39/46] Added a new test case for a missing Voronoi vertex. --- tests/libslic3r/test_voronoi.cpp | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/libslic3r/test_voronoi.cpp b/tests/libslic3r/test_voronoi.cpp index db12e2fec1..7f25797f56 100644 --- a/tests/libslic3r/test_voronoi.cpp +++ b/tests/libslic3r/test_voronoi.cpp @@ -2055,6 +2055,50 @@ TEST_CASE("Voronoi missing vertex 3", "[VoronoiMissingVertex3]") // REQUIRE(!has_missing_voronoi_vertices(poly, vd)); } +TEST_CASE("Voronoi missing vertex 4", "[VoronoiMissingVertex4]") +{ + // Probably the reason why Voronoi vertex is missing is that 19299999 and 19300000 are very close. + Polygon polygon_1 = { + Point(27000000, -18900000), + Point(27000000, 20000000), + Point(19000000, 20000000), + Point(19000000, 19299999), + Point(26000000, -18000000), + Point(-19000000, -18000000), + Point(-27000000, 19300000), + Point(-19000000, 19300000), + Point(-19000000, 20000000), + Point(-28000000, 20000000), + Point(-20000000, -18900000), + }; + + // Maybe this is the same case as the previous, but the missing Voronoi vertex is different. + Polygon polygon_2 = { + Point(27000000, -18900000), + Point(27000000, 20000000), + Point(19000000, 20000000), + Point(19000000, 19299999), + Point(19000000, -18000000), // Just this point is different other points are the same as previous. + Point(-19000000, -18000000), + Point(-27000000, 19300000), + Point(-19000000, 19300000), + Point(-19000000, 20000000), + Point(-28000000, 20000000), + Point(-20000000, -18900000), + }; + + Geometry::VoronoiDiagram vd_1; + Geometry::VoronoiDiagram vd_2; + Lines lines_1 = to_lines(polygon_1); + Lines lines_2 = to_lines(polygon_2); + construct_voronoi(lines_1.begin(), lines_1.end(), &vd_1); + construct_voronoi(lines_2.begin(), lines_2.end(), &vd_2); +#ifdef VORONOI_DEBUG_OUT + dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex4-1-out.svg").c_str(), vd_1, Points(), lines_1); + dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex4-2-out.svg").c_str(), vd_2, Points(), lines_2); +#endif +} + // In this case, the Voronoi vertex (146873, -146873) is included twice. // Also, near to those duplicate Voronoi vertices is another Voronoi vertex (146872, -146872). // Rotating the polygon will help solve this problem, but then there arise three very close Voronoi vertices. From 7d2e89286fd52145d18eb206780c435f996158f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 24 Mar 2022 09:47:33 +0100 Subject: [PATCH 40/46] Added a possibility into thick_polyline_to_extrusion_paths() to separately set tolerance for merging two following lines based on a difference between lines width. --- src/libslic3r/PerimeterGenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 51c26209e9..01d3c592a6 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -8,7 +8,7 @@ namespace Slic3r { -static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance) +static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance) { ExtrusionPaths paths; ExtrusionPath path(role); @@ -71,7 +71,7 @@ static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thi path.height = new_flow.height(); } else { thickness_delta = fabs(scale_(flow.width()) - w); - if (thickness_delta <= tolerance) { + if (thickness_delta <= merge_tolerance) { // the width difference between this line and the current flow width is // within the accepted tolerance path.polyline.append(line.b); @@ -95,7 +95,7 @@ static void variable_width(const ThickPolylines& polylines, ExtrusionRole role, // of segments, and any pruning shall be performed before we apply this tolerance. const float tolerance = float(scale_(0.05)); for (const ThickPolyline &p : polylines) { - ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance); + ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance, tolerance); // Append paths to collection. if (! paths.empty()) { if (paths.front().first_point() == paths.back().last_point()) From fa565ca468c2cf8a1858c681dbf3f449ba4157d1 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Thu, 24 Mar 2022 12:26:28 +0100 Subject: [PATCH 41/46] Sync with PrusaSlicer-settings. --- resources/profiles/PrusaResearch.idx | 1 + resources/profiles/PrusaResearch.ini | 345 ++++++++++++++++++++++++--- 2 files changed, 315 insertions(+), 31 deletions(-) diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index 9ee9035631..d63336c2ef 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,4 +1,5 @@ min_slic3r_version = 2.4.0-rc +1.4.4 Added multiple Fiberlogy filament profiles. Updated Extrudr filament profiles. 1.4.3 Added new filament profiles and SLA materials. 1.4.2 Added SLA material profiles. 1.4.1 Updated firmware version. diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 3182eba6bb..4af1e35ed1 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -5,7 +5,7 @@ name = Prusa Research # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.4.3 +config_version = 1.4.4 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaResearch/ changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1% @@ -2050,7 +2050,7 @@ compatible_printers_condition = nozzle_diameter[0]!=0.8 and printer_model!="MK2S inherits = Fillamentum ASA filament_vendor = Extrudr bed_temperature = 90 -filament_cost = 25.98 +filament_cost = 34.64 filament_density = 1.05 filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=120" first_layer_bed_temperature = 90 @@ -2083,8 +2083,8 @@ filament_vendor = Extrudr [filament:Extrudr XPETG CF] inherits = Extrudr PETG -filament_cost = 49.99 -filament_density = 1.41 +filament_cost = 62.49 +filament_density = 1.29 filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=198" first_layer_temperature = 235 temperature = 235 @@ -2125,7 +2125,7 @@ filament_spool_weight = 230 [filament:Extrudr Flax] inherits = *PLA* filament_vendor = Extrudr -filament_cost = 56.23 +filament_cost = 50.91 filament_density = 1.45 filament_notes = "High Performance Filament for decorative parts.\nPrints as easily as PLA with much higher strength and temperature resistance.\nFully biodegradable with a nice matt finish.\n\nhttps://www.extrudr.com/en/products/catalogue/?material=131" first_layer_temperature = 190 @@ -2140,13 +2140,13 @@ filament_spool_weight = 262 [filament:Extrudr GreenTEC] inherits = *PLA* filament_vendor = Extrudr -filament_cost = 56 +filament_cost = 50.91 filament_density = 1.3 -filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=106" +filament_notes = "https://www.extrudr.com/en/products/catalogue/?ignorechildren=1&material=106" first_layer_temperature = 208 temperature = 208 slowdown_below_layer_time = 20 -filament_spool_weight = 230 +filament_spool_weight = 262 [filament:Extrudr GreenTEC Pro] inherits = *PLA* @@ -2164,7 +2164,7 @@ filament_spool_weight = 230 [filament:Extrudr GreenTEC Pro Carbon] inherits = *PLA* filament_vendor = Extrudr -filament_cost = 56.23 +filament_cost = 62.49 filament_density = 1.2 filament_notes = "High Performance Filament for technical parts.\nPrints as easily as PLA with much higher stregnth and temperature resistance.\nFully biodegradable with a nice matt finish.\n\nhttps://www.extrudr.com/en/products/catalogue/?material=138" first_layer_temperature = 225 @@ -2221,8 +2221,8 @@ extrusion_multiplier = 1.2 filament_cost = 39.98 filament_density = 1.19 filament_deretract_speed = nil -filament_max_volumetric_speed = 2 -filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=115" +filament_max_volumetric_speed = 3 +filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=117" filament_retract_length = 0.4 filament_wipe = nil filament_spool_weight = 230 @@ -2236,8 +2236,8 @@ extrusion_multiplier = 1.2 filament_cost = 39.98 filament_density = 1.18 filament_deretract_speed = nil -filament_max_volumetric_speed = 1.2 -filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=115" +filament_max_volumetric_speed = 1.8 +filament_notes = "https://www.extrudr.com/en/products/catalogue/?material=116" filament_retract_length = 0.4 filament_wipe = nil filament_spool_weight = 230 @@ -3511,13 +3511,6 @@ filament_density = 1.27 filament_spool_weight = 235 compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) -[filament:Fiberlogy PETG] -inherits = *PET* -filament_vendor = Fiberlogy -filament_cost = 21.50 -filament_density = 1.27 -compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) - [filament:Prusament PETG] inherits = *PET* filament_vendor = Prusa Polymers @@ -3580,8 +3573,9 @@ filament_density = 1.27 filament_spool_weight = 235 filament_type = PETG -[filament:Fiberlogy PETG @0.6 nozzle] +[filament:Fiberlogy Easy PET-G @0.6 nozzle] inherits = *PET06* +renamed_from = Fiberlogy PETG @0.6 nozzle filament_vendor = Fiberlogy first_layer_temperature = 230 temperature = 240 @@ -3673,11 +3667,297 @@ filament_density = 1.24 filament_spool_weight = 230 compatible_printers_condition = nozzle_diameter[0]!=0.8 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) -[filament:Fiberlogy PLA] +[filament:Fiberlogy Easy PLA] inherits = *PLA* +renamed_from = Fiberlogy PLA filament_vendor = Fiberlogy -filament_cost = 25.4 +filament_cost = 20 filament_density = 1.24 +first_layer_temperature = 220 +temperature = 220 +filament_spool_weight = 330 + +[filament:Fiberlogy Easy PET-G] +inherits = *PET* +renamed_from = Fiberlogy PETG +filament_vendor = Fiberlogy +filament_spool_weight = 330 +filament_cost = 20 +filament_density = 1.27 +compatible_printers_condition = nozzle_diameter[0]!=0.6 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +first_layer_bed_temperature = 80 +bed_temperature = 80 +first_layer_temperature = 235 +temperature = 235 +min_fan_speed = 15 +max_fan_speed = 30 +bridge_fan_speed = 60 +disable_fan_first_layers = 5 +full_fan_speed_layer = 5 +slowdown_below_layer_time = 15 + +[filament:Fiberlogy ASA] +inherits = *ABS* +filament_vendor = Fiberlogy +filament_cost = 33 +filament_density = 1.07 +filament_spool_weight = 330 +fan_always_on = 0 +cooling = 1 +min_fan_speed = 10 +max_fan_speed = 15 +bridge_fan_speed = 30 +min_print_speed = 15 +slowdown_below_layer_time = 15 +first_layer_temperature = 260 +temperature = 260 +first_layer_bed_temperature = 105 +bed_temperature = 110 +filament_type = ASA +fan_below_layer_time = 30 +disable_fan_first_layers = 5 + +[filament:Fiberlogy ASA @MINI] +inherits = Fiberlogy ASA; *ABSMINI* + +[filament:Fiberlogy Easy ABS] +inherits = Fiberlogy ASA +filament_cost = 22.67 +filament_density = 1.09 +fan_always_on = 0 +cooling = 1 +min_fan_speed = 10 +max_fan_speed = 15 +min_print_speed = 15 +slowdown_below_layer_time = 15 +first_layer_temperature = 250 +temperature = 250 +first_layer_bed_temperature = 100 +bed_temperature = 100 +filament_type = ABS +fan_below_layer_time = 25 +disable_fan_first_layers = 5 + +[filament:Fiberlogy Easy ABS @MINI] +inherits = Fiberlogy Easy ABS; *ABSMINI* + +[filament:Fiberlogy CPE HT] +inherits = *PET* +filament_vendor = Fiberlogy +filament_cost = 42.67 +filament_density = 1.18 +extrusion_multiplier = 0.98 +filament_spool_weight = 330 +fan_always_on = 1 +cooling = 1 +min_fan_speed = 0 +max_fan_speed = 0 +bridge_fan_speed = 50 +min_print_speed = 15 +first_layer_temperature = 275 +temperature = 275 +first_layer_bed_temperature = 105 +bed_temperature = 110 +filament_type = CPE +fan_below_layer_time = 20 +slowdown_below_layer_time = 15 +disable_fan_first_layers = 5 + +[filament:Fiberlogy PCTG] +inherits = Fiberlogy CPE HT +filament_vendor = Fiberlogy +filament_cost = 29.41 +filament_density = 1.23 +extrusion_multiplier = 0.98 +min_fan_speed = 10 +max_fan_speed = 15 +bridge_fan_speed = 50 +min_print_speed = 15 +first_layer_temperature = 265 +temperature = 265 +first_layer_bed_temperature = 90 +bed_temperature = 90 +filament_type = CPE +fan_below_layer_time = 20 +slowdown_below_layer_time = 15 +disable_fan_first_layers = 5 + +[filament:Fiberlogy FiberFlex 40D] +inherits = *FLEX* +filament_vendor = Fiberlogy +fan_always_on = 1 +filament_max_volumetric_speed = 1.5 +extrusion_multiplier = 1.12 +first_layer_temperature = 230 +first_layer_bed_temperature = 60 +temperature = 230 +bed_temperature = 60 +bridge_fan_speed = 75 +min_fan_speed = 25 +max_fan_speed = 75 +filament_retract_before_travel = 2 +filament_cost = 39.41 +filament_density = 1.16 +filament_retract_length = 1.2 +filament_retract_speed = nil +filament_deretract_speed = 20 +filament_retract_lift = 0 +filament_wipe = 0 +disable_fan_first_layers = 5 +full_fan_speed_layer = 5 +min_print_speed = 15 +cooling = 1 +filament_spool_weight = 330 + +[filament:Fiberlogy FiberFlex 40D @MINI] +inherits = *FLEXMINI* +filament_vendor = Fiberlogy +filament_max_volumetric_speed = 1.5 +fan_always_on = 1 +first_layer_temperature = 240 +first_layer_bed_temperature = 60 +temperature = 240 +bed_temperature = 60 +filament_retract_length = 4 +filament_retract_before_travel = 5 +bridge_fan_speed = 80 +min_fan_speed = 25 +max_fan_speed = 60 +min_print_speed = 15 +slowdown_below_layer_time = 10 +cooling = 1 +filament_cost = 84.68 + +[filament:Fiberlogy MattFlex 40D] +inherits = Fiberlogy FiberFlex 40D +filament_vendor = Fiberlogy +fan_always_on = 1 +filament_max_volumetric_speed = 1.35 +extrusion_multiplier = 1.1 +filament_retract_before_travel = 2 +filament_cost = 49.11 +filament_retract_length = 1.2 + +[filament:Fiberlogy FiberFlex 30D] +inherits = Fiberlogy FiberFlex 40D +filament_max_volumetric_speed = 1.2 +extrusion_multiplier = 1.15 +first_layer_temperature = 240 +temperature = 240 +min_fan_speed = 25 +max_fan_speed = 60 +filament_density = 1.07 +filament_retract_length = 1.2 + +[filament:Fiberlogy FiberSatin] +inherits = Fiberlogy Easy PLA +first_layer_temperature = 215 +temperature = 215 +extrusion_multiplier = 1.03 +filament_density = 1.2 +filament_cost = 32.35 + +[filament:Fiberlogy FiberSilk] +inherits = Fiberlogy FiberSatin +first_layer_temperature = 230 +temperature = 230 +extrusion_multiplier = 0.97 +filament_density = 1.22 +filament_cost = 32.35 + +[filament:Fiberlogy FiberWood] +inherits = Fiberlogy Easy PLA +first_layer_temperature = 185 +temperature = 185 +extrusion_multiplier = 1 +filament_density = 1.23 +filament_cost = 38.66 +filament_max_volumetric_speed = 8 + +[filament:Fiberlogy HD PLA] +inherits = Fiberlogy Easy PLA +first_layer_temperature = 230 +temperature = 230 +extrusion_multiplier = 1 +filament_density = 1.24 +filament_cost = 30.59 + +[filament:Fiberlogy PLA Mineral] +inherits = Fiberlogy Easy PLA +first_layer_temperature = 195 +temperature = 190 +extrusion_multiplier = 0.98 +filament_density = 1.38 +filament_cost = 37.64 +filament_max_volumetric_speed = 10 + +[filament:Fiberlogy Impact PLA] +inherits = Fiberlogy HD PLA +filament_density = 1.22 +filament_cost = 27.65 + +[filament:Fiberlogy Nylon PA12] +inherits = Fiberlogy ASA +filament_type = NYLON +filament_density = 1.01 +filament_cost = 48 +first_layer_bed_temperature = 105 +bed_temperature = 110 +first_layer_temperature = 265 +temperature = 265 +min_fan_speed = 10 +max_fan_speed = 15 +fan_below_layer_time = 20 +bridge_fan_speed = 30 +fan_always_on = 0 +filament_retract_lift = 0.2 +filament_max_volumetric_speed = 6 +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.6}0.12{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/ and nozzle_diameter[0]==0.8}0.06{elsif printer_notes=~/.*PRINTER_MODEL_MINI.*/}0.2{elsif nozzle_diameter[0]==0.8}0.02{elsif nozzle_diameter[0]==0.6}0.04{else}0.08{endif} ; Filament gcode LA 1.5\n{if printer_notes=~/.*PRINTER_MODEL_MINI.*/};{elsif printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}M900 K200{elsif nozzle_diameter[0]==0.6}M900 K26{elsif nozzle_diameter[0]==0.8};{else}M900 K45{endif} ; Filament gcode LA 1.0" + +[filament:Fiberlogy Nylon PA12+CF15] +inherits = Fiberlogy Nylon PA12 +extrusion_multiplier = 0.97 +filament_density = 1.07 +filament_cost = 87.5 +first_layer_bed_temperature = 105 +bed_temperature = 110 +first_layer_temperature = 265 +temperature = 265 +min_fan_speed = 10 +max_fan_speed = 15 +fan_below_layer_time = 20 +bridge_fan_speed = 30 +fan_always_on = 0 +filament_max_volumetric_speed = 8 +compatible_printers_condition = nozzle_diameter[0]>=0.4 and printer_model!="MK2SMM" and printer_model!="MINI" and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) + +[filament:Fiberlogy Nylon PA12+GF15] +inherits = Fiberlogy Nylon PA12+CF15 +filament_density = 1.13 +filament_max_volumetric_speed = 8 + +[filament:Fiberlogy PP] +inherits = *ABS* +filament_vendor = Fiberlogy +filament_cost = 36.67 +filament_density = 1.05 +extrusion_multiplier = 1.05 +filament_spool_weight = 330 +fan_always_on = 1 +cooling = 1 +min_fan_speed = 0 +max_fan_speed = 25 +bridge_fan_speed = 70 +min_print_speed = 15 +slowdown_below_layer_time = 15 +first_layer_temperature = 245 +temperature = 245 +first_layer_bed_temperature = 0 +bed_temperature = 0 +filament_type = PP +fan_below_layer_time = 100 +disable_fan_first_layers = 5 +filament_max_volumetric_speed = 5 [filament:Filament PM PLA] inherits = *PLA* @@ -3736,7 +4016,7 @@ filament_density = 1.24 inherits = *PLA* filament_vendor = Prusa Polymers temperature = 215 -filament_cost = 30.24 +filament_cost = 36.29 filament_density = 1.24 filament_spool_weight = 201 filament_notes = "Affordable filament for everyday printing in premium quality manufactured in-house by Josef Prusa" @@ -3790,7 +4070,7 @@ filament_spool_weight = 230 [filament:Prusament PLA @MMU2] inherits = *PLA MMU2* filament_vendor = Prusa Polymers -filament_cost = 30.24 +filament_cost = 36.29 filament_density = 1.24 filament_spool_weight = 201 @@ -4124,8 +4404,9 @@ renamed_from = "Plasty Mladec PETG @MMU1" [filament:Verbatim PETG @MMU1] inherits = Verbatim PETG; *PETMMU1* -[filament:Fiberlogy PETG @MMU1] -inherits = Fiberlogy PETG; *PETMMU1* +[filament:Fiberlogy Easy PET-G @MMU1] +inherits = Fiberlogy Easy PET-G; *PETMMU1* +renamed_from = Fiberlogy PETG @MMU1 [filament:Prusa PETG @MMU1] inherits = Prusa PETG; *PETMMU1* @@ -4215,8 +4496,9 @@ compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0. inherits = Verbatim PETG; *PETMINI* compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6 -[filament:Fiberlogy PETG @MINI] -inherits = Fiberlogy PETG; *PETMINI* +[filament:Fiberlogy Easy PET-G @MINI] +inherits = Fiberlogy Easy PET-G; *PETMINI* +renamed_from = Fiberlogy PETG @MINI compatible_printers_condition = printer_model=="MINI" and nozzle_diameter[0]!=0.6 [filament:Generic ABS @MINI] @@ -4303,8 +4585,9 @@ renamed_from = "Plasty Mladec PETG @0.6 nozzle MINI" [filament:Verbatim PETG @0.6 nozzle MINI] inherits = Verbatim PETG; *PETMINI06* -[filament:Fiberlogy PETG @0.6 nozzle MINI] -inherits = Fiberlogy PETG; *PETMINI06* +[filament:Fiberlogy Easy PET-G @0.6 nozzle MINI] +inherits = Fiberlogy Easy PET-G; *PETMINI06* +renamed_from = Fiberlogy PETG @0.6 nozzle MINI [filament:Prusament ASA @MINI] inherits = Prusament ASA; *ABSMINI* From 8202862809bfd1dd367d39936c34447a6296117d Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 13 Jan 2022 16:48:41 +0100 Subject: [PATCH 42/46] object info notifiction not show on copy obj --- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 27c374b3f8..4370a2f644 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -821,7 +821,7 @@ void ObjectList::paste_objects_into_list(const std::vector& object_idxs) wxDataViewItemArray items; for (const size_t object : object_idxs) { - add_object_to_list(object); + add_object_to_list(object, false); items.Add(m_objects_model->GetItemById(object)); } From 9ece7c0ad47244a489ee72d1a81402ab6c561911 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 28 Feb 2022 13:33:32 +0100 Subject: [PATCH 43/46] Rendering of regular text after hypertext in regular notifications. (Using code from Hint notification) --- src/slic3r/GUI/NotificationManager.cpp | 110 +++++++++++++++++++++++-- src/slic3r/GUI/NotificationManager.hpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 +- 3 files changed, 106 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index fc9e5f49c8..fc20e43f5d 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -318,7 +318,8 @@ void NotificationManager::PopNotification::count_lines() } m_lines_count++; } - // hypertext calculation + // original hypertext calculation (when there was no text2) + /* if (!m_hypertext.empty()) { int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0; // m_endlines.size() - 2 because we are fitting hypertext instead of last endline if (ImGui::CalcTextSize((escape_string_cstyle(text.substr(prev_end, last_end - prev_end)) + m_hypertext).c_str()).x > m_window_width - m_window_width_offset) { @@ -326,9 +327,84 @@ void NotificationManager::PopNotification::count_lines() m_lines_count++; } } + */ + int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0; + int size_of_last_line = ImGui::CalcTextSize(text.substr(prev_end, last_end - prev_end).c_str()).x; + // hypertext calculation + if (!m_hypertext.empty()) { + if (size_of_last_line + ImGui::CalcTextSize(m_hypertext.c_str()).x > m_window_width - m_window_width_offset) { + // hypertext on new line + size_of_last_line = ImGui::CalcTextSize((m_hypertext + " ").c_str()).x; + m_endlines.push_back(last_end); + m_lines_count++; + } + else { + size_of_last_line += ImGui::CalcTextSize((m_hypertext + " ").c_str()).x; + } + } + // text after hypertext calculation + if (!m_text2.empty()) { + text = m_text2; + last_end = 0; + m_endlines2.clear(); + // if size_of_last_line too large to fit anything + size_t first_end = std::min(text.find_first_of('\n'), text.find_first_of(' ')); + if (size_of_last_line >= m_window_width - m_window_width_offset - ImGui::CalcTextSize(text.substr(0, first_end).c_str()).x) { + m_endlines2.push_back(0); + size_of_last_line = 0; + } + while (last_end < text.length() - 1) + { + size_t next_hard_end = text.find_first_of('\n', last_end); + if (next_hard_end != std::string::npos && ImGui::CalcTextSize(text.substr(last_end, next_hard_end - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) { + //next line is ended by '/n' + m_endlines2.push_back(next_hard_end); + last_end = next_hard_end + 1; + } + else { + // find next suitable endline + if (ImGui::CalcTextSize(text.substr(last_end).c_str()).x >= m_window_width - m_window_width_offset - size_of_last_line) { + // more than one line till end + size_t next_space = text.find_first_of(' ', last_end); + if (next_space > 0) { + size_t next_space_candidate = text.find_first_of(' ', next_space + 1); + while (next_space_candidate > 0 && ImGui::CalcTextSize(text.substr(last_end, next_space_candidate - last_end).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) { + next_space = next_space_candidate; + next_space_candidate = text.find_first_of(' ', next_space + 1); + } + } + else { + next_space = text.length(); + } + // when one word longer than line. + if (ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x > m_window_width - m_window_width_offset - size_of_last_line || + ImGui::CalcTextSize(text.substr(last_end, next_space - last_end).c_str()).x + size_of_last_line < (m_window_width - m_window_width_offset) / 5 * 3 + ) { + float width_of_a = ImGui::CalcTextSize("a").x; + int letter_count = (int)((m_window_width - m_window_width_offset - size_of_last_line) / width_of_a); + while (last_end + letter_count < text.size() && ImGui::CalcTextSize(text.substr(last_end, letter_count).c_str()).x < m_window_width - m_window_width_offset - size_of_last_line) { + letter_count += get_utf8_sequence_length(text, last_end + letter_count); + } + m_endlines2.push_back(last_end + letter_count); + last_end += letter_count; + } + else { + m_endlines2.push_back(next_space); + last_end = next_space + 1; + } + } + else { + m_endlines2.push_back(text.length()); + last_end = text.length(); + } - // m_text_2 (text after hypertext) is not used for regular notifications right now. - // its caluculation is in HintNotification::count_lines() + } + if (size_of_last_line == 0) // if first line is continuation of previous text, do not add to line count. + m_lines_count++; + size_of_last_line = 0; // should countain value only for first line (with hypertext) + + } + } } void NotificationManager::PopNotification::init() @@ -394,8 +470,29 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty() ? "" : " ")).c_str()).x, starting_y + (m_endlines.size() - 1) * shift_y, m_hypertext); } - // text2 (text after hypertext) is not rendered for regular notifications - // its rendering is in HintNotification::render_text + // text2 + if (!m_text2.empty() && (m_multiline|| m_lines_count <= 2)) { + starting_y += (m_endlines.size() - 1) * shift_y; + last_end = 0; + for (size_t i = 0; i < (m_multiline ? m_endlines2.size() : 2); i++) { + if (i == 0) //first line X is shifted by hypertext + ImGui::SetCursorPosX(x_offset + ImGui::CalcTextSize((line + m_hypertext + (line.empty() ? " " : " ")).c_str()).x); + else + ImGui::SetCursorPosX(x_offset); + + ImGui::SetCursorPosY(starting_y + i * shift_y); + line.clear(); + if (m_endlines2.size() > i && m_text2.size() >= m_endlines2[i]) { + + // regular line + line = m_text2.substr(last_end, m_endlines2[i] - last_end); + last_end = m_endlines2[i]; + if (m_text2.size() > m_endlines2[i]) + last_end += (m_text2[m_endlines2[i]] == '\n' || m_text2[m_endlines2[i]] == ' ' ? 1 : 0); + imgui.text(line.c_str()); + } + } + } } void NotificationManager::PopNotification::render_hypertext(ImGuiWrapper& imgui, const float text_x, const float text_y, const std::string text, bool more) @@ -1541,10 +1638,11 @@ void NotificationManager::push_notification(NotificationType type, const std::string& text, const std::string& hypertext, std::function callback, + const std::string& text_after, int timestamp) { int duration = get_standard_duration(level); - push_notification_data({ type, level, duration, text, hypertext, callback }, timestamp); + push_notification_data({ type, level, duration, text, hypertext, callback, text_after }, timestamp); } void NotificationManager::push_delayed_notification(const NotificationType type, std::function condition_callback, int64_t initial_delay, int64_t delay_interval) diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 72889c8549..c6a24d997d 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -154,7 +154,7 @@ public: // Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotificationLevel. // ErrorNotificationLevel are never faded out. void push_notification(NotificationType type, NotificationLevel level, const std::string& text, const std::string& hypertext = "", - std::function callback = std::function(), int timestamp = 0); + std::function callback = std::function(), const std::string& text_after = "", int timestamp = 0); // Pushes basic_notification with delay. See push_delayed_notification_data. void push_delayed_notification(const NotificationType type, std::function condition_callback, int64_t initial_delay, int64_t delay_interval); // Removes all notifications of type from m_waiting_notifications diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index df593f1300..3a5a49fd9e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2217,7 +2217,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) bool is_collapsed = wxGetApp().app_config->get("collapsed_sidebar") == "1"; sidebar->collapse(is_collapsed); } -} + } Plater::priv::~priv() { From bab44b383398598423920a2f1995ef2211903734 Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Fri, 25 Mar 2022 12:17:36 +0100 Subject: [PATCH 44/46] Initial Snapmaker bundle --- resources/profiles/Snapmaker.idx | 2 + resources/profiles/Snapmaker.ini | 473 ++++++++++++++++++ resources/profiles/Snapmaker/A250_bed.stl | Bin 0 -> 684 bytes resources/profiles/Snapmaker/A250_texture.svg | 279 +++++++++++ .../profiles/Snapmaker/A250_thumbnail.png | Bin 0 -> 29408 bytes resources/profiles/Snapmaker/A350_bed.stl | Bin 0 -> 12084 bytes resources/profiles/Snapmaker/A350_texture.svg | 383 ++++++++++++++ .../profiles/Snapmaker/A350_thumbnail.png | Bin 0 -> 28425 bytes 8 files changed, 1137 insertions(+) create mode 100644 resources/profiles/Snapmaker.idx create mode 100644 resources/profiles/Snapmaker.ini create mode 100644 resources/profiles/Snapmaker/A250_bed.stl create mode 100644 resources/profiles/Snapmaker/A250_texture.svg create mode 100644 resources/profiles/Snapmaker/A250_thumbnail.png create mode 100644 resources/profiles/Snapmaker/A350_bed.stl create mode 100644 resources/profiles/Snapmaker/A350_texture.svg create mode 100644 resources/profiles/Snapmaker/A350_thumbnail.png diff --git a/resources/profiles/Snapmaker.idx b/resources/profiles/Snapmaker.idx new file mode 100644 index 0000000000..03488b17c5 --- /dev/null +++ b/resources/profiles/Snapmaker.idx @@ -0,0 +1,2 @@ +min_slic3r_version = 2.4.1 +1.0.0 Initial Snapmaker bundle diff --git a/resources/profiles/Snapmaker.ini b/resources/profiles/Snapmaker.ini new file mode 100644 index 0000000000..aab7f7b0c7 --- /dev/null +++ b/resources/profiles/Snapmaker.ini @@ -0,0 +1,473 @@ +# Jubilee profiles + +# Based on the profiles from: https://github.com/nivekmai/snapmaker-prusa by nivekmai, WilliamBosacker, mrworf + +[vendor] +# Vendor name will be shown by the Config Wizard. +name = Snapmaker +# Configuration version of this file. Config file will only be installed, if the config_version differs. +# This means, the server may force the Slic3r configuration to be downgraded. +config_version = 1.0.0 +# Where to get the updates from? +config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Snapmaker/ +# The printer models will be shown by the Configuration Wizard in this order, + +[printer_model:A250] +name = Snapmaker A250 +variants = 0.4 +technology = FFF +bed_model = A250_bed.stl +bed_texture = A250_texture.svg +default_materials = Generic PLA @Snapmaker; Generic PETG @Snapmaker + +[printer_model:A350] +name = Snapmaker A350 +variants = 0.4 +technology = FFF +bed_model = A350_bed.stl +bed_texture = A350_texture.svg +default_materials = Generic PLA @Snapmaker; Generic PETG @Snapmaker + +[print:*common*] +avoid_crossing_perimeters = 1 +avoid_crossing_perimeters_max_detour = 0 +bottom_fill_pattern = monotonic +bottom_solid_layers = 4 +bottom_solid_min_thickness = 0 +bridge_acceleration = 0 +bridge_angle = 0 +bridge_flow_ratio = 1 +bridge_speed = 60 +brim_separation = 0 +brim_type = outer_only +brim_width = 0 +clip_multipart_objects = 1 +complete_objects = 0 +default_acceleration = 0 +dont_support_bridges = 1 +draft_shield = disabled +elefant_foot_compensation = 0.1 +ensure_vertical_shell_thickness = 1 +external_perimeter_extrusion_width = 0.45 +external_perimeter_speed = 50% +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 25 +extruder_clearance_radius = 75 +extrusion_width = 0.45 +fill_angle = 45 +fill_density = 20% +fill_pattern = gyroid +first_layer_acceleration = 0 +first_layer_acceleration_over_raft = 0 +first_layer_extrusion_width = 0.45 +first_layer_height = 0.2 +first_layer_speed = 15 +first_layer_speed_over_raft = 30 +fuzzy_skin = none +fuzzy_skin_point_dist = 0.8 +fuzzy_skin_thickness = 0.3 +gap_fill_enabled = 1 +gap_fill_speed = 20 +gcode_comments = 0 +gcode_label_objects = 0 +gcode_resolution = 0.0125 +gcode_substitutions = +infill_acceleration = 0 +infill_anchor = 600% +infill_anchor_max = 50 +infill_every_layers = 1 +infill_extruder = 1 +infill_extrusion_width = 0.45 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 25% +infill_speed = 100 +inherits = +interface_shells = 0 +ironing = 0 +ironing_flowrate = 15% +ironing_spacing = 0.25 +ironing_speed = 15 +ironing_type = top +layer_height = 0.2 +max_print_speed = 100 +max_volumetric_speed = 0 +min_skirt_length = 4 +mmu_segmented_region_max_width = 0 +notes = +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}_{print_time}.gcode +overhangs = 0 +perimeter_acceleration = 0 +perimeter_extruder = 1 +perimeter_extrusion_width = 0.45 +perimeter_speed = 60 +perimeters = 2 +post_process = +print_settings_id = +raft_contact_distance = 0.1 +raft_expansion = 1.5 +raft_first_layer_density = 90% +raft_first_layer_expansion = 3 +raft_layers = 0 +resolution = 0 +seam_position = nearest +single_extruder_multi_material_priming = 1 +skirt_distance = 5 +skirt_height = 1 +skirts = 3 +slice_closing_radius = 0.049 +slicing_mode = regular +small_perimeter_speed = 25% +solid_infill_below_area = 0 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +solid_infill_extrusion_width = 0.45 +solid_infill_speed = 80% +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_angle = 0 +support_material_auto = 1 +support_material_bottom_contact_distance = 0 +support_material_bottom_interface_layers = -1 +support_material_buildplate_only = 0 +support_material_closing_radius = 2 +support_material_contact_distance = 0.15 +support_material_enforce_layers = 0 +support_material_extruder = 0 +support_material_extrusion_width = 0.38 +support_material_interface_contact_loops = 0 +support_material_interface_extruder = 0 +support_material_interface_layers = 2 +support_material_interface_pattern = rectilinear +support_material_interface_spacing = 0.2 +support_material_interface_speed = 100% +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_speed = 60 +support_material_style = grid +support_material_synchronize_layers = 0 +support_material_threshold = 45 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thick_bridges = 1 +thin_walls = 0 +threads = 8 +top_fill_pattern = monotonic +top_infill_extrusion_width = 0.4 +top_solid_infill_speed = 60% +top_solid_layers = 4 +top_solid_min_thickness = 0 +travel_speed = 150 +travel_speed_z = 0 +wipe_tower = 0 +wipe_tower_bridging = 10 +wipe_tower_brim_width = 2 +wipe_tower_no_sparse_layers = 0 +wipe_tower_rotation_angle = 0 +wipe_tower_width = 60 +wipe_tower_x = 170 +wipe_tower_y = 140 +xy_size_compensation = 0 +compatible_printers_condition = nozzle_diameter[0]==0.4 + +[print:0.10mm HIGHDETAIL @SnapmakerA350] +inherits = *common* +layer_height = 0.1 +bottom_solid_layers = 7 +top_solid_layers = 8 +top_solid_min_thickness = 0.8 +bottom_solid_min_thickness = 0.8 +bridge_speed = 40 +infill_speed = 50 +perimeter_speed = 40 +support_material_speed = 40 +max_print_speed = 50 +skirt_distance = 10 +first_layer_speed = 25% +compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350" + +[print:0.16mm OPTIMAL @SnapmakerA350] +inherits = *common* +layer_height = 0.16 +top_solid_layers = 6 +bottom_solid_layers = 6 +first_layer_speed = 25% +max_print_speed = 60 +compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350" + +[print:0.20mm NORMAL @SnapmakerA350] +inherits = *common* +compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350" + +[print:0.20mm FAST @SnapmakerA350] +inherits = 0.20mm NORMAL @SnapmakerA350 +bridge_speed = 80 +gap_fill_speed = 30 +infill_speed = 120 +ironing_speed = 20 +perimeter_speed = 80 +support_material_speed = 80 +compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A350" + +[print:0.08mm DETAIL @SnapmakerA250] +inherits = 0.20mm NORMAL @SnapmakerA250 +layer_height = 0.08 +infill_speed = 40 +external_perimeter_speed = 10 +perimeter_speed = 15 +top_solid_infill_speed = 20 +travel_speed = 70 +first_layer_extrusion_width = 0.45 +perimeter_extrusion_width = 0.4 +external_perimeter_extrusion_width = 0.4 +infill_extrusion_width = 0.4 +solid_infill_extrusion_width = 0.4 +top_infill_extrusion_width = 0.4 + +[print:0.20mm NORMAL @SnapmakerA250] +inherits = *common* +compatible_printers_condition = nozzle_diameter[0]==0.4 and printer_model=="A250" +first_layer_speed = 15 +gap_fill_speed = 15 +infill_speed = 50 +perimeter_speed = 25 +small_perimeter_speed = 20 +external_perimeter_speed = 15 +support_material_speed = 25 +top_solid_infill_speed = 25 +travel_speed = 80 +max_print_speed = 80 +skirt_distance = 3 +min_skirt_length = 25 + +[print:0.24mm FAST @SnapmakerA250] +inherits = 0.20mm NORMAL @SnapmakerA250 +layer_height = 0.24 +infill_speed = 60 +external_perimeter_speed = 20 +top_solid_infill_speed = 30 + +[filament:*common*] +bed_temperature = 60 +bridge_fan_speed = 100 +compatible_printers = +compatible_printers_condition = +compatible_prints = +compatible_prints_condition = +cooling = 1 +disable_fan_first_layers = 3 +end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n" +extrusion_multiplier = 1 +fan_always_on = 1 +fan_below_layer_time = 60 +filament_colour = #29B2B2 +filament_cooling_final_speed = 3.4 +filament_cooling_initial_speed = 2.2 +filament_cooling_moves = 4 +filament_cost = 0 +filament_density = 0 +filament_deretract_speed = nil +filament_diameter = 1.75 +filament_load_time = 0 +filament_loading_speed = 28 +filament_loading_speed_start = 3 +filament_max_volumetric_speed = 0 +filament_minimal_purge_on_wipe_tower = 15 +filament_notes = "" +filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" +filament_retract_before_travel = nil +filament_retract_before_wipe = nil +filament_retract_layer_change = nil +filament_retract_length = nil +filament_retract_lift = nil +filament_retract_lift_above = nil +filament_retract_lift_below = nil +filament_retract_restart_extra = nil +filament_retract_speed = nil +filament_settings_id = "" +filament_soluble = 0 +filament_spool_weight = 0 +filament_toolchange_delay = 0 +filament_type = PLA +filament_unload_time = 0 +filament_unloading_speed = 90 +filament_unloading_speed_start = 100 +filament_wipe = nil +first_layer_bed_temperature = 60 +first_layer_temperature = 210 +full_fan_speed_layer = 0 +inherits = +max_fan_speed = 100 +min_fan_speed = 35 +min_print_speed = 10 +slowdown_below_layer_time = 5 +start_filament_gcode = "; Filament gcode\n" +temperature = 210 + +[filament:*PLA*] +inherits = *common* + +[filament:*PETG*] +inherits = *common* +first_layer_bed_temperature = 80 +bed_temperature = 75 +first_layer_temperature = 245 +temperature = 245 +filament_density = 1.27 +disable_fan_first_layers = 3 +min_fan_speed = 20 +max_fan_speed = 50 +fan_below_layer_time = 20 +min_print_speed = 20 +filament_max_volumetric_speed = 8 +filament_type = PETG + +[filament:Generic PLA @Snapmaker] +inherits = *PLA* +filament_vendor = Generic + +[filament:Generic PETG @Snapmaker] +inherits = *PETG* +filament_vendor = Generic + +[filament:Snapmaker PLA @Snapmaker] +inherits = *PLA* +filament_vendor = Snapmaker + +[filament:Overture PLA @Snapmaker] +inherits = *PLA* +filament_vendor = Overture +bed_temperature = 50 +first_layer_temperature = 205 +temperature = 205 +filament_density = 1.24 +disable_fan_first_layers = 1 +min_fan_speed = 100 +max_fan_speed = 100 +full_fan_speed_layer = 3 +fan_below_layer_time = 100 +min_print_speed = 15 +filament_max_volumetric_speed = 0 + +[filament:MatterHackers Build Translucent @Snapmaker] +inherits = *PETG* +filament_vendor = MatterHackers + +[filament:MatterHackers Build White @Snapmaker] +inherits = MatterHackers Build Translucent @Snapmaker +bed_temperature = 65 +first_layer_bed_temperature = 70 +first_layer_temperature = 260 +temperature = 255 +filament_density = 1.28 +disable_fan_first_layers = 3 +full_fan_speed_layer = 5 +min_fan_speed = 40 +max_fan_speed = 100 +fan_below_layer_time = 60 +min_print_speed = 10 + +[filament:Overture TPU @Snapmaker] +inherits = *common* +filament_vendor = Overture +filament_type = FLEX +first_layer_temperature = 220 +temperature = 220 +filament_density = 1.22 +disable_fan_first_layers = 1 +min_fan_speed = 100 +max_fan_speed = 100 +fan_below_layer_time = 100 +min_print_speed = 15 +filament_retract_speed = 40 +filament_deretract_speed = 25 +filament_retract_length = 1.8 +filament_max_volumetric_speed = 3 + +# Common printer preset +[printer:*common*] +bed_shape = 0x0,320x0,320x350,0x350 +color_change_gcode = M600 +cooling_tube_length = 5 +cooling_tube_retraction = 91.5 +default_filament_profile = "" +default_print_profile = +end_gcode = ;End GCode begin\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off\nG90 ;absolute positioning\nG92 E0\nG1 E-2 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG28 X0 Y0 ; home\nM84 ;steppers off\nM107 ;fan off\nM82 ;absolute extrusion mode\n;End GCode end +extra_loading_move = -2 +extruder_colour = "" +extruder_offset = 0x0 +gcode_flavor = marlin +high_current_on_filament_swap = 0 +machine_limits_usage = time_estimate_only +machine_max_acceleration_e = 10000 +machine_max_acceleration_extruding = 1000 +machine_max_acceleration_retracting = 1000 +machine_max_acceleration_travel = 1500 +machine_max_acceleration_x = 3000 +machine_max_acceleration_y = 3000 +machine_max_acceleration_z = 100 +machine_max_feedrate_e = 25 +machine_max_feedrate_x = 150 +machine_max_feedrate_y = 150 +machine_max_feedrate_z = 50 +machine_max_jerk_e = 2.5 +machine_max_jerk_x = 10 +machine_max_jerk_y = 10 +machine_max_jerk_z = 0.2 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +max_layer_height = 0.3 +max_print_height = 330 +min_layer_height = 0.08 +nozzle_diameter = 0.4 +parking_pos_retraction = 92 +pause_print_gcode = +printer_technology = FFF +remaining_times = 0 +retract_before_travel = 2 +retract_before_wipe = 0% +retract_layer_change = 1 +retract_length = 3 +retract_length_toolchange = 10 +retract_lift = 0 +retract_lift_above = 0 +retract_lift_below = 328 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 60 +deretract_speed = 40 +silent_mode = 0 +single_extruder_multi_material = 0 +start_gcode = M82 ;absolute extrusion mode\n;Start GCode begin\nM140 S[first_layer_bed_temperature] ;Start warming Bed\nM104 S[first_layer_temperature] ;Start warming Nozzle\nG28 ; home all axes\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000\nG1 Z0 F1800\nM190 S[first_layer_bed_temperature] ;Wait For Bed Temperature\nM109 S[first_layer_temperature] ;Wait for Hotend Temperature\nG92 E0\nG1 E20 F200 ; Prime extrude for wipe\nG92 E0 +thumbnails = 16x16,220x124 +use_firmware_retraction = 0 +use_relative_e_distances = 0 +use_volumetric_e = 0 +variable_layer_height = 1 +wipe = 0 +z_offset = 0 + +[printer:Snapmaker A350] +inherits = *common* +printer_model = A350 +printer_variant = 0.4 +default_filament_profile = Generic PLA @Snapmaker +default_print_profile = 0.20mm NORMAL @SnapmakerA350 + +[printer:Snapmaker A250] +inherits = *common* +printer_model = A250 +printer_variant = 0.4 +bed_shape = 0x0,230x0,230x250,0x250 +thumbnails = +variable_layer_height = 0 +retract_lift_below = 0 +max_print_height = 235 +start_gcode = M82 ;absolute extrusion mode\n;Start GCode begin\nM140 S[first_layer_bed_temperature] ;Start Warming Bed\nM104 S160 ;Preheat Nozzle\nG28 ; home all axes\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000\nG1 Z0 F1800\nG1 Z5 F5000 ; lift nozzle\nM190 S[first_layer_bed_temperature] ;Wait For Bed Temperature\nM109 S[first_layer_temperature] ;Wait for Hotend Temperature\nG92 E0\nG1 E10 F200\nG1 E-2 F300\nG92 E0\n;Start GCode end\nG1 F3600 E-2 +end_gcode = M140 S0\n;End GCode begin\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG90 ;absolute positioning\nG92 E0\nG1 E-2 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z330 E-1 F80 ;move Z up a bit and retract filament even more\nG1 X0 F3000 ;move X to min endstops, so the head is out of the way\nG1 Y250 F3000 ;so the head is out of the way and Plate is moved forward\nM84 ;steppers off\n;End GCode end\nM82 ;absolute extrusion mode\nM104 S0\nM107\n;End of Gcode +default_filament_profile = Generic PLA @Snapmaker +default_print_profile = 0.20mm NORMAL @SnapmakerA250 \ No newline at end of file diff --git a/resources/profiles/Snapmaker/A250_bed.stl b/resources/profiles/Snapmaker/A250_bed.stl new file mode 100644 index 0000000000000000000000000000000000000000..c783af9ac110d2dd67eb5efdd64dd5e7ffa6fe65 GIT binary patch literal 684 zcmbV}!3u&v5Qcq#f?i~=T}8o2$b!{Fz0JN>6e!+;Uc=52NSDC;clmX2?b06BVVrN~ z|7Wu#-)8AC(JC)?Do*#2KB>(?XHlX4IKd*oF{S_uYg9C + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/profiles/Snapmaker/A250_thumbnail.png b/resources/profiles/Snapmaker/A250_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..ffc7619e683719332c83a7c448ba314ce673ce0b GIT binary patch literal 29408 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 Y3piM<5>TqTmjD0&07*qoM6N<$f`uy%0ssI2 literal 0 HcmV?d00001 diff --git a/resources/profiles/Snapmaker/A350_bed.stl b/resources/profiles/Snapmaker/A350_bed.stl new file mode 100644 index 0000000000000000000000000000000000000000..ee418a68d44188ccdaed015e478cb6962d534893 GIT binary patch literal 12084 zcmbW7QK(%<6^75t?VC!WLTe<2KG+xUgNoqOJ)Wes)-*2v#tZthI zN@*jdDq4|Ph?+t{u@DW)J-1vCrP}ICn+L%*U^NIuN>iFb8Rwtb|D12mo^w5zhnvM- z>zlRKthHzFnSFL&zwhI_Z~XN2dsp}EziD;Hjh~$Cy><0td-m?0>|gyq{*C@K8jTJ< zf8R9zH+uHxD{E)BpO~Ee(vF?Kz1VG7{`JL|HV&OQF*$Q-lCFm!>(Qti>n}B@HlB!9 zH&nDnstJ!P4T;aa`0(V|@3Zd^jvYIaqPqRn%{6K)D=Lmu6V$W_(IqPR=}bsN!VwOL z5eZs(Ml!+KwPw-mX5!Xdk8bt!$~p;Cbb2X{7l_cLeiomfM9If7R2IDFUSz&88Xer{WutJkmGHKxY0GN=KR?!p*O3 zrl@`u>p_iWMa7Y7f|?eQGr#HFHmy~ozs9~IVOdrupL+{&;9j zYfK@W`G}e~cigb)x0Tc4KkmyLz zN;5Ls*T$$)J^mSY!qiw+>>Mcs64bPaocS%ikK-|O5|(8p+NUCQCsM=AO=}hw6Rw)9 zNT?s;HV=IsAHPP2|=ITQ~2Q`+h+{d!239RkaTHr zjs&f=7rp!|_JPx=DK(ZAJ4dR{ucp+rh@AP37xJmv7h>ilEX&IGigGITNZn2iGdDdT zMkHJhS&<5d{@xYa3DTMtPx>ZR@x!G_mF#+ z_lK=S(2Bd)l1I9ucot52A<>bb)xk^e+xdyhKC&s_m5)vupW~CBC-M_b`A}n8nOmk0 z+3UPLe=C@`GLdIjwqAFsk*wHd#gR%Lspiy>@GJ~{P~+L%+6S$;meBX&s7UBcPF*sL zieu4A=YF%^^0G!A$Rc%d1{R+McUVMR7cV6)`+kyD@Vwh=T31RBqT3K z(8}{R@R80e{hV-ZWJTYl9_fzaSia9ikPd+>1FbA8^P1q3(^eYStFs7S&$G)4(u(Wg zas=N1NQbaL?mOg1>lJ6zvLfM()C4sxBIm&_v6V7!bxD=E>XFXE{mx)w>k6{AI&b$| zvHMtb2w&~rWY*&IoK}_<$zp<<7LoJd9Yw;jte8{j#I#;8Lhqd6h%>;KC~{sqLmzYtpA&$HE#U_DgF z+0$7XKX)ZFr@D8&_Q?m|ue@Rm^Wd}A?>@5PNFnh3%2tYmR=%En+=dm-8WEOdr4w&I zB}yKtcO4Z8$;%P6(%HM$vDybUI@9-hMc*|+4GDcu@Y%p(f>!!Y;XAD+sNwey`VQe! z{rS~uJTD<(S+h&JCa7rPMTGjwR;s_B^X0Bh?+nzafep{`e*IHkrkiR|O%{@h0=UL-8b z%JY_ekf5eTWFKGaPiyavZ)7Aa%gU9_K1fj0BC-#xSL-A!%gQ~LeUPB0MPwgpb$2^= z*rzVLcGLUwy5@_zorL7sF9$NAzulB$(aP6z9x|0Z328`JE`+S}+iM@YG#q!H$X`X} zg&N7u+%kR0z8hPkS!~T)Av)QUkcNciLL_T3)Xe9>bDxxTN5WCL1{_H%!!UCZ%t^9O zkgBuS>Q{PtPxNnN^q%Nn*@VE~+-bk$6%Def_TlT9Xyu_< zbRL$K$Ht#7{w}SFX`V!CPOM?JmJ1OlcGg!WJfpJWNNILc7qT9-a{WD$S8CbMqGIfe zh+IW`H{s539=h(#6VW;Ld4eOAJUZsVNG!`=nX6>2`Em`Mxuddg60_O$ShR8;CWgH$ Sjr}nv6UspUW>GQrA@N@UXjel3 literal 0 HcmV?d00001 diff --git a/resources/profiles/Snapmaker/A350_texture.svg b/resources/profiles/Snapmaker/A350_texture.svg new file mode 100644 index 0000000000..8e8c47b655 --- /dev/null +++ b/resources/profiles/Snapmaker/A350_texture.svg @@ -0,0 +1,383 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/profiles/Snapmaker/A350_thumbnail.png b/resources/profiles/Snapmaker/A350_thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..598039a83ee61fa5c4b4a5757cc32d8411fa6a3e GIT binary patch literal 28425 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 literal 0 HcmV?d00001 From ea3e3f95b1578acc564eb7fdd5c34935fb5f0e1a Mon Sep 17 00:00:00 2001 From: rtyr <36745189+rtyr@users.noreply.github.com> Date: Fri, 25 Mar 2022 12:19:00 +0100 Subject: [PATCH 45/46] Fixed comment. --- resources/profiles/Snapmaker.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/profiles/Snapmaker.ini b/resources/profiles/Snapmaker.ini index aab7f7b0c7..68e32910b1 100644 --- a/resources/profiles/Snapmaker.ini +++ b/resources/profiles/Snapmaker.ini @@ -1,4 +1,4 @@ -# Jubilee profiles +# Snapmaker profiles # Based on the profiles from: https://github.com/nivekmai/snapmaker-prusa by nivekmai, WilliamBosacker, mrworf @@ -470,4 +470,4 @@ max_print_height = 235 start_gcode = M82 ;absolute extrusion mode\n;Start GCode begin\nM140 S[first_layer_bed_temperature] ;Start Warming Bed\nM104 S160 ;Preheat Nozzle\nG28 ; home all axes\nG90 ;absolute positioning\nG1 X-10 Y-10 F3000\nG1 Z0 F1800\nG1 Z5 F5000 ; lift nozzle\nM190 S[first_layer_bed_temperature] ;Wait For Bed Temperature\nM109 S[first_layer_temperature] ;Wait for Hotend Temperature\nG92 E0\nG1 E10 F200\nG1 E-2 F300\nG92 E0\n;Start GCode end\nG1 F3600 E-2 end_gcode = M140 S0\n;End GCode begin\nM104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG90 ;absolute positioning\nG92 E0\nG1 E-2 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG1 Z330 E-1 F80 ;move Z up a bit and retract filament even more\nG1 X0 F3000 ;move X to min endstops, so the head is out of the way\nG1 Y250 F3000 ;so the head is out of the way and Plate is moved forward\nM84 ;steppers off\n;End GCode end\nM82 ;absolute extrusion mode\nM104 S0\nM107\n;End of Gcode default_filament_profile = Generic PLA @Snapmaker -default_print_profile = 0.20mm NORMAL @SnapmakerA250 \ No newline at end of file +default_print_profile = 0.20mm NORMAL @SnapmakerA250 From 888f45c0d3704588ee0a91b8ae1ac0b755224ce3 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 25 Mar 2022 14:03:44 +0100 Subject: [PATCH 46/46] Tech ENABLE_PROCESS_G2_G3_LINES - Fixed update of horizontal slider in gcode preview --- src/slic3r/GUI/GUI_Preview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 902ea91415..9f62fa0b85 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -887,7 +887,7 @@ void Preview::update_moves_slider() m_moves_slider->SetSliderValues(values); m_moves_slider->SetSliderAlternateValues(alternate_values); m_moves_slider->SetMaxValue(int(values.size()) - 1); - m_moves_slider->SetSelectionSpan(values.front() - 1, values.back() - 1); + m_moves_slider->SetSelectionSpan(values.front() - 1 - view.endpoints.first, values.back() - 1 - view.endpoints.first); #else std::vector values(view.endpoints.last - view.endpoints.first + 1); std::vector alternate_values(view.endpoints.last - view.endpoints.first + 1);