mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
ENH: support exclude objects for klipper printer
Thanks OrcaSlicer. This is just function for klipper printer. NEVER used for BBL printer. Signed-off-by: salt.wei <salt.wei@bambulab.com> Change-Id: I910abceb67f4dcb4260f74f5dd1b4fb614812670
This commit is contained in:
parent
0daca9d329
commit
e567afdcb5
11 changed files with 146 additions and 5 deletions
|
@ -1586,6 +1586,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
file.write_format("; EXECUTABLE_BLOCK_START\n");
|
file.write_format("; EXECUTABLE_BLOCK_START\n");
|
||||||
|
|
||||||
|
// SoftFever: Orca's implementation for skipping object, for klipper firmware printer only
|
||||||
|
if (this->config().exclude_object && print.config().gcode_flavor.value == gcfKlipper)
|
||||||
|
file.write(set_object_info(&print));
|
||||||
|
|
||||||
// adds tags for time estimators
|
// adds tags for time estimators
|
||||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str());
|
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::First_Line_M73_Placeholder).c_str());
|
||||||
|
|
||||||
|
@ -2656,6 +2661,18 @@ namespace Skirt {
|
||||||
|
|
||||||
} // namespace Skirt
|
} // namespace Skirt
|
||||||
|
|
||||||
|
inline std::string get_instance_name(const PrintObject* object, size_t inst_id) {
|
||||||
|
auto obj_name = object->model_object()->name;
|
||||||
|
// replace space in obj_name with '-'
|
||||||
|
std::replace(obj_name.begin(), obj_name.end(), ' ', '_');
|
||||||
|
|
||||||
|
return (boost::format("%1%_id_%2%_copy_%3%") % obj_name % object->get_klipper_object_id() % inst_id).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string get_instance_name(const PrintObject* object, const PrintInstance& inst) {
|
||||||
|
return get_instance_name(object, inst.id);
|
||||||
|
}
|
||||||
|
|
||||||
// In sequential mode, process_layer is called once per each object and its copy,
|
// 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.
|
// 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.
|
// In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated.
|
||||||
|
@ -3156,6 +3173,7 @@ GCode::LayerResult GCode::process_layer(
|
||||||
if (is_anything_overridden && print_wipe_extrusions == 0)
|
if (is_anything_overridden && print_wipe_extrusions == 0)
|
||||||
gcode+="; PURGING FINISHED\n";
|
gcode+="; PURGING FINISHED\n";
|
||||||
for (InstanceToPrint &instance_to_print : instances_to_print) {
|
for (InstanceToPrint &instance_to_print : instances_to_print) {
|
||||||
|
const auto& inst = instance_to_print.print_object.instances()[instance_to_print.instance_id];
|
||||||
const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id];
|
const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id];
|
||||||
// To control print speed of the 1st object layer printed over raft interface.
|
// 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 &&
|
bool object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 &&
|
||||||
|
@ -3173,6 +3191,16 @@ GCode::LayerResult GCode::process_layer(
|
||||||
}
|
}
|
||||||
m_writer.set_object_start_str(start_str);
|
m_writer.set_object_start_str(start_str);
|
||||||
}
|
}
|
||||||
|
//Orca's implementation for skipping object, for klipper firmware printer only
|
||||||
|
bool reset_e = false;
|
||||||
|
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, inst.id) + "\n";
|
||||||
|
reset_e = true;
|
||||||
|
}
|
||||||
|
if (reset_e && !RELATIVE_E_AXIS)
|
||||||
|
gcode += m_writer.reset_e(true);
|
||||||
|
|
||||||
// When starting a new object, use the external motion planner for the first travel move.
|
// When starting a new object, use the external motion planner for the first travel move.
|
||||||
const Point &offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
|
const Point &offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
|
||||||
std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object, offset);
|
std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object, offset);
|
||||||
|
@ -3267,7 +3295,14 @@ GCode::LayerResult GCode::process_layer(
|
||||||
end_str += "M625\n";
|
end_str += "M625\n";
|
||||||
m_writer.set_object_end_str(end_str);
|
m_writer.set_object_end_str(end_str);
|
||||||
}
|
}
|
||||||
|
//Orca's implementation for skipping object, for klipper firmware printer only
|
||||||
|
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, inst.id) + "\n";
|
||||||
|
reset_e = true;
|
||||||
|
}
|
||||||
|
if (reset_e && !RELATIVE_E_AXIS)
|
||||||
|
gcode += m_writer.reset_e(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4553,6 +4588,41 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::string polygon_to_string(const Polygon& polygon, Print* print) {
|
||||||
|
std::ostringstream gcode;
|
||||||
|
gcode << "[";
|
||||||
|
for (const Point& p : polygon.points) {
|
||||||
|
const auto v = print->translate_to_print_space(p);
|
||||||
|
gcode << "[" << v.x() << "," << v.y() << "],";
|
||||||
|
}
|
||||||
|
const auto first_v = print->translate_to_print_space(polygon.points.front());
|
||||||
|
gcode << "[" << first_v.x() << "," << first_v.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_klipper_object_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();
|
||||||
|
auto center = print->translate_to_print_space(Vec2d(bbox.center().x(), bbox.center().y()));
|
||||||
|
gcode << "EXCLUDE_OBJECT_DEFINE NAME=" << get_instance_name(object, inst) << " CENTER=" << center.x()
|
||||||
|
<< "," << center.y() << " POLYGON=" << polygon_to_string(inst.get_convex_hull_2d(), print)
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gcode.str();
|
||||||
|
}
|
||||||
|
|
||||||
// convert a model-space scaled point into G-code coordinates
|
// convert a model-space scaled point into G-code coordinates
|
||||||
Vec2d GCode::point_to_gcode(const Point &point) const
|
Vec2d GCode::point_to_gcode(const Point &point) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -195,6 +195,9 @@ public:
|
||||||
void set_layer_count(unsigned int value) { m_layer_count = value; }
|
void set_layer_count(unsigned int value) { m_layer_count = value; }
|
||||||
void apply_print_config(const PrintConfig &print_config);
|
void apply_print_config(const PrintConfig &print_config);
|
||||||
|
|
||||||
|
// SoftFever
|
||||||
|
std::string set_object_info(Print* print);
|
||||||
|
|
||||||
// append full config to the given string
|
// append full config to the given string
|
||||||
static void append_full_config(const Print& print, std::string& str);
|
static void append_full_config(const Print& print, std::string& str);
|
||||||
|
|
||||||
|
|
|
@ -1384,6 +1384,16 @@ BoundingBoxf3 ModelObject::instance_bounding_box(size_t instance_idx, bool dont_
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
//BBS: add convex bounding box
|
||||||
BoundingBoxf3 ModelObject::instance_convex_hull_bounding_box(size_t instance_idx, bool dont_translate) const
|
BoundingBoxf3 ModelObject::instance_convex_hull_bounding_box(size_t instance_idx, bool dont_translate) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -423,6 +423,8 @@ public:
|
||||||
const BoundingBoxf3& raw_bounding_box() const;
|
const BoundingBoxf3& raw_bounding_box() const;
|
||||||
// A snug bounding box around the transformed non-modifier object volumes.
|
// 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(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.
|
// 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;
|
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.
|
// A snug bounding box of non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
|
||||||
|
|
|
@ -785,7 +785,9 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk",
|
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk",
|
||||||
"filter_out_gap_fill",
|
"filter_out_gap_fill",
|
||||||
// calib
|
// calib
|
||||||
"print_flow_ratio"
|
"print_flow_ratio",
|
||||||
|
//Orca
|
||||||
|
"exclude_object"
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::vector<std::string> s_Preset_filament_options {
|
static std::vector<std::string> s_Preset_filament_options {
|
||||||
|
|
|
@ -160,7 +160,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||||
"initial_layer_jerk",
|
"initial_layer_jerk",
|
||||||
"travel_jerk",
|
"travel_jerk",
|
||||||
"inner_wall_acceleration",
|
"inner_wall_acceleration",
|
||||||
"sparse_infill_acceleration"
|
"sparse_infill_acceleration",
|
||||||
|
"exclude_object",
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::unordered_set<std::string> steps_ignore;
|
static std::unordered_set<std::string> steps_ignore;
|
||||||
|
@ -2004,6 +2005,16 @@ std::vector<Point> Print::first_layer_wipe_tower_corners(bool check_wipe_tower_e
|
||||||
return corners;
|
return corners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SoftFever
|
||||||
|
Vec2d Print::translate_to_print_space(const Vec2d& point) const {
|
||||||
|
//const BoundingBoxf bed_bbox(config().printable_area.values);
|
||||||
|
return Vec2d(point(0) - m_origin(0), point(1) - m_origin(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2d Print::translate_to_print_space(const Point& point) const {
|
||||||
|
return Vec2d(unscaled(point.x()) - m_origin(0), unscaled(point.y()) - m_origin(1));
|
||||||
|
}
|
||||||
|
|
||||||
void Print::finalize_first_layer_convex_hull()
|
void Print::finalize_first_layer_convex_hull()
|
||||||
{
|
{
|
||||||
append(m_first_layer_convex_hull.points, m_skirt_convex_hull);
|
append(m_first_layer_convex_hull.points, m_skirt_convex_hull);
|
||||||
|
@ -3495,4 +3506,14 @@ int Print::load_cached_data(const std::string& directory)
|
||||||
return ret;
|
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
|
} // namespace Slic3r
|
||||||
|
|
|
@ -194,6 +194,13 @@ struct PrintInstance
|
||||||
const ModelInstance *model_instance;
|
const ModelInstance *model_instance;
|
||||||
// Shift of this instance's center into the world coordinates.
|
// Shift of this instance's center into the world coordinates.
|
||||||
Point shift;
|
Point shift;
|
||||||
|
|
||||||
|
BoundingBoxf3 get_bounding_box();
|
||||||
|
Polygon get_convex_hull_2d();
|
||||||
|
// SoftFever
|
||||||
|
//
|
||||||
|
// instance id
|
||||||
|
size_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<PrintInstance> PrintInstances;
|
typedef std::vector<PrintInstance> PrintInstances;
|
||||||
|
@ -295,6 +302,7 @@ public:
|
||||||
Transform3d trafo_centered() const
|
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; }
|
{ 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; }
|
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.
|
// Whoever will get a non-const pointer to PrintObject will be able to modify its layers.
|
||||||
LayerPtrs& layers() { return m_layers; }
|
LayerPtrs& layers() { return m_layers; }
|
||||||
|
@ -420,6 +428,11 @@ public:
|
||||||
|
|
||||||
// BBS: Boundingbox of the first layer
|
// BBS: Boundingbox of the first layer
|
||||||
BoundingBox firstLayerObjectBrimBoundingBox;
|
BoundingBox firstLayerObjectBrimBoundingBox;
|
||||||
|
|
||||||
|
// SoftFever
|
||||||
|
size_t get_klipper_object_id() const { return m_klipper_object_id; }
|
||||||
|
void set_klipper_object_id(size_t id) { m_klipper_object_id = id; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// to be called from Print only.
|
// to be called from Print only.
|
||||||
friend class Print;
|
friend class Print;
|
||||||
|
@ -504,6 +517,11 @@ private:
|
||||||
|
|
||||||
PrintObject* m_shared_object{ nullptr };
|
PrintObject* m_shared_object{ nullptr };
|
||||||
|
|
||||||
|
// SoftFever
|
||||||
|
//
|
||||||
|
// object id for klipper firmware only
|
||||||
|
size_t m_klipper_object_id;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//BBS: When printing multi-material objects, this settings will make slicer to clip the overlapping object parts one by the other.
|
//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).
|
//(2nd part will be clipped by the 1st, 3rd part will be clipped by the 1st and 2nd etc).
|
||||||
|
@ -789,11 +807,14 @@ public:
|
||||||
|
|
||||||
// Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
|
// Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
|
||||||
std::vector<Point> first_layer_wipe_tower_corners(bool check_wipe_tower_existance=true) const;
|
std::vector<Point> first_layer_wipe_tower_corners(bool check_wipe_tower_existance=true) const;
|
||||||
|
//SoftFever
|
||||||
CalibMode & calib_mode() { return m_calib_params.mode; }
|
CalibMode & calib_mode() { return m_calib_params.mode; }
|
||||||
const CalibMode& calib_mode() const { return m_calib_params.mode; }
|
const CalibMode& calib_mode() const { return m_calib_params.mode; }
|
||||||
void set_calib_params(const Calib_Params ¶ms);
|
void set_calib_params(const Calib_Params ¶ms);
|
||||||
const Calib_Params& calib_params() const { return m_calib_params; }
|
const Calib_Params& calib_params() const { return m_calib_params; }
|
||||||
|
Vec2d translate_to_print_space(const Vec2d& point) const;
|
||||||
|
// scaled point
|
||||||
|
Vec2d translate_to_print_space(const Point& point) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Invalidates the step, and its depending steps in Print.
|
// Invalidates the step, and its depending steps in Print.
|
||||||
|
|
|
@ -1704,6 +1704,13 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->readonly = false;
|
def->readonly = false;
|
||||||
def->set_default_value(new ConfigOptionEnum<GCodeFlavor>(gcfMarlinLegacy));
|
def->set_default_value(new ConfigOptionEnum<GCodeFlavor>(gcfMarlinLegacy));
|
||||||
|
|
||||||
|
//OrcaSlicer
|
||||||
|
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 for klipper firmware printer");
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->set_default_value(new ConfigOptionBool(1));
|
||||||
|
|
||||||
//BBS
|
//BBS
|
||||||
def = this->add("infill_combination", coBool);
|
def = this->add("infill_combination", coBool);
|
||||||
def->label = L("Infill combination");
|
def->label = L("Infill combination");
|
||||||
|
|
|
@ -976,7 +976,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
||||||
((ConfigOptionFloat, travel_jerk))
|
((ConfigOptionFloat, travel_jerk))
|
||||||
|
|
||||||
// BBS: move from PrintObjectConfig
|
// BBS: move from PrintObjectConfig
|
||||||
((ConfigOptionBool, independent_support_layer_height))
|
((ConfigOptionBool, independent_support_layer_height))
|
||||||
|
((ConfigOptionBool, exclude_object))
|
||||||
)
|
)
|
||||||
|
|
||||||
// This object is mapped to Perl as Slic3r::Config::Full.
|
// This object is mapped to Perl as Slic3r::Config::Full.
|
||||||
|
|
|
@ -703,6 +703,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||||
|
|
||||||
toggle_field("accel_to_decel_factor", config->opt_bool("accel_to_decel_enable"));
|
toggle_field("accel_to_decel_factor", config->opt_bool("accel_to_decel_enable"));
|
||||||
}
|
}
|
||||||
|
toggle_line("exclude_object", gcflavor == gcfKlipper);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
void ConfigManipulation::update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config/* = false*/)
|
||||||
|
|
|
@ -2050,6 +2050,7 @@ void TabPrint::build()
|
||||||
optgroup = page->new_optgroup(L("G-code output"), L"param_gcode");
|
optgroup = page->new_optgroup(L("G-code output"), L"param_gcode");
|
||||||
optgroup->append_single_option_line("reduce_infill_retraction");
|
optgroup->append_single_option_line("reduce_infill_retraction");
|
||||||
optgroup->append_single_option_line("gcode_add_line_number");
|
optgroup->append_single_option_line("gcode_add_line_number");
|
||||||
|
optgroup->append_single_option_line("exclude_object");
|
||||||
Option option = optgroup->get_option("filename_format");
|
Option option = optgroup->get_option("filename_format");
|
||||||
option.opt.full_width = true;
|
option.opt.full_width = true;
|
||||||
optgroup->append_single_option_line(option);
|
optgroup->append_single_option_line(option);
|
||||||
|
@ -3627,6 +3628,8 @@ void TabPrinter::toggle_options()
|
||||||
//}
|
//}
|
||||||
if (m_active_page->title() == "Basic information") {
|
if (m_active_page->title() == "Basic information") {
|
||||||
toggle_option("single_extruder_multi_material", have_multiple_extruders);
|
toggle_option("single_extruder_multi_material", have_multiple_extruders);
|
||||||
|
//BBS: gcode_flavore of BBL printer can't be edited and changed
|
||||||
|
toggle_option("gcode_flavor", !is_BBL_printer);
|
||||||
|
|
||||||
auto flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
|
auto flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
|
||||||
bool is_marlin_flavor = flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware;
|
bool is_marlin_flavor = flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue