mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-12 01:07:57 -06:00
support Klipper Exclude objects
natively.
Also remove fake slicer info
This commit is contained in:
parent
32d952587d
commit
22a24168e6
11 changed files with 141 additions and 34 deletions
|
@ -1530,12 +1530,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
print.config().nozzle_temperature_initial_layer.get_at(0));
|
||||
file.write("; CONFIG_BLOCK_END\n\n");
|
||||
} else {
|
||||
file.write_format("; hack-fix: write fake slicer info here so that "
|
||||
"preprocess_cancellation can process.\n");
|
||||
file.write_format("; %s\n\n", std::string(std::string("generated by SuperSlicer " SoftFever_VERSION " on ") +
|
||||
Slic3r::Utils::local_timestamp())
|
||||
.c_str());
|
||||
|
||||
DoExport::export_thumbnails_to_file(
|
||||
thumbnail_cb, print.get_plate_index(), print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values,
|
||||
[&file](const char *sz) { file.write(sz); },
|
||||
|
@ -1563,6 +1557,10 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
}
|
||||
|
||||
file.write_format("; EXECUTABLE_BLOCK_START\n");
|
||||
|
||||
// SoftFever
|
||||
file.write(set_object_info(&print));
|
||||
|
||||
// adds tags for time estimators
|
||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str());
|
||||
|
||||
|
@ -2474,7 +2472,7 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
|||
const PrintObject *print_object = layers[layer_id].original_object;
|
||||
//const PrintObject *print_object = layers[layer_id].object();
|
||||
if (print_object)
|
||||
out.emplace_back(object_by_extruder, layer_id, *print_object, single_object_instance_idx);
|
||||
out.emplace_back(object_by_extruder, *print_object, single_object_instance_idx);
|
||||
}
|
||||
} else {
|
||||
// Create mapping from PrintObject* to ObjectByExtruder*.
|
||||
|
@ -2502,7 +2500,7 @@ std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
|||
auto it = std::lower_bound(sorted.begin(), sorted.end(), key);
|
||||
if (it != sorted.end() && it->first == &print_object)
|
||||
// ObjectByExtruder for this PrintObject was found.
|
||||
out.emplace_back(*it->second, it->second - objects_by_extruder.data(), print_object, instance - print_object.instances().data());
|
||||
out.emplace_back(*it->second, print_object, instance->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2670,6 +2668,14 @@ namespace Skirt {
|
|||
|
||||
} // namespace Skirt
|
||||
|
||||
inline std::string get_instance_name(const PrintObject *object, const PrintInstance &inst) {
|
||||
return (boost::format("%1%_id_%2%_copy_%3%") % object->model_object()->name % object->get_id() % inst.id).str();
|
||||
}
|
||||
|
||||
inline std::string get_instance_name(const PrintObject *object, size_t inst_id) {
|
||||
return (boost::format("%1%_id_%2%_copy_%3%") % object->model_object()->name % object->get_id() % inst_id).str();
|
||||
}
|
||||
|
||||
// In sequential mode, process_layer is called once per each object and its copy,
|
||||
// therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object.
|
||||
// In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated.
|
||||
|
@ -3172,7 +3178,7 @@ GCode::LayerResult GCode::process_layer(
|
|||
if (is_anything_overridden && print_wipe_extrusions == 0)
|
||||
gcode+="; PURGING FINISHED\n";
|
||||
for (InstanceToPrint &instance_to_print : instances_to_print) {
|
||||
const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id];
|
||||
const LayerToPrint &layer_to_print = layers[instance_to_print.get_object_id()];
|
||||
// To control print speed of the 1st object layer printed over raft interface.
|
||||
bool object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 &&
|
||||
instance_to_print.print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id();
|
||||
|
@ -3181,11 +3187,19 @@ GCode::LayerResult GCode::process_layer(
|
|||
m_object_layer_over_raft = object_layer_over_raft;
|
||||
if (m_config.reduce_crossing_wall)
|
||||
m_avoid_crossing_perimeters.init_layer(*m_layer);
|
||||
bool reset_e = false;
|
||||
if (this->config().gcode_label_objects) {
|
||||
gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
||||
if (!m_config.use_relative_e_distances)
|
||||
gcode += m_writer.reset_e(true);
|
||||
gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
||||
reset_e = true;
|
||||
}
|
||||
if (this->config().exclude_object && print.config().gcode_flavor.value == gcfKlipper) {
|
||||
gcode += std::string("EXCLUDE_OBJECT_START NAME=") +
|
||||
get_instance_name(&instance_to_print.print_object, instance_to_print.instance_id) + "\n";
|
||||
reset_e = true;
|
||||
}
|
||||
// ref to: https://github.com/SoftFever/OrcaSlicer/pull/205/commits/7f1fe0bd544077626080aa1a9a0576aa735da1a4#r1083470162
|
||||
if (reset_e && !m_config.use_relative_e_distances)
|
||||
gcode += m_writer.reset_e(true);
|
||||
m_extrusion_quality_estimator.set_current_object(&instance_to_print.print_object);
|
||||
|
||||
// When starting a new object, use the external motion planner for the first travel move.
|
||||
|
@ -3196,7 +3210,7 @@ GCode::LayerResult GCode::process_layer(
|
|||
m_last_obj_copy = this_object_copy;
|
||||
this->set_origin(unscale(offset));
|
||||
if (instance_to_print.object_by_extruder.support != nullptr) {
|
||||
m_layer = layers[instance_to_print.layer_id].support_layer;
|
||||
m_layer = layers[instance_to_print.get_object_id()].support_layer;
|
||||
m_object_layer_over_raft = false;
|
||||
|
||||
//BBS: print supports' brims first
|
||||
|
@ -3274,10 +3288,16 @@ GCode::LayerResult GCode::process_layer(
|
|||
gcode += this->extrude_infill(print,by_region_specific, true);
|
||||
}
|
||||
if (this->config().gcode_label_objects) {
|
||||
gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
||||
if (!m_config.use_relative_e_distances)
|
||||
gcode += m_writer.reset_e(true);
|
||||
gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.print_object.get_id()) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
||||
reset_e = true;
|
||||
}
|
||||
if (this->config().exclude_object && print.config().gcode_flavor.value == gcfKlipper) {
|
||||
gcode += std::string("EXCLUDE_OBJECT_END NAME=") +
|
||||
get_instance_name(&instance_to_print.print_object, instance_to_print.instance_id) + "\n";
|
||||
reset_e = true;
|
||||
}
|
||||
if (reset_e && !m_config.use_relative_e_distances)
|
||||
gcode += m_writer.reset_e(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4591,6 +4611,37 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||
return gcode;
|
||||
}
|
||||
|
||||
inline std::string polygon_to_string(const Polygon &polygon) {
|
||||
std::ostringstream gcode;
|
||||
gcode << "[";
|
||||
for (const Point &p : polygon.points) {
|
||||
gcode << "[" << unscaled(p.x()) << "," << unscaled(p.y()) << "],";
|
||||
}
|
||||
gcode << "[" << unscaled(polygon.points.front().x()) << "," << unscaled(polygon.points.front().y()) << "]";
|
||||
gcode << "]";
|
||||
return gcode.str();
|
||||
}
|
||||
// this function iterator PrintObject and assign a seqential id to each object.
|
||||
// this id is used to generate unique object id for each object.
|
||||
std::string GCode::set_object_info(Print* print) {
|
||||
std::ostringstream gcode;
|
||||
size_t object_id = 0;
|
||||
for (PrintObject* object : print->objects()) {
|
||||
object->set_id(object_id++);
|
||||
size_t inst_id = 0;
|
||||
for (PrintInstance &inst : object->instances()) {
|
||||
inst.id = inst_id;
|
||||
if (this->config().exclude_object && print->config().gcode_flavor.value == gcfKlipper) {
|
||||
auto bbox = inst.get_bounding_box();
|
||||
gcode << "EXCLUDE_OBJECT_DEFINE NAME=" << get_instance_name(object, inst)
|
||||
<< " CENTER=" << bbox.center().x() << "," << bbox.center().y()
|
||||
<< " POLYGON=" << polygon_to_string(inst.get_convex_hull_2d()) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
// convert a model-space scaled point into G-code coordinates
|
||||
Vec2d GCode::point_to_gcode(const Point &point) const
|
||||
{
|
||||
|
@ -4714,4 +4765,10 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Index into std::vector<LayerToPrint>, which contains Object and Support layers for the current print_z, collected for
|
||||
// a single object, or for possibly multiple objects with multiple instances.
|
||||
|
||||
inline size_t GCode::InstanceToPrint::get_object_id() const { return print_object.get_id(); }
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -202,6 +202,9 @@ public:
|
|||
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
|
||||
std::string set_extruder(unsigned int extruder_id, double print_z);
|
||||
|
||||
// SoftFever
|
||||
std::string set_object_info(Print* print);
|
||||
|
||||
// append full config to the given string
|
||||
static void append_full_config(const Print& print, std::string& str);
|
||||
|
||||
|
@ -377,13 +380,13 @@ private:
|
|||
|
||||
struct InstanceToPrint
|
||||
{
|
||||
InstanceToPrint(ObjectByExtruder &object_by_extruder, size_t layer_id, const PrintObject &print_object, size_t instance_id) :
|
||||
object_by_extruder(object_by_extruder), layer_id(layer_id), print_object(print_object), instance_id(instance_id) {}
|
||||
InstanceToPrint(ObjectByExtruder &object_by_extruder, const PrintObject &print_object, size_t instance_id) :
|
||||
object_by_extruder(object_by_extruder), print_object(print_object), instance_id(instance_id) {}
|
||||
|
||||
// Repository
|
||||
ObjectByExtruder &object_by_extruder;
|
||||
// Index into std::vector<LayerToPrint>, which contains Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances.
|
||||
const size_t layer_id;
|
||||
size_t get_object_id() const;
|
||||
const PrintObject &print_object;
|
||||
// Instance idx of the copy of a print object.
|
||||
const size_t instance_id;
|
||||
|
|
|
@ -1286,18 +1286,21 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
|
|||
}
|
||||
|
||||
// This returns an accurate snug bounding box of the transformed object instance, without the translation applied.
|
||||
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
const Transform3d& inst_matrix = this->instances[instance_idx]->get_transformation().get_matrix(dont_translate);
|
||||
for (ModelVolume *v : this->volumes)
|
||||
{
|
||||
if (v->is_model_part())
|
||||
bb.merge(v->mesh().transformed_bounding_box(inst_matrix * v->get_matrix()));
|
||||
}
|
||||
return bb;
|
||||
BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_translate) const {
|
||||
return instance_bounding_box(*this->instances[instance_idx], dont_translate);
|
||||
}
|
||||
|
||||
BoundingBoxf3 ModelObject::instance_bounding_box(const ModelInstance &instance, bool dont_translate) const {
|
||||
BoundingBoxf3 bbox;
|
||||
const auto& inst_mat = instance.get_transformation().get_matrix(dont_translate);
|
||||
for (auto vol : this->volumes) {
|
||||
if (vol->is_model_part())
|
||||
bbox.merge(vol->mesh().transformed_bounding_box(inst_mat * vol->get_matrix()));
|
||||
}
|
||||
return bbox;
|
||||
}
|
||||
|
||||
|
||||
//BBS: add convex bounding box
|
||||
BoundingBoxf3 ModelObject::instance_convex_hull_bounding_box(size_t instance_idx, bool dont_translate) const
|
||||
{
|
||||
|
|
|
@ -345,6 +345,8 @@ public:
|
|||
const BoundingBoxf3& raw_bounding_box() const;
|
||||
// A snug bounding box around the transformed non-modifier object volumes.
|
||||
BoundingBoxf3 instance_bounding_box(size_t instance_idx, bool dont_translate = false) const;
|
||||
BoundingBoxf3 instance_bounding_box(const ModelInstance& instance, bool dont_translate = false) const;
|
||||
|
||||
// A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
|
||||
const BoundingBoxf3& raw_mesh_bounding_box() const;
|
||||
// A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
|
||||
|
|
|
@ -755,7 +755,8 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops",
|
||||
"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", "initial_layer_travel_speed"
|
||||
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
|
||||
"initial_layer_travel_speed", "exclude_object"
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -159,7 +159,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"accel_to_decel_factor",
|
||||
"wipe_on_loops",
|
||||
"gcode_comments",
|
||||
"gcode_label_objects"
|
||||
"gcode_label_objects",
|
||||
"exclude_object"
|
||||
};
|
||||
|
||||
static std::unordered_set<std::string> steps_ignore;
|
||||
|
@ -3329,4 +3330,14 @@ int Print::load_cached_data(const std::string& directory)
|
|||
return ret;
|
||||
}
|
||||
|
||||
BoundingBoxf3 PrintInstance::get_bounding_box() {
|
||||
return print_object->model_object()->instance_bounding_box(*model_instance, false);
|
||||
}
|
||||
|
||||
Polygon PrintInstance::get_convex_hull_2d() {
|
||||
Polygon poly = print_object->model_object()->convex_hull_2d(model_instance->get_matrix());
|
||||
poly.douglas_peucker(0.1);
|
||||
return poly;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -191,6 +191,13 @@ struct PrintInstance
|
|||
const ModelInstance *model_instance;
|
||||
// Shift of this instance's center into the world coordinates.
|
||||
Point shift;
|
||||
|
||||
BoundingBoxf3 get_bounding_box();
|
||||
Polygon get_convex_hull_2d();
|
||||
// SoftFever
|
||||
//
|
||||
// instance id
|
||||
size_t id;
|
||||
};
|
||||
|
||||
typedef std::vector<PrintInstance> PrintInstances;
|
||||
|
@ -292,6 +299,7 @@ public:
|
|||
Transform3d trafo_centered() const
|
||||
{ Transform3d t = this->trafo(); t.pretranslate(Vec3d(- unscale<double>(m_center_offset.x()), - unscale<double>(m_center_offset.y()), 0)); return t; }
|
||||
const PrintInstances& instances() const { return m_instances; }
|
||||
PrintInstances &instances() { return m_instances; }
|
||||
|
||||
// Whoever will get a non-const pointer to PrintObject will be able to modify its layers.
|
||||
LayerPtrs& layers() { return m_layers; }
|
||||
|
@ -417,7 +425,12 @@ public:
|
|||
|
||||
// BBS: Boundingbox of the first layer
|
||||
BoundingBox firstLayerObjectBrimBoundingBox;
|
||||
private:
|
||||
|
||||
// SoftFever
|
||||
size_t get_id() const { return m_id; }
|
||||
void set_id(size_t id) { m_id = id; }
|
||||
|
||||
private:
|
||||
// to be called from Print only.
|
||||
friend class Print;
|
||||
|
||||
|
@ -501,6 +514,12 @@ private:
|
|||
|
||||
PrintObject* m_shared_object{ nullptr };
|
||||
|
||||
|
||||
// SoftFever
|
||||
//
|
||||
// object id
|
||||
size_t m_id;
|
||||
|
||||
public:
|
||||
//BBS: When printing multi-material objects, this settings will make slicer to clip the overlapping object parts one by the other.
|
||||
//(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc).
|
||||
|
|
|
@ -1814,6 +1814,12 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(1));
|
||||
|
||||
def = this->add("exclude_object", coBool);
|
||||
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 = this->add("gcode_comments", coBool);
|
||||
def->label = L("Verbose G-code");
|
||||
def->tooltip = L("Enable this to get a commented G-code file, with each line explained by a descriptive text. "
|
||||
|
|
|
@ -1003,6 +1003,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
// SoftFever
|
||||
((ConfigOptionPercents, filament_shrink))
|
||||
((ConfigOptionBool, gcode_label_objects))
|
||||
((ConfigOptionBool, exclude_object))
|
||||
((ConfigOptionBool, gcode_comments))
|
||||
|
||||
)
|
||||
|
|
|
@ -697,6 +697,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
toggle_line(el, gcflavor == gcfKlipper);
|
||||
if(gcflavor == gcfKlipper)
|
||||
toggle_field("accel_to_decel_factor", config->opt_bool("accel_to_decel_enable"));
|
||||
|
||||
toggle_field("exclude_object", gcflavor == gcfKlipper);
|
||||
|
||||
}
|
||||
|
||||
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
||||
|
|
|
@ -2058,6 +2058,7 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("gcode_add_line_number");
|
||||
optgroup->append_single_option_line("gcode_comments");
|
||||
optgroup->append_single_option_line("gcode_label_objects");
|
||||
optgroup->append_single_option_line("exclude_object");
|
||||
Option option = optgroup->get_option("filename_format");
|
||||
// option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue