mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-10 17:21:10 +00:00
Merge branch 'main' into main
This commit is contained in:
+59
-44
@@ -122,7 +122,6 @@
|
||||
|
||||
#include <Shiny/Shiny.h>
|
||||
|
||||
#include "miniz_extension.hpp"
|
||||
|
||||
using namespace std::literals::string_view_literals;
|
||||
|
||||
@@ -134,6 +133,16 @@ using namespace std::literals::string_view_literals;
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include "AABBTreeLines.hpp"
|
||||
#include "Extruder.hpp"
|
||||
#include "ExtrusionEntityCollection.hpp"
|
||||
#include "FilamentMixer.hpp"
|
||||
#include "Format/STEP.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "MultiNozzleUtils.hpp"
|
||||
#include "Slicing.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
@@ -4037,6 +4046,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
// Collect custom seam data from all objects.
|
||||
std::function<void(void)> throw_if_canceled_func = [&print]() { print.throw_if_canceled(); };
|
||||
m_seam_placer.init(print, throw_if_canceled_func);
|
||||
// Precise Seam: init() only prepares its warning; issue it here, inside the active export step.
|
||||
if (!m_seam_placer.precise_seam_warning().empty())
|
||||
print.active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL,
|
||||
m_seam_placer.precise_seam_warning(),
|
||||
PrintStateBase::SlicingPreciseSeamWarning);
|
||||
|
||||
// BBS: get path for change filament
|
||||
if (m_writer.multiple_extruders) {
|
||||
@@ -4606,11 +4620,6 @@ struct PrecomputedLayer
|
||||
};
|
||||
} // namespace
|
||||
|
||||
template<typename BoolsOption> static bool any_enabled(const BoolsOption &option)
|
||||
{
|
||||
return std::any_of(option.values.begin(), option.values.end(), [](unsigned char enabled) { return enabled != 0; });
|
||||
}
|
||||
|
||||
// Whether process_layer() prepares the overhang estimator for `layer`.
|
||||
template<typename OverhangSpeed>
|
||||
static bool prepares_overhang_estimator(const Layer &layer, bool overhang_fan, OverhangSpeed overhang_speed)
|
||||
@@ -5398,7 +5407,8 @@ namespace Skirt {
|
||||
// Orca: Klipper can't parse object names with spaces and other spetical characters
|
||||
std::string sanitize_instance_name(const std::string& name) {
|
||||
// Replace sequences of non-word characters with an underscore
|
||||
std::string result = std::regex_replace(name, std::regex("[ !@#$%^&*()=+\\[\\]{};:\",']+"), "_");
|
||||
static const std::regex non_word_characters("[ !@#$%^&*()=+\\[\\]{};:\",']+");
|
||||
std::string result = std::regex_replace(name, non_word_characters, "_");
|
||||
// Remove leading and trailing underscores
|
||||
if (!result.empty() && result.front() == '_') {
|
||||
result.erase(result.begin());
|
||||
@@ -5412,12 +5422,16 @@ std::string sanitize_instance_name(const std::string& name) {
|
||||
|
||||
inline std::string get_instance_name(const PrintObject *object, size_t inst_id) {
|
||||
auto obj_name = sanitize_instance_name(object->model_object()->name);
|
||||
auto name = (boost::format("%1%_id_%2%_copy_%3%") % obj_name % object->get_id() % inst_id).str();
|
||||
auto name = obj_name + "_id_" + std::to_string(object->get_id()) + "_copy_" + std::to_string(inst_id);
|
||||
return sanitize_instance_name(name);
|
||||
}
|
||||
|
||||
inline std::string get_instance_name(const PrintObject *object, const PrintInstance &inst) {
|
||||
return get_instance_name(object, inst.id);
|
||||
const std::string& GCode::instance_name(const PrintInstance &instance)
|
||||
{
|
||||
auto [it, inserted] = m_instance_names.try_emplace(&instance);
|
||||
if (inserted)
|
||||
it->second = get_instance_name(instance.print_object, instance.id);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string GCode::generate_skirt(const Print &print,
|
||||
@@ -6877,7 +6891,7 @@ LayerResult GCode::process_layer(
|
||||
const auto gflavor = print.config().gcode_flavor.value;
|
||||
if (gflavor == gcfKlipper) {
|
||||
m_writer.set_object_start_str(std::string("EXCLUDE_OBJECT_START NAME=") +
|
||||
get_instance_name(&instance_to_print.print_object, inst.id) + "\n");
|
||||
instance_name(inst) + "\n");
|
||||
}
|
||||
else if (gflavor == gcfMarlinLegacy || gflavor == gcfMarlinFirmware || gflavor == gcfRepRapFirmware) {
|
||||
std::string str = std::string("M486 S") + std::to_string(inst.unique_id) + "\n";
|
||||
@@ -7026,7 +7040,7 @@ LayerResult GCode::process_layer(
|
||||
const auto gflavor = print.config().gcode_flavor.value;
|
||||
if (gflavor == gcfKlipper) {
|
||||
m_writer.set_object_end_str(std::string("EXCLUDE_OBJECT_END NAME=") +
|
||||
get_instance_name(&instance_to_print.print_object, inst.id) + "\n");
|
||||
instance_name(inst) + "\n");
|
||||
} else if (gflavor == gcfMarlinLegacy || gflavor == gcfMarlinFirmware || gflavor == gcfRepRapFirmware) {
|
||||
m_writer.set_object_end_str(std::string("M486 S-1\n"));
|
||||
}
|
||||
@@ -7101,7 +7115,7 @@ LayerResult GCode::process_layer(
|
||||
const auto gflavor = print.config().gcode_flavor.value;
|
||||
if (gflavor == gcfKlipper) {
|
||||
m_writer.set_object_start_str(std::string("EXCLUDE_OBJECT_START NAME=") +
|
||||
get_instance_name(&instance_to_print.print_object, inst.id) + "\n");
|
||||
instance_name(inst) + "\n");
|
||||
} else if (gflavor == gcfMarlinLegacy || gflavor == gcfMarlinFirmware || gflavor == gcfRepRapFirmware) {
|
||||
m_writer.set_object_start_str(std::string("M486 S") + std::to_string(inst.unique_id) + "\n");
|
||||
}
|
||||
@@ -7327,7 +7341,7 @@ LayerResult GCode::process_layer(
|
||||
const auto gflavor = print.config().gcode_flavor.value;
|
||||
if (gflavor == gcfKlipper) {
|
||||
m_writer.set_object_end_str(std::string("EXCLUDE_OBJECT_END NAME=") +
|
||||
get_instance_name(&instance_to_print.print_object, inst.id) + "\n");
|
||||
instance_name(inst) + "\n");
|
||||
} else if (gflavor == gcfMarlinLegacy || gflavor == gcfMarlinFirmware || gflavor == gcfRepRapFirmware) {
|
||||
m_writer.set_object_end_str(std::string("M486 S-1\n"));
|
||||
}
|
||||
@@ -8344,12 +8358,12 @@ static float overhang_fan_overlap_threshold(int overhang_fan_threshold)
|
||||
}
|
||||
}
|
||||
|
||||
std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double speed)
|
||||
std::string GCode::_extrude(const ExtrusionPath &path, const std::string &path_description, double speed)
|
||||
{
|
||||
std::string gcode;
|
||||
|
||||
if (is_bridge(path.role()))
|
||||
description += " (bridge)";
|
||||
const std::string bridge_description = is_bridge(path.role()) ? path_description + " (bridge)" : std::string();
|
||||
const std::string &description = bridge_description.empty() ? path_description : bridge_description;
|
||||
|
||||
const ExtrusionPathSloped* sloped = dynamic_cast<const ExtrusionPathSloped*>(&path);
|
||||
|
||||
@@ -9020,7 +9034,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
// ORCA: End of adaptive PA code segment
|
||||
}
|
||||
|
||||
gcode += m_writer.set_speed(F, "", comment);
|
||||
m_writer.set_speed(gcode, F, "", comment);
|
||||
{
|
||||
if (m_enable_cooling_markers) {
|
||||
if (enable_overhang_bridge_fan) {
|
||||
@@ -9044,7 +9058,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
double saved_z = m_writer.get_position().z();
|
||||
|
||||
for (const Line3& line : path.polyline.lines()) {
|
||||
std::string tempDescription = description;
|
||||
std::string flow_description;
|
||||
const double line_length = line.length() * SCALING_FACTOR;
|
||||
if (line_length < EPSILON)
|
||||
continue;
|
||||
@@ -9055,7 +9069,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role());
|
||||
|
||||
if (m_config.gcode_comments && oldE > 0 && oldE != dE) {
|
||||
tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
|
||||
flow_description = description + Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
|
||||
}
|
||||
}
|
||||
if (path.z_contoured) {
|
||||
@@ -9074,24 +9088,24 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
if (z < 0.1) {
|
||||
throw RuntimeError("GCode: very low z");
|
||||
}
|
||||
gcode += m_writer.extrude_to_xyz(Vec3d(dest2d.x(), dest2d.y(), z), e,
|
||||
GCodeWriter::full_gcode_comment ? tempDescription : "");
|
||||
m_writer.extrude_to_xyz(gcode, Vec3d(dest2d.x(), dest2d.y(), z), e,
|
||||
flow_description.empty() ? description : flow_description);
|
||||
|
||||
} else if (sloped == nullptr) {
|
||||
// Normal extrusion
|
||||
gcode += m_writer.extrude_to_xy(
|
||||
m_writer.extrude_to_xy(gcode,
|
||||
this->point_to_gcode(line.b.to_point()),
|
||||
dE,
|
||||
GCodeWriter::full_gcode_comment ? tempDescription : "", path.is_force_no_extrusion());
|
||||
flow_description.empty() ? description : flow_description, path.is_force_no_extrusion());
|
||||
} else {
|
||||
// Sloped extrusion
|
||||
const auto [z_ratio, e_ratio] = sloped->interpolate(path_length / total_length);
|
||||
Vec2d dest2d = this->point_to_gcode(line.b.to_point());
|
||||
Vec3d dest3d(dest2d(0), dest2d(1), get_sloped_z(z_ratio));
|
||||
gcode += m_writer.extrude_to_xyz(
|
||||
m_writer.extrude_to_xyz(gcode,
|
||||
dest3d,
|
||||
dE * e_ratio,
|
||||
GCodeWriter::full_gcode_comment ? tempDescription : "", path.is_force_no_extrusion());
|
||||
flow_description.empty() ? description : flow_description, path.is_force_no_extrusion());
|
||||
}
|
||||
check_and_insert_timelapse(line.b.to_point()); // Inline farthest-point snapshot
|
||||
}
|
||||
@@ -9099,13 +9113,13 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
// BBS: start to generate gcode from arc fitting data which includes line and arc
|
||||
const std::vector<PathFittingData>& fitting_result = path.polyline.fitting_result;
|
||||
for (size_t fitting_index = 0; fitting_index < fitting_result.size(); fitting_index++) {
|
||||
std::string tempDescription = description;
|
||||
std::string flow_description;
|
||||
switch (fitting_result[fitting_index].path_type) {
|
||||
case EMovePathType::Linear_move: {
|
||||
size_t start_index = fitting_result[fitting_index].start_point_index;
|
||||
size_t end_index = fitting_result[fitting_index].end_point_index;
|
||||
for (size_t point_index = start_index + 1; point_index < end_index + 1; point_index++) {
|
||||
tempDescription = description;
|
||||
flow_description.clear();
|
||||
const Line line = Line(path.polyline.points[point_index - 1].to_point(), path.polyline.points[point_index].to_point());
|
||||
const double line_length = line.length() * SCALING_FACTOR;
|
||||
if (line_length < EPSILON)
|
||||
@@ -9116,13 +9130,13 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role());
|
||||
|
||||
if (m_config.gcode_comments && oldE > 0 && oldE != dE) {
|
||||
tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
|
||||
flow_description = description + Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
|
||||
}
|
||||
}
|
||||
gcode += m_writer.extrude_to_xy(
|
||||
m_writer.extrude_to_xy(gcode,
|
||||
this->point_to_gcode(line.b),
|
||||
dE,
|
||||
GCodeWriter::full_gcode_comment ? tempDescription : "", path.is_force_no_extrusion());
|
||||
flow_description.empty() ? description : flow_description, path.is_force_no_extrusion());
|
||||
check_and_insert_timelapse(line.b); // Inline farthest-point snapshot
|
||||
}
|
||||
break;
|
||||
@@ -9140,15 +9154,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(arc_length, dE, path.role());
|
||||
|
||||
if (m_config.gcode_comments && oldE > 0 && oldE != dE) {
|
||||
tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, arc_length);
|
||||
flow_description = description + Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, arc_length);
|
||||
}
|
||||
}
|
||||
gcode += m_writer.extrude_arc_to_xy(
|
||||
m_writer.extrude_arc_to_xy(gcode,
|
||||
this->point_to_gcode(arc.end_point),
|
||||
center_offset,
|
||||
dE,
|
||||
arc.direction == ArcDirection::Arc_Dir_CCW,
|
||||
GCodeWriter::full_gcode_comment ? tempDescription : "", path.is_force_no_extrusion());
|
||||
flow_description.empty() ? description : flow_description, path.is_force_no_extrusion());
|
||||
check_and_insert_timelapse(arc.end_point); // Inline farthest-point snapshot
|
||||
break;
|
||||
}
|
||||
@@ -9172,7 +9186,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
Polyline3 l(p);
|
||||
total_length = l.length() * SCALING_FACTOR;
|
||||
}
|
||||
gcode += m_writer.set_speed(last_set_speed, "", comment);
|
||||
m_writer.set_speed(gcode, last_set_speed, "", comment);
|
||||
Vec3d prev = this->point_to_gcode_quantized(new_points[0].p);
|
||||
bool pre_fan_enabled = false;
|
||||
bool cur_fan_enabled = false;
|
||||
@@ -9184,7 +9198,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
|
||||
double path_length = 0.;
|
||||
for (size_t i = 1; i < new_points.size(); i++) {
|
||||
std::string tempDescription = description;
|
||||
std::string flow_description;
|
||||
const ProcessedPoint &processed_point = new_points[i];
|
||||
const ProcessedPoint &pre_processed_point = new_points[i-1];
|
||||
Vec3d p = this->point_to_gcode_quantized(processed_point.p);
|
||||
@@ -9251,10 +9265,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
// Ignore small speed variations - emit speed change if the delta between current and new is greater than 60mm/min / 1mm/sec
|
||||
// Reset speed to F if delta to F is less than 1mm/sec
|
||||
if ((std::abs(last_set_speed - new_speed) > 60)) {
|
||||
gcode += m_writer.set_speed(new_speed, "", comment);
|
||||
m_writer.set_speed(gcode, new_speed, "", comment);
|
||||
last_set_speed = new_speed;
|
||||
} else if ((std::abs(F - new_speed) <= 60)) {
|
||||
gcode += m_writer.set_speed(F, "", comment);
|
||||
m_writer.set_speed(gcode, F, "", comment);
|
||||
last_set_speed = F;
|
||||
}
|
||||
auto dE = e_per_mm * line_length;
|
||||
@@ -9263,7 +9277,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
dE = m_small_area_infill_flow_compensator->modify_flow(line_length, dE, path.role());
|
||||
|
||||
if (m_config.gcode_comments && oldE > 0 && oldE != dE) {
|
||||
tempDescription += Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
|
||||
flow_description = description + Slic3r::format(" | Old Flow Value: %0.5f Length: %0.5f",oldE, line_length);
|
||||
}
|
||||
}
|
||||
if (path.z_contoured) {
|
||||
@@ -9281,16 +9295,16 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
if (z < 0.1) {
|
||||
throw RuntimeError("GCode: very low z");
|
||||
}
|
||||
gcode += m_writer.extrude_to_xyz(Vec3d(dest2d.x(), dest2d.y(), z), e,
|
||||
GCodeWriter::full_gcode_comment ? tempDescription : "");
|
||||
m_writer.extrude_to_xyz(gcode, Vec3d(dest2d.x(), dest2d.y(), z), e,
|
||||
flow_description.empty() ? description : flow_description);
|
||||
} else if (sloped == nullptr) {
|
||||
// Normal extrusion
|
||||
gcode += m_writer.extrude_to_xy(p.head<2>(), dE, GCodeWriter::full_gcode_comment ? tempDescription : "");
|
||||
m_writer.extrude_to_xy(gcode, p.head<2>(), dE, flow_description.empty() ? description : flow_description);
|
||||
} else {
|
||||
// Sloped extrusion
|
||||
const auto [z_ratio, e_ratio] = sloped->interpolate(path_length / total_length);
|
||||
Vec3d dest3d(p(0), p(1), get_sloped_z(z_ratio));
|
||||
gcode += m_writer.extrude_to_xyz(dest3d, dE * e_ratio, GCodeWriter::full_gcode_comment ? tempDescription : "");
|
||||
m_writer.extrude_to_xyz(gcode, dest3d, dE * e_ratio, flow_description.empty() ? description : flow_description);
|
||||
}
|
||||
|
||||
// Inline farthest-point snapshot on the variable-speed emission path. Inert unless the
|
||||
@@ -10376,6 +10390,7 @@ std::string GCode::set_object_info(Print *print) {
|
||||
// PA_Line has only one object, no EXCLUDE_OBJECT_DEFINE needed
|
||||
} else {
|
||||
size_t unique_id = 0;
|
||||
m_instance_names.clear();
|
||||
for (PrintObject* object : print->objects()) {
|
||||
object->set_id(object_id++);
|
||||
size_t inst_id = 0;
|
||||
@@ -10384,7 +10399,7 @@ std::string GCode::set_object_info(Print *print) {
|
||||
inst.id = inst_id++;
|
||||
auto bbox = inst.get_bounding_box();
|
||||
auto center = print->translate_to_print_space(Vec2d(bbox.center().x(), bbox.center().y()));
|
||||
auto inst_name = get_instance_name(object, inst);
|
||||
const std::string &inst_name = instance_name(inst);
|
||||
if (gflavor == gcfKlipper) {
|
||||
gcode << "EXCLUDE_OBJECT_DEFINE NAME=" << inst_name << " CENTER=" << center.x() << "," << center.y()
|
||||
<< " POLYGON=" << polygon_to_string(inst.get_convex_hull_2d(), print) << "\n";
|
||||
|
||||
Reference in New Issue
Block a user