Merge branch 'main' into enh-port-edit-gcode-dlg

# Conflicts:
#	src/slic3r/GUI/OG_CustomCtrl.cpp
#	src/slic3r/GUI/OG_CustomCtrl.hpp
This commit is contained in:
Ocraftyone 2024-01-01 10:58:04 -05:00
commit f78d55eac5
No known key found for this signature in database
GPG key ID: 85836ED21AD4D125
265 changed files with 29219 additions and 7128 deletions

View file

@ -42,7 +42,8 @@ using namespace nlohmann;
namespace Slic3r {
static const std::string VERSION_CHECK_URL = "https://api.github.com/repos/softfever/OrcaSlicer/releases/latest";
static const std::string VERSION_CHECK_URL_STABLE = "https://api.github.com/repos/softfever/OrcaSlicer/releases/latest";
static const std::string VERSION_CHECK_URL = "https://api.github.com/repos/softfever/OrcaSlicer/releases";
static const std::string MODELS_STR = "models";
const std::string AppConfig::SECTION_FILAMENTS = "filaments";
@ -240,6 +241,10 @@ void AppConfig::set_defaults()
set_bool("stealth_mode", false);
}
if(get("check_stable_update_only").empty()) {
set_bool("check_stable_update_only", false);
}
// Orca
if(get("show_splash_screen").empty()) {
set_bool("show_splash_screen", true);
@ -1253,10 +1258,10 @@ std::string AppConfig::config_path()
return path;
}
std::string AppConfig::version_check_url() const
std::string AppConfig::version_check_url(bool stable_only/* = false*/) const
{
auto from_settings = get("version_check_url");
return from_settings.empty() ? VERSION_CHECK_URL : from_settings;
return from_settings.empty() ? stable_only ? VERSION_CHECK_URL_STABLE : VERSION_CHECK_URL : from_settings;
}
bool AppConfig::exists()

View file

@ -247,7 +247,7 @@ public:
// Get the Slic3r version check url.
// This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file.
std::string version_check_url() const;
std::string version_check_url(bool stable_only = false) const;
// Returns the original Slic3r version found in the ini file before it was overwritten
// by the current version

View file

@ -5,7 +5,6 @@
#include <stack>
#include <functional>
#include <unordered_set>
#include <sstream>
#include <queue>
#include <functional>
@ -19,6 +18,7 @@
#include "Geometry/VoronoiVisualUtils.hpp"
#include "Geometry/VoronoiUtilsCgal.hpp"
#include "../EdgeGrid.hpp"
#include "ankerl/unordered_dense.h"
#define SKELETAL_TRAPEZOIDATION_BEAD_SEARCH_MAX 1000 //A limit to how long it'll keep searching for adjacent beads. Increasing will re-use beadings more often (saving performance), but search longer for beading (costing performance).
@ -522,14 +522,14 @@ static bool has_missing_twin_edge(const SkeletalTrapezoidationGraph &graph)
return false;
}
inline static std::unordered_map<Point, Point, PointHash> try_to_fix_degenerated_voronoi_diagram_by_rotation(
inline static ankerl::unordered_dense::map<Point, Point, PointHash> try_to_fix_degenerated_voronoi_diagram_by_rotation(
Geometry::VoronoiDiagram &voronoi_diagram,
const Polygons &polys,
Polygons &polys_rotated,
std::vector<SkeletalTrapezoidation::Segment> &segments,
const double fix_angle)
{
std::unordered_map<Point, Point, PointHash> vertex_mapping;
ankerl::unordered_dense::map<Point, Point, PointHash> vertex_mapping;
for (Polygon &poly : polys_rotated)
poly.rotate(fix_angle);
@ -562,7 +562,7 @@ inline static std::unordered_map<Point, Point, PointHash> try_to_fix_degenerated
inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalTrapezoidationGraph &graph,
const double fix_angle,
const std::unordered_map<Point, Point, PointHash> &vertex_mapping)
const ankerl::unordered_dense::map<Point, Point, PointHash> &vertex_mapping)
{
for (STHalfEdgeNode &node : graph.nodes) {
// If a mapping exists between a rotated point and an original point, use this mapping. Otherwise, rotate a point in the opposite direction.
@ -623,7 +623,7 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
const bool is_voronoi_diagram_planar = Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram);
const double fix_angle = PI / 6;
std::unordered_map<Point, Point, PointHash> vertex_mapping;
ankerl::unordered_dense::map<Point, Point, PointHash> vertex_mapping;
// polys_copy is referenced through items stored in the std::vector segments.
Polygons polys_copy = polys;
if (has_missing_voronoi_vertex || !is_voronoi_diagram_planar) {
@ -751,7 +751,7 @@ process_voronoi_diagram:
void SkeletalTrapezoidation::separatePointyQuadEndNodes()
{
std::unordered_set<node_t*> visited_nodes;
ankerl::unordered_dense::set<node_t*> visited_nodes;
for (edge_t& edge : graph.edges)
{
if (edge.prev)
@ -2221,7 +2221,7 @@ void SkeletalTrapezoidation::addToolpathSegment(const ExtrusionJunction& from, c
void SkeletalTrapezoidation::connectJunctions(ptr_vector_t<LineJunctions>& edge_junctions)
{
std::unordered_set<edge_t*> unprocessed_quad_starts(graph.edges.size() * 5 / 2);
ankerl::unordered_dense::set<edge_t*> unprocessed_quad_starts(graph.edges.size() * 5 / 2);
for (edge_t& edge : graph.edges)
{
if (!edge.prev)
@ -2230,7 +2230,7 @@ void SkeletalTrapezoidation::connectJunctions(ptr_vector_t<LineJunctions>& edge_
}
}
std::unordered_set<edge_t*> passed_odd_edges;
ankerl::unordered_dense::set<edge_t*> passed_odd_edges;
while (!unprocessed_quad_starts.empty())
{

View file

@ -7,7 +7,7 @@
#include <boost/polygon/voronoi.hpp>
#include <memory> // smart pointers
#include <unordered_map>
#include <ankerl/unordered_dense.h>
#include <utility> // pair
#include "utils/HalfEdgeGraph.hpp"
@ -163,8 +163,8 @@ protected:
* mapping each voronoi VD edge to the corresponding halfedge HE edge
* In case the result segment is discretized, we map the VD edge to the *last* HE edge
*/
std::unordered_map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge;
std::unordered_map<vd_t::vertex_type*, node_t*> vd_node_to_he_node;
ankerl::unordered_dense::map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge;
ankerl::unordered_dense::map<vd_t::vertex_type*, node_t*> vd_node_to_he_node;
node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet.
/*!

View file

@ -2,7 +2,8 @@
//CuraEngine is released under the terms of the AGPLv3 or higher.
#include "SkeletalTrapezoidationGraph.hpp"
#include <unordered_map>
#include <ankerl/unordered_dense.h>
#include <boost/log/trivial.hpp>
@ -180,8 +181,8 @@ bool STHalfEdgeNode::isLocalMaximum(bool strict) const
void SkeletalTrapezoidationGraph::collapseSmallEdges(coord_t snap_dist)
{
std::unordered_map<edge_t*, std::list<edge_t>::iterator> edge_locator;
std::unordered_map<node_t*, std::list<node_t>::iterator> node_locator;
ankerl::unordered_dense::map<edge_t*, std::list<edge_t>::iterator> edge_locator;
ankerl::unordered_dense::map<node_t*, std::list<node_t>::iterator> node_locator;
for (auto edge_it = edges.begin(); edge_it != edges.end(); ++edge_it)
{

View file

@ -782,10 +782,9 @@ bool WallToolPaths::removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpa
*
* \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one.
*/
std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> WallToolPaths::getRegionOrder(const std::vector<ExtrusionLine *> &input, const bool outer_to_inner)
WallToolPaths::ExtrusionLineSet WallToolPaths::getRegionOrder(const std::vector<ExtrusionLine *> &input, const bool outer_to_inner)
{
std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> order_requirements;
ExtrusionLineSet order_requirements;
// We build a grid where we map toolpath vertex locations to toolpaths,
// so that we can easily find which two toolpaths are next to each other,
// which is the requirement for there to be an order constraint.

View file

@ -5,7 +5,7 @@
#define CURAENGINE_WALLTOOLPATHS_H
#include <memory>
#include <unordered_set>
#include <ankerl/unordered_dense.h>
#include "BeadingStrategy/BeadingStrategyFactory.hpp"
#include "utils/ExtrusionLine.hpp"
@ -86,6 +86,8 @@ public:
*/
static bool removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpaths);
using ExtrusionLineSet = ankerl::unordered_dense::set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>>;
/*!
* Get the order constraints of the insets when printing walls per region / hole.
* Each returned pair consists of adjacent wall lines where the left has an inset_idx one lower than the right.
@ -94,7 +96,7 @@ public:
*
* \param outer_to_inner Whether the wall polygons with a lower inset_idx should go before those with a higher one.
*/
static std::unordered_set<std::pair<const ExtrusionLine *, const ExtrusionLine *>, boost::hash<std::pair<const ExtrusionLine *, const ExtrusionLine *>>> getRegionOrder(const std::vector<ExtrusionLine *> &input, bool outer_to_inner);
static ExtrusionLineSet getRegionOrder(const std::vector<ExtrusionLine *> &input, bool outer_to_inner);
protected:
/*!

View file

@ -119,8 +119,7 @@ void ExtrusionLine::simplify(const int64_t smallest_line_segment_squared, const
//h^2 = (L / b)^2 [square it]
//h^2 = L^2 / b^2 [factor the divisor]
const auto height_2 = int64_t(double(area_removed_so_far) * double(area_removed_so_far) / double(base_length_2));
coord_t weighted_average_width;
const int64_t extrusion_area_error = calculateExtrusionAreaDeviationError(previous, current, next, weighted_average_width);
const int64_t extrusion_area_error = calculateExtrusionAreaDeviationError(previous, current, next);
if ((height_2 <= scaled<coord_t>(0.001) //Almost exactly colinear (barring rounding errors).
&& Line::distance_to_infinite(current.p, previous.p, next.p) <= scaled<double>(0.001)) // Make sure that height_2 is not small because of cancellation of positive and negative areas
// We shouldn't remove middle junctions of colinear segments if the area changed for the C-P segment is exceeding the maximum allowed
@ -200,8 +199,7 @@ void ExtrusionLine::simplify(const int64_t smallest_line_segment_squared, const
junctions = new_junctions;
}
int64_t ExtrusionLine::calculateExtrusionAreaDeviationError(ExtrusionJunction A, ExtrusionJunction B, ExtrusionJunction C, coord_t& weighted_average_width)
{
int64_t ExtrusionLine::calculateExtrusionAreaDeviationError(ExtrusionJunction A, ExtrusionJunction B, ExtrusionJunction C) {
/*
* A B C A C
* --------------- **************
@ -219,27 +217,19 @@ int64_t ExtrusionLine::calculateExtrusionAreaDeviationError(ExtrusionJunction A,
* weighted-average width for the entire extrusion line.
*
* */
const int64_t ab_length = (B - A).cast<int64_t>().norm();
const int64_t bc_length = (C - B).cast<int64_t>().norm();
const coord_t width_diff = std::max(std::abs(B.w - A.w), std::abs(C.w - B.w));
if (width_diff > 1)
{
const int64_t ab_length = (B.p - A.p).cast<int64_t>().norm();
const int64_t bc_length = (C.p - B.p).cast<int64_t>().norm();
if (const coord_t width_diff = std::max(std::abs(B.w - A.w), std::abs(C.w - B.w)); width_diff > 1) {
// Adjust the width only if there is a difference, or else the rounding errors may produce the wrong
// weighted average value.
const int64_t ab_weight = (A.w + B.w) / 2;
const int64_t bc_weight = (B.w + C.w) / 2;
assert(((ab_length * ab_weight + bc_length * bc_weight) / (C - A).cast<int64_t>().norm()) <= std::numeric_limits<coord_t>::max());
weighted_average_width = (ab_length * ab_weight + bc_length * bc_weight) / (C - A).cast<int64_t>().norm();
assert((int64_t(std::abs(ab_weight - weighted_average_width)) * ab_length + int64_t(std::abs(bc_weight - weighted_average_width)) * bc_length) <= double(std::numeric_limits<int64_t>::max()));
return std::abs(ab_weight - weighted_average_width) * ab_length + std::abs(bc_weight - weighted_average_width) * bc_length;
}
else
{
const int64_t ab_weight = (A.w + B.w) / 2;
const int64_t bc_weight = (B.w + C.w) / 2;
const int64_t weighted_average_width = (ab_length * ab_weight + bc_length * bc_weight) / (ab_length + bc_length);
const int64_t ac_length = (C.p - A.p).cast<int64_t>().norm();
return std::abs((ab_weight * ab_length + bc_weight * bc_length) - (weighted_average_width * ac_length));
} else {
// If the width difference is very small, then select the width of the segment that is longer
weighted_average_width = ab_length > bc_length ? A.w : B.w;
assert((int64_t(width_diff) * int64_t(bc_length)) <= std::numeric_limits<coord_t>::max());
assert((int64_t(width_diff) * int64_t(ab_length)) <= std::numeric_limits<coord_t>::max());
return ab_length > bc_length ? width_diff * bc_length : width_diff * ab_length;
return ab_length > bc_length ? int64_t(width_diff) * bc_length : int64_t(width_diff) * ab_length;
}
}

View file

@ -186,9 +186,8 @@ struct ExtrusionLine
* \param A Start point of the 3-point-straight line
* \param B Intermediate point of the 3-point-straight line
* \param C End point of the 3-point-straight line
* \param weighted_average_width The weighted average of the widths of the two colinear extrusion segments
* */
static int64_t calculateExtrusionAreaDeviationError(ExtrusionJunction A, ExtrusionJunction B, ExtrusionJunction C, coord_t& weighted_average_width);
static int64_t calculateExtrusionAreaDeviationError(ExtrusionJunction A, ExtrusionJunction B, ExtrusionJunction C);
bool is_contour() const;

View file

@ -1720,7 +1720,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
//BBS: version check
bool dont_load_config = !m_load_config;
if (m_bambuslicer_generator_version) {
Semver app_version = *(Semver::parse(SLIC3R_VERSION));
Semver app_version = *(Semver::parse(SoftFever_VERSION));
Semver file_version = *m_bambuslicer_generator_version;
if (file_version.maj() != app_version.maj())
dont_load_config = true;
@ -3638,7 +3638,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
}*/
} else if (m_curr_metadata_name == BBL_APPLICATION_TAG) {
// Generator application of the 3MF.
// SLIC3R_APP_KEY - SLIC3R_VERSION
// SLIC3R_APP_KEY - SoftFever_VERSION
if (boost::starts_with(m_curr_characters, "BambuStudio-")) {
m_is_bbl_3mf = true;
m_bambuslicer_generator_version = Semver::parse(m_curr_characters.substr(12));
@ -6380,7 +6380,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
metadata_item_map[BBL_CREATION_DATE_TAG] = date;
metadata_item_map[BBL_MODIFICATION_TAG] = date;
//SoftFever: write BambuStudio tag to keep it compatible
metadata_item_map[BBL_APPLICATION_TAG] = (boost::format("%1%-%2%") % "BambuStudio" % SLIC3R_VERSION).str();
metadata_item_map[BBL_APPLICATION_TAG] = (boost::format("%1%-%2%") % "BambuStudio" % SoftFever_VERSION).str();
}
metadata_item_map[BBS_3MF_VERSION] = std::to_string(VERSION_BBS_3MF);
@ -7197,7 +7197,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{
const std::string& temp_path = model.get_backup_path();
std::string temp_file = temp_path + std::string("/") + "_temp_1.config";
config.save_to_json(temp_file, std::string("project_settings"), std::string("project"), std::string(SLIC3R_VERSION));
config.save_to_json(temp_file, std::string("project_settings"), std::string("project"), std::string(SoftFever_VERSION));
return _add_file_to_archive(archive, BBS_PROJECT_CONFIG_FILE, temp_file);
}
@ -7538,7 +7538,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
// save slice header for debug
stream << " <" << SLICE_HEADER_TAG << ">\n";
stream << " <" << SLICE_HEADER_ITEM_TAG << " " << KEY_ATTR << "=\"" << "X-BBL-Client-Type" << "\" " << VALUE_ATTR << "=\"" << "slicer" << "\"/>\n";
stream << " <" << SLICE_HEADER_ITEM_TAG << " " << KEY_ATTR << "=\"" << "X-BBL-Client-Version" << "\" " << VALUE_ATTR << "=\"" << convert_to_full_version(SLIC3R_VERSION) << "\"/>\n";
stream << " <" << SLICE_HEADER_ITEM_TAG << " " << KEY_ATTR << "=\"" << "X-BBL-Client-Version" << "\" " << VALUE_ATTR << "=\"" << convert_to_full_version(SoftFever_VERSION) << "\"/>\n";
stream << " </" << SLICE_HEADER_TAG << ">\n";
for (unsigned int i = 0; i < (unsigned int)plate_data_list.size(); ++i)

View file

@ -3077,7 +3077,8 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print)
{
const auto flavor = print.config().gcode_flavor.value;
if (flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware) {
if ((flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfRepRapFirmware) &&
print.config().emit_machine_limits_to_gcode.value == true) {
int factor = flavor == gcfRepRapFirmware ? 60 : 1; // RRF M203 and M566 are in mm/min
file.write_format("M201 X%d Y%d Z%d E%d\n",
int(print.config().machine_max_acceleration_x.values.front() + 0.5),
@ -3120,7 +3121,6 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print)
print.config().machine_max_jerk_y.values.front() * factor,
print.config().machine_max_jerk_z.values.front() * factor,
print.config().machine_max_jerk_e.values.front() * factor);
}
}
@ -4515,6 +4515,58 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// extrude along the path
std::string gcode;
// Port of "wipe inside before extruding an external perimeter" feature from super slicer
if (m_config.wipe_before_external_loop.value && !paths.empty() && paths.front().size() > 1 && paths.back().size() > 1 && paths.front().role() == erExternalPerimeter) {
const bool is_full_loop_ccw = loop.polygon().is_counter_clockwise();
bool is_hole_loop = (loop.loop_role() & ExtrusionLoopRole::elrHole) != 0; // loop.make_counter_clockwise();
const double nozzle_diam = EXTRUDER_CONFIG(nozzle_diameter);
// note: previous & next are inverted to extrude "in the opposite direction, and we are "rewinding"
Point previous_point = paths.front().polyline.points[1];
Point current_point = paths.front().polyline.points.front();
Point next_point = paths.back().polyline.points.back();
// can happen if seam_gap is null
if (next_point == current_point) {
next_point = paths.back().polyline.points[paths.back().polyline.points.size() - 2];
}
Point a = next_point; // second point
Point b = previous_point; // second to last point
if ((is_hole_loop ? !is_full_loop_ccw : is_full_loop_ccw)) {
// swap points
std::swap(a, b);
}
double angle = current_point.ccw_angle(a, b) / 3;
// turn outwards if contour, turn inwwards if hole
if (is_hole_loop ? !is_full_loop_ccw : is_full_loop_ccw) angle *= -1;
Vec2d current_pos = current_point.cast<double>();
Vec2d next_pos = next_point.cast<double>();
Vec2d vec_dist = next_pos - current_pos;
double vec_norm = vec_dist.norm();
// Offset distance is the minimum between half the nozzle diameter or half the line width for the upcomming perimeter
// This is to mimimize potential instances where the de-retraction is performed on top of a neighbouring
// thin perimeter due to arachne reducing line width.
coordf_t dist = std::min(scaled(nozzle_diam) * 0.5, scaled(paths.front().width) * 0.5);
// FIXME Hiding the seams will not work nicely for very densely discretized contours!
Point pt = (current_pos + vec_dist * (2 * dist / vec_norm)).cast<coord_t>();
pt.rotate(angle, current_point);
pt = (current_pos + vec_dist * (2 * dist / vec_norm)).cast<coord_t>();
pt.rotate(angle, current_point);
// use extrude instead of travel_to_xy to trigger the unretract
ExtrusionPath fake_path_wipe(Polyline{pt, current_point}, paths.front());
fake_path_wipe.mm3_per_mm = 0;
gcode += extrude_path(fake_path_wipe, "move inwards before retraction/seam", speed);
}
bool is_small_peri = false;
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
// description += ExtrusionLoop::role_to_string(loop.loop_role());

View file

@ -123,6 +123,7 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object
// (print->config().print_sequence == PrintSequence::ByObject is true).
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
{
m_is_BBL_printer = object.print()->is_BBL_printer();
m_print_object_ptr = &object;
if (object.layers().empty())
return;
@ -162,6 +163,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
// (print->config().print_sequence == PrintSequence::ByObject is false).
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
{
m_is_BBL_printer = print.is_BBL_printer();
m_print_config_ptr = &print.config();
// Initialize the print layers for all objects and all layers.
@ -757,24 +759,23 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume()
const unsigned int number_of_extruders = (unsigned int) (sqrt(flush_matrix.size()) + EPSILON);
// Extract purging volumes for each extruder pair:
std::vector<std::vector<float>> wipe_volumes;
if (m_print_config_ptr->purge_in_prime_tower) {
if (print_config->purge_in_prime_tower || m_is_BBL_printer) {
for (unsigned int i = 0; i < number_of_extruders; ++i)
wipe_volumes.push_back(
std::vector<float>(flush_matrix.begin() + i * number_of_extruders, flush_matrix.begin() + (i + 1) * number_of_extruders));
wipe_volumes.push_back( std::vector<float>(flush_matrix.begin() + i * number_of_extruders,
flush_matrix.begin() + (i + 1) * number_of_extruders));
} else {
// populate wipe_volumes with prime_volume
for (unsigned int i = 0; i < number_of_extruders; ++i) {
wipe_volumes.push_back(std::vector<float>(number_of_extruders, m_print_config_ptr->prime_volume));
}
for (unsigned int i = 0; i < number_of_extruders; ++i)
wipe_volumes.push_back(std::vector<float>(number_of_extruders, print_config->prime_volume));
}
unsigned int current_extruder_id = -1;
for (int i = 0; i < m_layer_tools.size(); ++i) {
LayerTools& lt = m_layer_tools[i];
if (lt.extruders.empty())
continue;
// todo: The algorithm complexity is too high(o(n2)), currently only 8 colors are supported
if (i != 0 && lt.extruders.size() <= 8) {
// todo: The algorithm complexity is too high(o(n2)), currently only 12 colors are supported
if (i != 0 && lt.extruders.size() <= 12) {
lt.extruders = get_extruders_order(wipe_volumes, lt.extruders, current_extruder_id);
}
current_extruder_id = lt.extruders.back();

View file

@ -210,6 +210,7 @@ private:
const PrintConfig* m_print_config_ptr = nullptr;
const PrintObject* m_print_object_ptr = nullptr;
bool m_is_BBL_printer = false;
};
} // namespace SLic3r

View file

@ -1505,6 +1505,8 @@ void PerimeterGenerator::process_classic()
const Surface &surface = this->slices->surfaces[surface_order[order_idx]];
// detect how many perimeters must be generated for this island
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
if (this->config->alternate_extra_wall && this->layer_id % 2 == 1 && !m_spiral_vase) // add alternating extra wall
loop_number++;
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
loop_number = 0;
// Set the topmost layer to be one wall
@ -1937,6 +1939,8 @@ void PerimeterGenerator::process_arachne()
coord_t bead_width_0 = ext_perimeter_spacing;
// detect how many perimeters must be generated for this island
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
if (this->config->alternate_extra_wall && this->layer_id % 2 == 1 && !m_spiral_vase) // add alternating extra wall
loop_number++;
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
loop_number = 0;
// Orca: set the topmost layer to be one wall according to the config

View file

@ -766,7 +766,7 @@ bool Preset::has_cali_lines(PresetBundle* preset_bundle)
}
static std::vector<std::string> s_Preset_print_options {
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "slicing_mode",
"layer_height", "initial_layer_print_height", "wall_loops", "alternate_extra_wall", "slice_closing_radius", "spiral_mode", "spiral_mode_smooth", "spiral_mode_max_xy_smoothing", "slicing_mode",
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only",
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
@ -808,7 +808,7 @@ static std::vector<std::string> s_Preset_print_options {
"small_perimeter_speed", "small_perimeter_threshold","bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface",
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk",
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "wipe_before_external_loop",
"bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
@ -878,7 +878,7 @@ static std::vector<std::string> s_Preset_printer_options {
"cooling_tube_retraction",
"cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "purge_in_prime_tower", "enable_filament_ramming",
"z_offset",
"disable_m73", "preferred_orientation"
"disable_m73", "preferred_orientation", "emit_machine_limits_to_gcode"
};
static std::vector<std::string> s_Preset_sla_print_options {

View file

@ -5,6 +5,7 @@
#include "Utils.hpp"
#include "Model.hpp"
#include "format.hpp"
#include "libslic3r_version.h"
#include <algorithm>
#include <set>
@ -462,7 +463,7 @@ std::string PresetBundle::get_texture_for_printer_model(std::string model_name)
{
for (auto vendor_model: vendor_profile.second.models)
{
if (vendor_model.name == model_name)
if (vendor_model.name == model_name || vendor_model.id == model_name)
{
texture_name = vendor_model.bed_texture;
vendor_name = vendor_profile.first;
@ -675,7 +676,7 @@ PresetsConfigSubstitutions PresetBundle::import_presets(std::vector<std::string>
import_json_presets(substitutions, file, override_confirm, rule, overwrite, result);
}
// Determine if it is a preset bundle
if (boost::iends_with(file, ".bbscfg") || boost::iends_with(file, ".bbsflmt") || boost::iends_with(file, ".zip")) {
if (boost::iends_with(file, ".orca_printer") || boost::iends_with(file, ".orca_filament") || boost::iends_with(file, ".zip")) {
boost::system::error_code ec;
// create user folder
fs::path user_folder(data_dir() + "/" + PRESET_USER_DIR);
@ -767,7 +768,7 @@ bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & s
std::string version_str = key_values[BBL_JSON_KEY_VERSION];
boost::optional<Semver> version = Semver::parse(version_str);
if (!version) return false;
Semver app_version = *(Semver::parse(SLIC3R_VERSION));
Semver app_version = *(Semver::parse(SoftFever_VERSION));
if (version->maj() != app_version.maj()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << " Preset incompatibla, not loading: " << name;
return false;

View file

@ -487,7 +487,7 @@ void PrintConfigDef::init_common_params()
def = this->add("print_host", coString);
def->label = L("Hostname, IP or URL");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
def->tooltip = L("Orca Slicer can upload G-code files to a printer host. This field should contain "
"the hostname, IP address or URL of the printer host instance. "
"Print host behind HAProxy with basic auth enabled can be accessed by putting the user name and password into the URL "
"in the following format: https://username:password@your-octopi-address/");
@ -505,7 +505,7 @@ void PrintConfigDef::init_common_params()
def = this->add("printhost_apikey", coString);
def->label = L("API Key / Password");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
def->tooltip = L("Orca Slicer can upload G-code files to a printer host. This field should contain "
"the API Key or the password required for authentication.");
def->mode = comAdvanced;
def->cli = ConfigOptionDef::nocli;
@ -1633,7 +1633,7 @@ def = this->add("filament_loading_speed", coFloats);
def->label = L("Minimal purge on wipe tower");
def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside "
"the nozzle may not be known, and the filament pressure is likely not yet stable. "
"Before purging the print head into an infill or a sacrificial object, Slic3r will always prime "
"Before purging the print head into an infill or a sacrificial object, Orca Slicer will always prime "
"this amount of material into the wipe tower to produce successive infill or sacrificial object extrusions reliably.");
def->sidetext = L("mm³");
def->min = 0;
@ -1837,7 +1837,7 @@ def = this->add("filament_loading_speed", coFloats);
def->label = L("Sparse infill anchor length");
def->category = L("Strength");
def->tooltip = L("Connect an infill line to an internal perimeter with a short segment of an additional perimeter. "
"If expressed as percentage (example: 15%) it is calculated over infill extrusion width. Slic3r tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment "
"If expressed as percentage (example: 15%) it is calculated over infill extrusion width. Orca Slicer tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment "
"shorter than infill_anchor_max is found, the infill line is connected to a perimeter segment at just one side "
"and the length of the perimeter segment taken is limited to this parameter, but no longer than anchor_length_max. "
"\nSet this parameter to zero to disable anchoring perimeters connected to a single infill line.");
@ -1864,7 +1864,7 @@ def = this->add("filament_loading_speed", coFloats);
def->label = L("Maximum length of the infill anchor");
def->category = L("Strength");
def->tooltip = L("Connect an infill line to an internal perimeter with a short segment of an additional perimeter. "
"If expressed as percentage (example: 15%) it is calculated over infill extrusion width. Slic3r tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment "
"If expressed as percentage (example: 15%) it is calculated over infill extrusion width. Orca Slicer tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment "
"shorter than this parameter is found, the infill line is connected to a perimeter segment at just one side "
"and the length of the perimeter segment taken is limited to infill_anchor, but no longer than this parameter. "
"\nIf set to 0, the old algorithm for infill connection will be used, it should create the same result as with 1000 & 0.");
@ -2367,7 +2367,7 @@ def = this->add("filament_loading_speed", coFloats);
def->label = L("Exclude objects");
def->tooltip = L("Enable this option to add EXCLUDE OBJECT command in g-code");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(1));
def->set_default_value(new ConfigOptionBool(false));
def = this->add("gcode_comments", coBool);
def->label = L("Verbose G-code");
@ -2564,6 +2564,14 @@ def = this->add("filament_loading_speed", coFloats);
def->mode = comDevelop;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("emit_machine_limits_to_gcode", coBool);
def->label = L("Emit limits to G-code");
def->category = L("Machine limits");
def->tooltip = L("If enabled, the machine limits will be emitted to G-code file.\nThis option will be ignored if the g-code flavor is "
"set to Klipper.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("machine_pause_gcode", coString);
def->label = L("Pause G-code");
def->tooltip = L("This G-code will be used as a code for the pause print. User can insert pause G-code in gcode viewer");
@ -2818,7 +2826,7 @@ def = this->add("filament_loading_speed", coFloats);
def = this->add("host_type", coEnum);
def->label = L("Host Type");
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field must contain "
def->tooltip = L("Orca Slicer can upload G-code files to a printer host. This field must contain "
"the kind of the host.");
def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values();
def->enum_values.push_back("prusalink");
@ -3001,12 +3009,19 @@ def = this->add("filament_loading_speed", coFloats);
def->max = 1000;
def->set_default_value(new ConfigOptionInt(2));
def = this->add("alternate_extra_wall", coBool);
def->label = L("Alternate extra wall");
def->category = L("Strength");
def->tooltip = L("This setting adds an extra wall to every other layer. This way the infill gets wedged vertically between the walls, resulting in stronger prints. \n\nWhen this option is enabled, the ensure vertical shell thickness option needs to be disabled. \n\nUsing lightning infill together with this option is not recommended as there is limited infill to anchor the extra perimeters to.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("post_process", coStrings);
def->label = L("Post-processing Scripts");
def->tooltip = L("If you want to process the output G-code through custom scripts, "
"just list their absolute paths here. Separate multiple scripts with a semicolon. "
"Scripts will be passed the absolute path to the G-code file as the first argument, "
"and they can access the Slic3r config settings by reading environment variables.");
"and they can access the Orca Slicer config settings by reading environment variables.");
def->gui_flags = "serialized";
def->multiline = true;
def->full_width = true;
@ -3312,6 +3327,16 @@ def = this->add("filament_loading_speed", coFloats);
def->tooltip = L("To minimize the visibility of the seam in a closed loop extrusion, a small inward movement is executed before the extruder leaves the loop.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("wipe_before_external_loop", coBool);
def->label = L("Wipe before external loop");
def->tooltip = L("To minimise visibility of potential overextrusion at the start of an external perimeter when printing with "
"Outer/Inner or Inner/Outer/Inner wall print order, the deretraction is performed slightly on the inside from the "
"start of the external perimeter. That way any potential over extrusion is hidden from the outside surface. \n\nThis "
"is useful when printing with Outer/Inner or Inner/Outer/Inner wall print order as in these modes it is more likely "
"an external perimeter is printed immediately after a deretraction move.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("wipe_speed", coFloatOrPercent);
def->label = L("Wipe speed");
@ -4436,8 +4461,8 @@ def = this->add("filament_loading_speed", coFloats);
def->label = L("Use relative E distances");
def->tooltip = L("Relative extrusion is recommended when using \"label_objects\" option."
"Some extruders work better with this option unckecked (absolute extrusion mode). "
"Wipe tower is only compatible with relative mode. It is always enabled on "
"BambuLab printers. Default is checked");
"Wipe tower is only compatible with relative mode. It is recommended on "
"most printers. Default is checked");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));
@ -5494,6 +5519,7 @@ void DynamicPrintConfig::normalize_fdm(int used_filaments)
}
{
this->opt<ConfigOptionInt>("wall_loops", true)->value = 1;
this->opt<ConfigOptionBool>("alternate_extra_wall", true)->value = false;
this->opt<ConfigOptionInt>("top_shell_layers", true)->value = 0;
this->opt<ConfigOptionPercent>("sparse_infill_density", true)->value = 0;
}
@ -5566,6 +5592,7 @@ void DynamicPrintConfig::normalize_fdm_1()
}
{
this->opt<ConfigOptionInt>("wall_loops", true)->value = 1;
this->opt<ConfigOptionBool>("alternate_extra_wall", true)->value = false;
this->opt<ConfigOptionInt>("top_shell_layers", true)->value = 0;
this->opt<ConfigOptionPercent>("sparse_infill_density", true)->value = 0;
}

View file

@ -853,6 +853,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, inner_wall_speed))
// Total number of perimeters.
((ConfigOptionInt, wall_loops))
((ConfigOptionBool, alternate_extra_wall))
((ConfigOptionFloat, minimum_sparse_infill_area))
((ConfigOptionInt, solid_infill_filament))
((ConfigOptionFloatOrPercent, internal_solid_infill_line_width))
@ -879,6 +880,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, role_based_wipe_speed))
((ConfigOptionFloatOrPercent, wipe_speed))
((ConfigOptionBool, wipe_on_loops))
((ConfigOptionBool, wipe_before_external_loop))
((ConfigOptionEnum<WallInfillOrder>, wall_infill_order))
((ConfigOptionBool, precise_outer_wall))
((ConfigOptionBool, overhang_speed_classic))
@ -906,6 +908,8 @@ PRINT_CONFIG_CLASS_DEFINE(
PRINT_CONFIG_CLASS_DEFINE(
MachineEnvelopeConfig,
// Orca: whether emit machine limits into the beginning of the G-code.
((ConfigOptionBool, emit_machine_limits_to_gcode))
// M201 X... Y... Z... E... [mm/sec^2]
((ConfigOptionFloats, machine_max_acceleration_x))
((ConfigOptionFloats, machine_max_acceleration_y))

View file

@ -911,6 +911,7 @@ bool PrintObject::invalidate_state_by_config_options(
}
} else if (
opt_key == "wall_loops"
|| opt_key == "alternate_extra_wall"
|| opt_key == "top_one_wall_type"
|| opt_key == "min_width_top_surface"
|| opt_key == "only_one_wall_first_layer"

View file

@ -284,6 +284,9 @@ static std::string g_data_dir;
void set_data_dir(const std::string &dir)
{
g_data_dir = dir;
if (!g_data_dir.empty() && !boost::filesystem::exists(g_data_dir)) {
boost::filesystem::create_directory(g_data_dir);
}
}
const std::string& data_dir()