Make LabelObjects hold state.

* This enables setting the object flags anywhere in gcode.
* The flags are then set in such a way that cancel object behaves as expected.
This commit is contained in:
Martin Šach 2024-02-21 17:56:55 +01:00 committed by Lukas Matena
parent 58e32e173b
commit fdbe119658
5 changed files with 96 additions and 40 deletions

View File

@ -576,7 +576,6 @@ GCodeGenerator::GCodeGenerator(const Print* print) :
m_brim_done(false),
m_second_layer_things_done(false),
m_silent_time_estimator_enabled(false),
m_current_instance({nullptr, -1}),
m_print(print)
{}
@ -1248,7 +1247,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
m_avoid_crossing_perimeters.use_external_mp_once();
file.write(this->retract_and_wipe());
file.write(this->travel_to(*this->last_position, Point(0, 0), ExtrusionRole::None, "move to origin position for next object"));
file.write(this->travel_to(*this->last_position, Point(0, 0), ExtrusionRole::None, "move to origin position for next object", ""));
m_enable_cooling_markers = true;
// Disable motion planner when traveling to first object point.
m_avoid_crossing_perimeters.disable_once();
@ -1333,6 +1332,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail
// and export G-code into file.
this->process_layers(print, tool_ordering, print_object_instances_ordering, layers_to_print,
smooth_path_cache_global, file);
file.write(m_label_objects.maybe_stop_instance());
if (m_wipe_tower)
// Purge the extruder, pull out the active filament.
file.write(m_wipe_tower->finalize(*this));
@ -2518,12 +2518,11 @@ void GCodeGenerator::process_layer_single_object(
m_avoid_crossing_perimeters.init_layer(*m_layer);
// When starting a new object, use the external motion planner for the first travel move.
const Point &offset = print_object.instances()[print_instance.instance_id].shift;
GCode::PrintObjectInstance next_instance = {&print_object, int(print_instance.instance_id)};
if (m_current_instance != next_instance)
const bool updated{m_label_objects.update(print_instance.print_object.instances()[print_instance.instance_id])};
if (updated)
m_avoid_crossing_perimeters.use_external_mp_once();
m_current_instance = next_instance;
this->set_origin(unscale(offset));
gcode += m_label_objects.start_object(print_instance.print_object.instances()[print_instance.instance_id], GCode::LabelObjects::IncludeName::No);
}
};
@ -2703,8 +2702,6 @@ void GCodeGenerator::process_layer_single_object(
}
}
}
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)
@ -3069,7 +3066,7 @@ void GCodeGenerator::GCodeOutputStream::write_format(const char* format, ...)
va_end(args);
}
std::string GCodeGenerator::travel_to_first_position(const Vec3crd& point, const double from_z) {
std::string GCodeGenerator::travel_to_first_position(const Vec3crd& point, const double from_z, const std::string& gcode_to_insert) {
std::string gcode;
const Vec3d gcode_point = to_3d(this->point_to_gcode(point.head<2>()), unscaled(point.z()));
@ -3093,6 +3090,8 @@ std::string GCodeGenerator::travel_to_first_position(const Vec3crd& point, const
this->last_position = point.head<2>();
this->writer().update_position(gcode_point);
gcode += gcode_to_insert;
std::string comment{"move to first layer point"};
gcode += this->writer().get_travel_to_xy_gcode(gcode_point.head<2>(), comment);
gcode += this->writer().get_travel_to_z_gcode(gcode_point.z(), comment);
@ -3126,13 +3125,14 @@ std::string GCodeGenerator::_extrude(
if (!m_current_layer_first_position) {
const Vec3crd point = to_3d(path.front().point, scaled(this->m_last_layer_z));
gcode += this->travel_to_first_position(point, unscaled(point.z()));
gcode += this->travel_to_first_position(point, unscaled(point.z()), this->m_label_objects.maybe_change_instance());
} else {
// go to first point of extrusion path
if (!this->last_position) {
const double z = this->m_last_layer_z;
const std::string comment{"move to print after unknown position"};
gcode += this->retract_and_wipe();
gcode += m_label_objects.maybe_change_instance();
gcode += this->m_writer.travel_to_xy(this->point_to_gcode(path.front().point), comment);
gcode += this->m_writer.get_travel_to_z_gcode(z, comment);
} else if ( this->last_position != path.front().point) {
@ -3140,7 +3140,7 @@ std::string GCodeGenerator::_extrude(
comment += description;
comment += description_bridge;
comment += " point";
const std::string travel_gcode{this->travel_to(*this->last_position, path.front().point, path_attr.role, comment)};
const std::string travel_gcode{this->travel_to(*this->last_position, path.front().point, path_attr.role, comment, this->m_label_objects.maybe_change_instance())};
gcode += travel_gcode;
}
}
@ -3366,7 +3366,8 @@ std::string GCodeGenerator::_extrude(
std::string GCodeGenerator::generate_travel_gcode(
const Points3& travel,
const std::string& comment
const std::string& comment,
const std::string& insert_before_end
) {
std::string gcode;
@ -3381,9 +3382,16 @@ std::string GCodeGenerator::generate_travel_gcode(
gcode += this->m_writer.set_travel_acceleration(acceleration);
Vec3d previous_point{this->point_to_gcode(travel.front())};
for (const Vec3crd& point : travel) {
bool already_inserted{false};
for (std::size_t i{0}; i < travel.size(); ++i) {
const Vec3crd& point{travel[i]};
const Vec3d gcode_point{this->point_to_gcode(point)};
if (travel.size() - i <= 2 && !already_inserted) {
gcode += insert_before_end;
already_inserted = true;
}
gcode += this->m_writer.travel_to_xyz(previous_point, gcode_point, comment);
this->last_position = point.head<2>();
previous_point = gcode_point;
@ -3479,7 +3487,11 @@ Polyline GCodeGenerator::generate_travel_xy_path(
// This method accepts &point in print coordinates.
std::string GCodeGenerator::travel_to(
const Point &start_point, const Point &end_point, ExtrusionRole role, const std::string &comment
const Point &start_point,
const Point &end_point,
ExtrusionRole role,
const std::string &comment,
const std::string &gcode_to_insert
) {
// check whether a straight travel move would need retraction
@ -3537,7 +3549,7 @@ std::string GCodeGenerator::travel_to(
)
);
return wipe_retract_gcode + generate_travel_gcode(travel, comment);
return wipe_retract_gcode + generate_travel_gcode(travel, comment, gcode_to_insert);
}
std::string GCodeGenerator::retract_and_wipe(bool toolchange)
@ -3592,6 +3604,8 @@ std::string GCodeGenerator::set_extruder(unsigned int extruder_id, double print_
// prepend retraction on the current extruder
std::string gcode = this->retract_and_wipe(true);
gcode += this->m_label_objects.maybe_stop_instance();
// Always reset the extrusion path, even if the tool change retract is set to zero.
m_wipe.reset_path();

View File

@ -319,7 +319,8 @@ private:
std::string extrude_support(const ExtrusionEntityReferences &support_fills, const GCode::SmoothPathCache &smooth_path_cache);
std::string generate_travel_gcode(
const Points3& travel,
const std::string& comment
const std::string& comment,
const std::string& insert_before_end
);
Polyline generate_travel_xy_path(
const Point& start,
@ -331,10 +332,11 @@ private:
const Point &start_point,
const Point &end_point,
ExtrusionRole role,
const std::string &comment
const std::string &comment,
const std::string &gcode_to_insert
);
std::string travel_to_first_position(const Vec3crd& point, const double from_z);
std::string travel_to_first_position(const Vec3crd& point, const double from_z, const std::string& gcode_to_insert);
bool needs_retraction(const Polyline &travel, ExtrusionRole role = ExtrusionRole::None);
@ -444,9 +446,6 @@ private:
bool m_second_layer_things_done;
// G-code that is due to be written before the next extrusion
std::string m_pending_pre_extrusion_gcode;
// Pointer to currently exporting PrintObject and instance index.
GCode::PrintObjectInstance m_current_instance;
bool m_silent_time_estimator_enabled;
// Processor

View File

@ -111,7 +111,37 @@ void LabelObjects::init(const SpanOfConstPtrs<PrintObject>& objects, LabelObject
}
}
bool LabelObjects::update(const PrintInstance &instance) {
if (this->last_operation_instance == &instance) {
return false;
}
this->last_operation_instance = &instance;
return true;
}
std::string LabelObjects::maybe_start_instance() {
if (current_instance == nullptr && last_operation_instance != nullptr) {
current_instance = last_operation_instance;
return this->start_object(*current_instance, LabelObjects::IncludeName::No);
}
return "";
}
std::string LabelObjects::maybe_stop_instance() {
if (current_instance != nullptr) {
const std::string result{this->stop_object(*current_instance)};
current_instance = nullptr;
return result;
}
return "";
}
std::string LabelObjects::maybe_change_instance() {
if (last_operation_instance != current_instance) {
return this->maybe_stop_instance() + this->maybe_start_instance();
}
return "";
}
std::string LabelObjects::all_objects_header() const
{

View File

@ -16,35 +16,46 @@ class Print;
namespace GCode {
class LabelObjects {
class LabelObjects
{
public:
void init(const SpanOfConstPtrs<PrintObject>& objects, LabelObjectsStyle label_object_style, GCodeFlavor gcode_flavor);
std::string all_objects_header() const;
std::string all_objects_header_singleline_json() const;
bool update(const PrintInstance &instance);
std::string maybe_start_instance();
std::string maybe_stop_instance();
std::string maybe_change_instance();
private:
struct LabelData
{
const PrintInstance* pi;
std::string name;
std::string center;
std::string polygon;
int unique_id;
};
enum class IncludeName {
No,
Yes
};
void init(const SpanOfConstPtrs<PrintObject>& objects, LabelObjectsStyle label_object_style, GCodeFlavor gcode_flavor);
std::string all_objects_header() const;
std::string all_objects_header_singleline_json() 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 {
const PrintInstance* pi;
std::string name;
std::string center;
std::string polygon;
int unique_id;
};
const PrintInstance* current_instance{nullptr};
const PrintInstance* last_operation_instance{nullptr};
LabelObjectsStyle m_label_objects_style;
GCodeFlavor m_flavor;
std::vector<LabelData> m_label_data;
};
} // namespace GCode
} // namespace Slic3r

View File

@ -64,15 +64,17 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip
if (gcodegen.m_current_layer_first_position) {
if (gcodegen.last_position) {
gcode += gcodegen.travel_to(
*gcodegen.last_position, xy_point, ExtrusionRole::Mixed, comment
*gcodegen.last_position, xy_point, ExtrusionRole::Mixed, comment,
gcodegen.m_label_objects.maybe_stop_instance()
);
} else {
gcode += gcodegen.m_label_objects.maybe_stop_instance();
gcode += gcodegen.writer().travel_to_xy(gcodegen.point_to_gcode(xy_point), comment);
gcode += gcodegen.writer().get_travel_to_z_gcode(z, comment);
}
} else {
const Vec3crd point = to_3d(xy_point, scaled(z));
gcode += gcodegen.travel_to_first_position(point, current_z);
gcode += gcodegen.travel_to_first_position(point, current_z, gcodegen.m_label_objects.maybe_stop_instance());
}
gcode += gcodegen.unretract();
} else {
@ -268,7 +270,7 @@ std::string WipeTowerIntegration::finalize(GCodeGenerator &gcodegen)
if (std::abs(gcodegen.writer().get_position().z() - m_final_purge.print_z) > EPSILON)
gcode += gcodegen.generate_travel_gcode(
{{gcodegen.last_position->x(), gcodegen.last_position->y(), scaled(m_final_purge.print_z)}},
"move to safe place for purging"
"move to safe place for purging", ""
);
gcode += append_tcr(gcodegen, m_final_purge, -1);
return gcode;