mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 04:32:01 +08:00
Label objects: refactoring + fix of object/instance indexing when instances are rotated/out-of-bed
This commit is contained in:
parent
387376fb25
commit
fe3cf27394
@ -158,6 +158,8 @@ set(SLIC3R_SOURCES
|
||||
GCode/ExtrusionProcessor.hpp
|
||||
GCode/FindReplace.cpp
|
||||
GCode/FindReplace.hpp
|
||||
GCode/LabelObjects.cpp
|
||||
GCode/LabelObjects.hpp
|
||||
GCode/GCodeWriter.cpp
|
||||
GCode/GCodeWriter.hpp
|
||||
GCode/PostProcessor.cpp
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "Exception.hpp"
|
||||
#include "ExtrusionEntity.hpp"
|
||||
#include "Geometry/ConvexHull.hpp"
|
||||
#include "GCode/LabelObjects.hpp"
|
||||
#include "GCode/PrintExtents.hpp"
|
||||
#include "GCode/Thumbnails.hpp"
|
||||
#include "GCode/WipeTower.hpp"
|
||||
@ -102,69 +103,6 @@ namespace Slic3r {
|
||||
gcode += '\n';
|
||||
}
|
||||
|
||||
|
||||
// Accepts vector of PrintObjectPtrs and an object and instance ids. Returns starting tag for label object function.
|
||||
static std::string label_object_start(LabelObjects label_object_style, GCodeFlavor flavor, const SpanOfConstPtrs<PrintObject>& objects, int object_id, int instance_id)
|
||||
{
|
||||
int unique_id = 0;
|
||||
for (size_t idx = 0; idx < size_t(object_id); ++idx)
|
||||
unique_id += int(objects[idx]->model_object()->instances.size());
|
||||
unique_id += instance_id;
|
||||
|
||||
std::string name = objects[object_id]->model_object()->name;
|
||||
if (label_object_style == LabelObjects::Firmware && objects[object_id]->model_object()->instances.size() > 1u)
|
||||
name += " (copy " + std::to_string(instance_id) + ")";
|
||||
|
||||
std::string out;
|
||||
if (label_object_style == LabelObjects::Octoprint)
|
||||
out += std::string("; printing object ") + name + " id:" + std::to_string(object_id) + " copy " + std::to_string(instance_id) + "\n";
|
||||
else if (label_object_style == LabelObjects::Firmware) {
|
||||
if (flavor == GCodeFlavor::gcfMarlinFirmware || flavor == GCodeFlavor::gcfMarlinLegacy || flavor == GCodeFlavor::gcfRepRapFirmware) {
|
||||
out += std::string("M486 S") + std::to_string(unique_id) + "\n";
|
||||
out += std::string("M486 A");
|
||||
out += (flavor == GCodeFlavor::gcfRepRapFirmware ? (std::string("\"") + name + "\"") : name) + "\n";
|
||||
} else {
|
||||
// Not supported by / implemented for the other firmware flavors.
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
static std::string label_object_stop(LabelObjects label_object_style, GCodeFlavor flavor, int object_id, int instance_id, const std::string& name)
|
||||
{
|
||||
std::string out;
|
||||
if (label_object_style == LabelObjects::Octoprint)
|
||||
out += std::string("; stop printing object ") + name + " id:" + std::to_string(object_id) + " copy " + std::to_string(instance_id) + "\n";
|
||||
else if (label_object_style == LabelObjects::Firmware)
|
||||
if (flavor == GCodeFlavor::gcfMarlinFirmware || flavor == GCodeFlavor::gcfMarlinLegacy || flavor == GCodeFlavor::gcfRepRapFirmware)
|
||||
out += std::string("M486 S-1\n");
|
||||
else {
|
||||
// Not supported by / implemented for the other firmware flavors.
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
static std::string label_all_objects(LabelObjects label_objects_style, GCodeFlavor flavor, const Print& print)
|
||||
{
|
||||
std::string out;
|
||||
|
||||
if (label_objects_style != LabelObjects::Disabled) {
|
||||
out += "\n";
|
||||
for (size_t object_idx = 0; object_idx < print.objects().size(); ++object_idx) {
|
||||
for (size_t inst_idx = 0; inst_idx < print.objects()[object_idx]->model_object()->instances.size(); ++inst_idx) {
|
||||
out += label_object_start(label_objects_style, flavor, print.objects(), object_idx, inst_idx);
|
||||
out += label_object_stop(label_objects_style, flavor, object_idx, inst_idx, print.objects()[object_idx]->model_object()->name);
|
||||
}
|
||||
}
|
||||
out += "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Return true if tch_prefix is found in custom_gcode
|
||||
static bool custom_gcode_changes_tool(const std::string& custom_gcode, const std::string& tch_prefix, unsigned next_extruder)
|
||||
{
|
||||
@ -1207,7 +1145,8 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
|
||||
this->print_machine_envelope(file, print);
|
||||
|
||||
// Label all objects so printer knows about them since the start.
|
||||
file.write(label_all_objects(config().gcode_label_objects, config().gcode_flavor, print));
|
||||
m_label_objects.init(print);
|
||||
file.write(m_label_objects.all_objects_header());
|
||||
|
||||
// Update output variables after the extruders were initialized.
|
||||
m_placeholder_parser_integration.init(m_writer);
|
||||
@ -2419,13 +2358,13 @@ void GCodeGenerator::process_layer_single_object(
|
||||
m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
m_last_obj_copy = this_object_copy;
|
||||
this->set_origin(unscale(offset));
|
||||
if (this->config().gcode_label_objects != LabelObjects::Disabled) {
|
||||
if (this->config().gcode_label_objects != LabelObjectsStyle::Disabled) {
|
||||
for (const PrintObject* po : print_object.print()->objects()) {
|
||||
if (po == &print_object)
|
||||
break;
|
||||
++object_id;
|
||||
}
|
||||
gcode += label_object_start(config().gcode_label_objects, config().gcode_flavor, print_object.print()->objects(), object_id, print_instance.instance_id);
|
||||
gcode += m_label_objects.start_object(print_instance.print_object.instances()[print_instance.instance_id], GCode::LabelObjects::IncludeName::No);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -2603,8 +2542,8 @@ void GCodeGenerator::process_layer_single_object(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! first && config().gcode_label_objects != LabelObjects::Disabled)
|
||||
gcode += label_object_stop(config().gcode_label_objects, config().gcode_flavor, object_id, print_instance.instance_id, print_object.model_object()->name);
|
||||
if (! first)
|
||||
gcode += m_label_objects.stop_object(print_instance.print_object.instances()[print_instance.instance_id]);
|
||||
}
|
||||
|
||||
void GCodeGenerator::apply_print_config(const PrintConfig &print_config)
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "GCode/CoolingBuffer.hpp"
|
||||
#include "GCode/FindReplace.hpp"
|
||||
#include "GCode/GCodeWriter.hpp"
|
||||
#include "GCode/LabelObjects.hpp"
|
||||
#include "GCode/PressureEqualizer.hpp"
|
||||
#include "GCode/RetractWhenCrossingPerimeters.hpp"
|
||||
#include "GCode/SmoothPath.hpp"
|
||||
@ -353,6 +354,7 @@ private:
|
||||
|
||||
OozePrevention m_ooze_prevention;
|
||||
GCode::Wipe m_wipe;
|
||||
GCode::LabelObjects m_label_objects;
|
||||
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
||||
JPSPathFinder m_avoid_crossing_curled_overhangs;
|
||||
RetractWhenCrossingPerimeters m_retract_when_crossing_perimeters;
|
||||
|
122
src/libslic3r/GCode/LabelObjects.cpp
Normal file
122
src/libslic3r/GCode/LabelObjects.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
#include "LabelObjects.hpp"
|
||||
|
||||
|
||||
namespace Slic3r::GCode {
|
||||
|
||||
|
||||
|
||||
void LabelObjects::init(const Print& print)
|
||||
{
|
||||
m_label_objects_style = print.config().gcode_label_objects;
|
||||
m_flavor = print.config().gcode_flavor;
|
||||
|
||||
if (m_label_objects_style == LabelObjectsStyle::Disabled)
|
||||
return;
|
||||
|
||||
std::map<const ModelObject*, std::vector<const PrintInstance*>> model_object_to_print_instances;
|
||||
|
||||
// Iterate over all PrintObjects and their PrintInstances, collect PrintInstances which
|
||||
// belong to the same ModelObject.
|
||||
for (const PrintObject* po : print.objects())
|
||||
for (const PrintInstance& pi : po->instances())
|
||||
model_object_to_print_instances[pi.model_instance->get_object()].emplace_back(&pi);
|
||||
|
||||
// Now go through the map, assign a unique_id to each of the PrintInstances and get the indices of the
|
||||
// respective ModelObject and ModelInstance so we can use them in the tags. This will maintain
|
||||
// indices even in case that some instances are rotated (those end up in different PrintObjects)
|
||||
// or when some are out of bed (these ModelInstances have no corresponding PrintInstances).
|
||||
int unique_id = 0;
|
||||
for (const auto& [model_object, print_instances] : model_object_to_print_instances) {
|
||||
const ModelObjectPtrs& model_objects = model_object->get_model()->objects;
|
||||
int object_id = int(std::find(model_objects.begin(), model_objects.end(), model_object) - model_objects.begin());
|
||||
for (const PrintInstance* const pi : print_instances) {
|
||||
int instance_id = int(std::find(model_object->instances.begin(), model_object->instances.end(), pi->model_instance) - model_object->instances.begin());
|
||||
if (m_label_objects_style != LabelObjectsStyle::Octoprint) {
|
||||
// OctoPrint comments have always indexed instances from 0, let's keep it that way.
|
||||
// In the other cases, we will use one-based indexing so the indices match with the one in PrusaSlicer.
|
||||
++instance_id;
|
||||
}
|
||||
m_label_data.emplace(pi, LabelData{model_object->name, unique_id, object_id, instance_id, print_instances.size() > 1});
|
||||
++unique_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string LabelObjects::all_objects_header() const
|
||||
{
|
||||
if (m_label_objects_style == LabelObjectsStyle::Disabled)
|
||||
return std::string();
|
||||
|
||||
std::string out;
|
||||
|
||||
// Let's sort the values according to unique_id so they are in the same order in which they were added.
|
||||
std::vector<std::pair<const PrintInstance*, LabelData>> label_data_sorted;
|
||||
for (const auto& pi_and_label : m_label_data)
|
||||
label_data_sorted.emplace_back(pi_and_label);
|
||||
std::sort(label_data_sorted.begin(), label_data_sorted.end(), [](const auto& ld1, const auto& ld2) { return ld1.second.unique_id < ld2.second.unique_id; });
|
||||
|
||||
out += "\n";
|
||||
for (const auto& [print_instance, label] : label_data_sorted) {
|
||||
out += start_object(*print_instance, IncludeName::Yes);
|
||||
out += stop_object(*print_instance);
|
||||
}
|
||||
out += "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string LabelObjects::start_object(const PrintInstance& print_instance, IncludeName include_name) const
|
||||
{
|
||||
if (m_label_objects_style == LabelObjectsStyle::Disabled)
|
||||
return std::string();
|
||||
|
||||
const LabelData& label = m_label_data.at(&print_instance);
|
||||
|
||||
std::string name = label.name;
|
||||
if (m_label_objects_style == LabelObjectsStyle::Firmware && label.object_has_more_instances)
|
||||
name += " (copy " + std::to_string(label.instance_id) + ")";
|
||||
|
||||
std::string out;
|
||||
if (m_label_objects_style == LabelObjectsStyle::Octoprint)
|
||||
out += std::string("; printing object ") + name + " id:" + std::to_string(label.object_id) + " copy " + std::to_string(label.instance_id) + "\n";
|
||||
else if (m_label_objects_style == LabelObjectsStyle::Firmware) {
|
||||
if (m_flavor == GCodeFlavor::gcfMarlinFirmware || m_flavor == GCodeFlavor::gcfMarlinLegacy || m_flavor == GCodeFlavor::gcfRepRapFirmware) {
|
||||
out += std::string("M486 S") + std::to_string(label.unique_id) + "\n";
|
||||
if (include_name == IncludeName::Yes) {
|
||||
out += std::string("M486 A");
|
||||
out += (m_flavor == GCodeFlavor::gcfRepRapFirmware ? (std::string("\"") + name + "\"") : name) + "\n";
|
||||
}
|
||||
} else {
|
||||
// Not supported by / implemented for the other firmware flavors.
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string LabelObjects::stop_object(const PrintInstance& print_instance) const
|
||||
{
|
||||
if (m_label_objects_style == LabelObjectsStyle::Disabled)
|
||||
return std::string();
|
||||
|
||||
const LabelData& label = m_label_data.at(&print_instance);
|
||||
|
||||
std::string out;
|
||||
if (m_label_objects_style == LabelObjectsStyle::Octoprint)
|
||||
out += std::string("; stop printing object ") + label.name + " id:" + std::to_string(label.object_id) + " copy " + std::to_string(label.instance_id) + "\n";
|
||||
else if (m_label_objects_style == LabelObjectsStyle::Firmware)
|
||||
if (m_flavor == GCodeFlavor::gcfMarlinFirmware || m_flavor == GCodeFlavor::gcfMarlinLegacy || m_flavor == GCodeFlavor::gcfRepRapFirmware)
|
||||
out += std::string("M486 S-1\n");
|
||||
else {
|
||||
// Not supported by / implemented for the other firmware flavors.
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Slic3r::GCode
|
49
src/libslic3r/GCode/LabelObjects.hpp
Normal file
49
src/libslic3r/GCode/LabelObjects.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef slic3r_GCode_LabelObjects_hpp_
|
||||
#define slic3r_GCode_LabelObjects_hpp_
|
||||
|
||||
#include "Print.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum GCodeFlavor : unsigned char;
|
||||
enum class LabelObjectsStyle;
|
||||
|
||||
|
||||
namespace GCode {
|
||||
|
||||
//std::string label_object_start(LabelObjectsStyle label_object_style, GCodeFlavor flavor, const SpanOfConstPtrs<PrintObject>& objects, int object_id, int instance_id);
|
||||
//std::string label_object_stop(LabelObjectsStyle label_object_style, GCodeFlavor flavor, int object_id, int instance_id, const std::string& name);
|
||||
//std::string label_all_objects(LabelObjectsStyle label_objects_style, GCodeFlavor flavor, const Print& print);
|
||||
|
||||
|
||||
class LabelObjects {
|
||||
public:
|
||||
enum class IncludeName {
|
||||
No,
|
||||
Yes
|
||||
};
|
||||
void init(const Print& print);
|
||||
std::string all_objects_header() const;
|
||||
std::string start_object(const PrintInstance& print_instance, IncludeName include_name) const;
|
||||
std::string stop_object(const PrintInstance& print_instance) const;
|
||||
|
||||
private:
|
||||
struct LabelData {
|
||||
std::string name;
|
||||
int unique_id;
|
||||
int object_id;
|
||||
int instance_id;
|
||||
bool object_has_more_instances;
|
||||
};
|
||||
|
||||
LabelObjectsStyle m_label_objects_style;
|
||||
GCodeFlavor m_flavor;
|
||||
std::unordered_map<const PrintInstance*, LabelData> m_label_data;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace GCode
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_GCode_LabelObjects_hpp_
|
@ -229,12 +229,12 @@ static const t_config_enum_values s_keys_map_DraftShield = {
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(DraftShield)
|
||||
|
||||
static const t_config_enum_values s_keys_map_LabelObjects = {
|
||||
{ "disabled", int(LabelObjects::Disabled) },
|
||||
{ "octoprint", int(LabelObjects::Octoprint) },
|
||||
{ "firmware", int(LabelObjects::Firmware) }
|
||||
static const t_config_enum_values s_keys_map_LabelObjectsStyle = {
|
||||
{ "disabled", int(LabelObjectsStyle::Disabled) },
|
||||
{ "octoprint", int(LabelObjectsStyle::Octoprint) },
|
||||
{ "firmware", int(LabelObjectsStyle::Firmware) }
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(LabelObjects)
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(LabelObjectsStyle)
|
||||
|
||||
static const t_config_enum_values s_keys_map_GCodeThumbnailsFormat = {
|
||||
{ "PNG", int(GCodeThumbnailsFormat::PNG) },
|
||||
@ -1507,13 +1507,13 @@ void PrintConfigDef::init_fff_params()
|
||||
" Firmware = firmware specific G-code (it will be chosen based on firmware flavor and it can end up to be empty).\n\n"
|
||||
"This settings is NOT compatible with Single Extruder Multi Material setup and Wipe into Object / Wipe into Infill.");
|
||||
|
||||
def->set_enum<LabelObjects>({
|
||||
def->set_enum<LabelObjectsStyle>({
|
||||
{ "disabled", L("Disabled") },
|
||||
{ "octoprint", L("OctoPrint comments") },
|
||||
{ "firmware", L("Firmware-specific") }
|
||||
});
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<LabelObjects>(LabelObjects::Disabled));
|
||||
def->set_default_value(new ConfigOptionEnum<LabelObjectsStyle>(LabelObjectsStyle::Disabled));
|
||||
|
||||
def = this->add("gcode_substitutions", coStrings);
|
||||
def->label = L("G-code substitutions");
|
||||
|
@ -147,7 +147,7 @@ enum DraftShield {
|
||||
dsDisabled, dsLimited, dsEnabled
|
||||
};
|
||||
|
||||
enum class LabelObjects {
|
||||
enum class LabelObjectsStyle {
|
||||
Disabled, Octoprint, Firmware
|
||||
};
|
||||
|
||||
@ -187,7 +187,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLAPillarConnectionMode)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLASupportTreeType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BrimType)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(LabelObjects)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(LabelObjectsStyle)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeThumbnailsFormat)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule)
|
||||
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PerimeterGeneratorType)
|
||||
@ -734,7 +734,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloats, filament_multitool_ramming_flow))
|
||||
((ConfigOptionBool, gcode_comments))
|
||||
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
|
||||
((ConfigOptionEnum<LabelObjects>, gcode_label_objects))
|
||||
((ConfigOptionEnum<LabelObjectsStyle>, gcode_label_objects))
|
||||
// Triples of strings: "search pattern", "replace with pattern", "attribs"
|
||||
// where "attribs" are one of:
|
||||
// r - regular expression
|
||||
|
Loading…
x
Reference in New Issue
Block a user