BambuStudio/libslic3r/GCode/GCodeProcessor.hpp

979 lines
37 KiB
C++

#ifndef slic3r_GCodeProcessor_hpp_
#define slic3r_GCodeProcessor_hpp_
#include "libslic3r/GCodeReader.hpp"
#include "libslic3r/Point.hpp"
#include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/PrintConfig.hpp"
#include "libslic3r/CustomGCode.hpp"
#include "libslic3r/Extruder.hpp"
#include <cstdint>
#include <array>
#include <vector>
#include <mutex>
#include <string>
#include <string_view>
#include <optional>
namespace Slic3r {
// slice warnings enum strings
#define NOZZLE_HRC_CHECKER "the_actual_nozzle_hrc_smaller_than_the_required_nozzle_hrc"
#define BED_TEMP_TOO_HIGH_THAN_FILAMENT "bed_temperature_too_high_than_filament"
#define NOT_SUPPORT_TRADITIONAL_TIMELAPSE "not_support_traditional_timelapse"
#define NOT_GENERATE_TIMELAPSE "not_generate_timelapse"
#define LONG_RETRACTION_WHEN_CUT "activate_long_retraction_when_cut"
enum class EMoveType : unsigned char
{
Noop,
Retract,
Unretract,
Seam,
Tool_change,
Color_change,
Pause_Print,
Custom_GCode,
Travel,
Wipe,
Extrude,
Count
};
struct PrintEstimatedStatistics
{
enum class ETimeMode : unsigned char
{
Normal,
Stealth,
Count
};
struct Mode
{
float time;
float prepare_time;
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> custom_gcode_times;
std::vector<std::pair<EMoveType, float>> moves_times;
std::vector<std::pair<ExtrusionRole, float>> roles_times;
std::vector<float> layers_times;
void reset() {
time = 0.0f;
prepare_time = 0.0f;
custom_gcode_times.clear();
custom_gcode_times.shrink_to_fit();
moves_times.clear();
moves_times.shrink_to_fit();
roles_times.clear();
roles_times.shrink_to_fit();
layers_times.clear();
layers_times.shrink_to_fit();
}
};
std::vector<double> volumes_per_color_change;
std::map<size_t, double> model_volumes_per_extruder;
std::map<size_t, double> wipe_tower_volumes_per_extruder;
std::map<size_t, double> support_volumes_per_extruder;
std::map<size_t, double> total_volumes_per_extruder;
//BBS: the flush amount of every filament
std::map<size_t, double> flush_per_filament;
std::map<ExtrusionRole, std::pair<double, double>> used_filaments_per_role;
std::array<Mode, static_cast<size_t>(ETimeMode::Count)> modes;
unsigned int total_filamentchanges;
PrintEstimatedStatistics() { reset(); }
void reset() {
for (auto m : modes) {
m.reset();
}
volumes_per_color_change.clear();
volumes_per_color_change.shrink_to_fit();
wipe_tower_volumes_per_extruder.clear();
model_volumes_per_extruder.clear();
support_volumes_per_extruder.clear();
total_volumes_per_extruder.clear();
flush_per_filament.clear();
used_filaments_per_role.clear();
total_filamentchanges = 0;
}
};
struct ConflictResult
{
std::string _objName1;
std::string _objName2;
float _height;
const void *_obj1; // nullptr means wipe tower
const void *_obj2;
int layer = -1;
ConflictResult(const std::string &objName1, const std::string &objName2, float height, const void *obj1, const void *obj2)
: _objName1(objName1), _objName2(objName2), _height(height), _obj1(obj1), _obj2(obj2)
{}
ConflictResult() = default;
};
struct BedMatchResult
{
bool match;
std::string bed_type_name;
int extruder_id;
BedMatchResult():match(true),bed_type_name(""),extruder_id(-1) {}
BedMatchResult(bool _match,const std::string& _bed_type_name="",int _extruder_id=-1)
:match(_match),bed_type_name(_bed_type_name),extruder_id(_extruder_id)
{}
};
using ConflictResultOpt = std::optional<ConflictResult>;
struct GCodeProcessorResult
{
ConflictResultOpt conflict_result;
BedMatchResult bed_match_result;
struct SettingsIds
{
std::string print;
std::vector<std::string> filament;
std::string printer;
void reset() {
print.clear();
filament.clear();
printer.clear();
}
};
struct MoveVertex
{
unsigned int gcode_id{ 0 };
EMoveType type{ EMoveType::Noop };
ExtrusionRole extrusion_role{ erNone };
unsigned char extruder_id{ 0 };
unsigned char cp_color_id{ 0 };
Vec3f position{ Vec3f::Zero() }; // mm
float delta_extruder{ 0.0f }; // mm
float feedrate{ 0.0f }; // mm/s
float width{ 0.0f }; // mm
float height{ 0.0f }; // mm
float mm3_per_mm{ 0.0f };
float fan_speed{ 0.0f }; // percentage
float temperature{ 0.0f }; // Celsius degrees
float time{ 0.0f }; // s
float layer_duration{ 0.0f }; // s (layer id before finalize)
//BBS: arc move related data
EMovePathType move_path_type{ EMovePathType::Noop_move };
Vec3f arc_center_position{ Vec3f::Zero() }; // mm
std::vector<Vec3f> interpolation_points; // interpolation points of arc for drawing
float volumetric_rate() const { return feedrate * mm3_per_mm; }
//BBS: new function to support arc move
bool is_arc_move_with_interpolation_points() const {
return (move_path_type == EMovePathType::Arc_move_ccw || move_path_type == EMovePathType::Arc_move_cw) && interpolation_points.size();
}
bool is_arc_move() const {
return move_path_type == EMovePathType::Arc_move_ccw || move_path_type == EMovePathType::Arc_move_cw;
}
};
struct SliceWarning {
int level; // 0: normal tips, 1: warning; 2: error
std::string msg; // enum string
std::string error_code; // error code for studio
std::vector<std::string> params; // extra msg info
};
std::string filename;
unsigned int id;
std::vector<MoveVertex> moves;
// Positions of ends of lines of the final G-code this->filename after TimeProcessor::post_process() finalizes the G-code.
std::vector<size_t> lines_ends;
Pointfs printable_area;
//BBS: add bed exclude area
Pointfs bed_exclude_area;
//BBS: add toolpath_outside
bool toolpath_outside;
//BBS: add object_label_enabled
bool label_object_enabled;
//BBS : extra retraction when change filament,experiment func
bool long_retraction_when_cut {0};
int timelapse_warning_code {0};
bool support_traditional_timelapse{true};
float printable_height;
SettingsIds settings_ids;
size_t extruders_count;
std::vector<std::string> extruder_colors;
std::vector<float> filament_diameters;
std::vector<int> required_nozzle_HRC;
std::vector<float> filament_densities;
std::vector<float> filament_costs;
std::vector<int> filament_vitrification_temperature;
PrintEstimatedStatistics print_statistics;
std::vector<CustomGCode::Item> custom_gcode_per_print_z;
std::vector<std::pair<float, std::pair<size_t, size_t>>> spiral_vase_layers;
//BBS
std::vector<SliceWarning> warnings;
NozzleType nozzle_type;
BedType bed_type = BedType::btCount;
#if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 };
#endif // ENABLE_GCODE_VIEWER_STATISTICS
void reset();
//BBS: add mutex for protection of gcode result
mutable std::mutex result_mutex;
GCodeProcessorResult& operator=(const GCodeProcessorResult &other)
{
filename = other.filename;
id = other.id;
moves = other.moves;
lines_ends = other.lines_ends;
printable_area = other.printable_area;
bed_exclude_area = other.bed_exclude_area;
toolpath_outside = other.toolpath_outside;
label_object_enabled = other.label_object_enabled;
long_retraction_when_cut = other.long_retraction_when_cut;
timelapse_warning_code = other.timelapse_warning_code;
printable_height = other.printable_height;
settings_ids = other.settings_ids;
extruders_count = other.extruders_count;
extruder_colors = other.extruder_colors;
filament_diameters = other.filament_diameters;
filament_densities = other.filament_densities;
filament_costs = other.filament_costs;
print_statistics = other.print_statistics;
custom_gcode_per_print_z = other.custom_gcode_per_print_z;
spiral_vase_layers = other.spiral_vase_layers;
warnings = other.warnings;
bed_type = other.bed_type;
bed_match_result = other.bed_match_result;
#if ENABLE_GCODE_VIEWER_STATISTICS
time = other.time;
#endif
return *this;
}
void lock() const { result_mutex.lock(); }
void unlock() const { result_mutex.unlock(); }
};
class GCodeProcessor
{
static const std::vector<std::string> Reserved_Tags;
static const std::string Flush_Start_Tag;
static const std::string Flush_End_Tag;
public:
enum class ETags : unsigned char
{
Role,
Wipe_Start,
Wipe_End,
Height,
Width,
Layer_Change,
Color_Change,
Pause_Print,
Custom_Code,
First_Line_M73_Placeholder,
Last_Line_M73_Placeholder,
Estimated_Printing_Time_Placeholder,
Total_Layer_Number_Placeholder,
Wipe_Tower_Start,
Wipe_Tower_End,
Used_Filament_Weight_Placeholder,
Used_Filament_Volume_Placeholder,
Used_Filament_Length_Placeholder
};
static const std::string& reserved_tag(ETags tag) { return Reserved_Tags[static_cast<unsigned char>(tag)]; }
// checks the given gcode for reserved tags and returns true when finding the 1st (which is returned into found_tag)
static bool contains_reserved_tag(const std::string& gcode, std::string& found_tag);
// checks the given gcode for reserved tags and returns true when finding any
// (the first max_count found tags are returned into found_tag)
static bool contains_reserved_tags(const std::string& gcode, unsigned int max_count, std::vector<std::string>& found_tag);
static int get_gcode_last_filament(const std::string &gcode_str);
static bool get_last_z_from_gcode(const std::string& gcode_str, double& z);
static const float Wipe_Width;
static const float Wipe_Height;
static bool s_IsBBLPrinter;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
static const std::string Mm3_Per_Mm_Tag;
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
private:
using AxisCoords = std::array<double, 4>;
using ExtruderColors = std::vector<unsigned char>;
using ExtruderTemps = std::vector<float>;
enum class EUnits : unsigned char
{
Millimeters,
Inches
};
enum class EPositioningType : unsigned char
{
Absolute,
Relative
};
struct CachedPosition
{
AxisCoords position; // mm
float feedrate; // mm/s
void reset();
};
struct CpColor
{
unsigned char counter;
unsigned char current;
void reset();
};
public:
struct FeedrateProfile
{
float entry{ 0.0f }; // mm/s
float cruise{ 0.0f }; // mm/s
float exit{ 0.0f }; // mm/s
};
struct Trapezoid
{
float accelerate_until{ 0.0f }; // mm
float decelerate_after{ 0.0f }; // mm
float cruise_feedrate{ 0.0f }; // mm/sec
float acceleration_time(float entry_feedrate, float acceleration) const;
float cruise_time() const;
float deceleration_time(float distance, float acceleration) const;
float cruise_distance() const;
};
struct TimeBlock
{
struct Flags
{
bool recalculate{ false };
bool nominal_length{ false };
bool prepare_stage{ false };
};
EMoveType move_type{ EMoveType::Noop };
ExtrusionRole role{ erNone };
unsigned int g1_line_id{ 0 };
unsigned int layer_id{ 0 };
float distance{ 0.0f }; // mm
float acceleration{ 0.0f }; // mm/s^2
float max_entry_speed{ 0.0f }; // mm/s
float safe_feedrate{ 0.0f }; // mm/s
Flags flags;
FeedrateProfile feedrate_profile;
Trapezoid trapezoid;
// Calculates this block's trapezoid
void calculate_trapezoid();
float time() const;
};
private:
struct TimeMachine
{
struct State
{
float feedrate; // mm/s
float safe_feedrate; // mm/s
//BBS: feedrate of X-Y-Z-E axis. But when the move is G2 and G3, X-Y will be
//same value which means feedrate in X-Y plane.
AxisCoords axis_feedrate; // mm/s
AxisCoords abs_axis_feedrate; // mm/s
//BBS: unit vector of enter speed and exit speed in x-y-z space.
//For line move, there are same. For arc move, there are different.
Vec3f enter_direction;
Vec3f exit_direction;
void reset();
};
struct CustomGCodeTime
{
bool needed;
float cache;
std::vector<std::pair<CustomGCode::Type, float>> times;
void reset();
};
struct G1LinesCacheItem
{
unsigned int id;
float elapsed_time;
};
bool enabled;
float acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp.
float max_acceleration; // mm/s^2
float retract_acceleration; // mm/s^2
// hard limit for the acceleration, to which the firmware will clamp.
float max_retract_acceleration; // mm/s^2
float travel_acceleration; // mm/s^2
// hard limit for the travel acceleration, to which the firmware will clamp.
float max_travel_acceleration; // mm/s^2
float extrude_factor_override_percentage;
float time; // s
struct StopTime
{
unsigned int g1_line_id;
float elapsed_time;
};
std::vector<StopTime> stop_times;
std::string line_m73_main_mask;
std::string line_m73_stop_mask;
State curr;
State prev;
CustomGCodeTime gcode_time;
std::vector<TimeBlock> blocks;
std::vector<G1LinesCacheItem> g1_times_cache;
std::array<float, static_cast<size_t>(EMoveType::Count)> moves_time;
std::array<float, static_cast<size_t>(ExtrusionRole::erCount)> roles_time;
std::vector<float> layers_time;
//BBS: prepare stage time before print model, including start gcode time and mostly same with start gcode time
float prepare_time;
void reset();
// Simulates firmware st_synchronize() call
void simulate_st_synchronize(float additional_time = 0.0f);
void calculate_time(size_t keep_last_n_blocks = 0, float additional_time = 0.0f);
};
struct UsedFilaments // filaments per ColorChange
{
double color_change_cache;
std::vector<double> volumes_per_color_change;
double model_extrude_cache;
std::map<size_t, double> model_volumes_per_extruder;
double wipe_tower_cache;
std::map<size_t, double>wipe_tower_volumes_per_extruder;
double support_volume_cache;
std::map<size_t, double>support_volumes_per_extruder;
//BBS: the flush amount of every filament
std::map<size_t, double> flush_per_filament;
double total_volume_cache;
std::map<size_t, double>total_volumes_per_extruder;
double role_cache;
std::map<ExtrusionRole, std::pair<double, double>> filaments_per_role;
void reset();
void increase_support_caches(double extruded_volume);
void increase_model_caches(double extruded_volume);
void increase_wipe_tower_caches(double extruded_volume);
void process_color_change_cache();
void process_model_cache(GCodeProcessor* processor);
void process_wipe_tower_cache(GCodeProcessor* processor);
void process_support_cache(GCodeProcessor* processor);
void process_total_volume_cache(GCodeProcessor* processor);
void update_flush_per_filament(size_t extrude_id, float flush_length);
void process_role_cache(GCodeProcessor* processor);
void process_caches(GCodeProcessor* processor);
friend class GCodeProcessor;
};
struct TimeProcessContext
{
size_t total_layer_num;
std::vector<Extruder> filament_lists;
UsedFilaments used_filaments;
TimeProcessContext( size_t total_layer_num_,
const std::vector<Extruder>& filament_lists_,
const UsedFilaments& used_filaments_)
:total_layer_num(total_layer_num_), filament_lists(filament_lists_), used_filaments(used_filaments_) {}
};
struct TimeProcessor
{
struct Planner
{
// Size of the firmware planner queue. The old 8-bit Marlins usually just managed 16 trapezoidal blocks.
// Let's be conservative and plan for newer boards with more memory.
static constexpr size_t queue_size = 64;
// The firmware recalculates last planner_queue_size trapezoidal blocks each time a new block is added.
// We are not simulating the firmware exactly, we calculate a sequence of blocks once a reasonable number of blocks accumulate.
static constexpr size_t refresh_threshold = queue_size * 4;
};
// extruder_id is currently used to correctly calculate filament load / unload times into the total print time.
// This is currently only really used by the MK3 MMU2:
// extruder_unloaded = true means no filament is loaded yet, all the filaments are parked in the MK3 MMU2 unit.
bool extruder_unloaded;
// allow to skip the lines M201/M203/M204/M205 generated by GCode::print_machine_envelope() for non-Normal time estimate mode
bool machine_envelope_processing_enabled;
MachineEnvelopeConfig machine_limits;
// Additional load / unload times for a filament exchange sequence.
float filament_load_times;
float filament_unload_times;
std::array<TimeMachine, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> machines;
void reset();
// post process the file with the given filename to add remaining time lines M73
// and updates moves' gcode ids accordingly
void post_process(const std::string& filename, std::vector<GCodeProcessorResult::MoveVertex>& moves, std::vector<size_t>& lines_ends, const TimeProcessContext& context);
};
public:
class SeamsDetector
{
bool m_active{ false };
std::optional<Vec3f> m_first_vertex;
public:
void activate(bool active) {
if (m_active != active) {
m_active = active;
if (m_active)
m_first_vertex.reset();
}
}
std::optional<Vec3f> get_first_vertex() const { return m_first_vertex; }
void set_first_vertex(const Vec3f& vertex) { m_first_vertex = vertex; }
bool is_active() const { return m_active; }
bool has_first_vertex() const { return m_first_vertex.has_value(); }
};
// Helper class used to fix the z for color change, pause print and
// custom gcode markes
class OptionsZCorrector
{
GCodeProcessorResult& m_result;
std::optional<size_t> m_move_id;
std::optional<size_t> m_custom_gcode_per_print_z_id;
public:
explicit OptionsZCorrector(GCodeProcessorResult& result) : m_result(result) {
}
void set() {
m_move_id = m_result.moves.size() - 1;
m_custom_gcode_per_print_z_id = m_result.custom_gcode_per_print_z.size() - 1;
}
void update(float height) {
if (!m_move_id.has_value() || !m_custom_gcode_per_print_z_id.has_value())
return;
const Vec3f position = m_result.moves.back().position;
GCodeProcessorResult::MoveVertex& move = m_result.moves.emplace_back(m_result.moves[*m_move_id]);
move.position = position;
move.height = height;
m_result.moves.erase(m_result.moves.begin() + *m_move_id);
m_result.custom_gcode_per_print_z[*m_custom_gcode_per_print_z_id].print_z = position.z();
reset();
}
void reset() {
m_move_id.reset();
m_custom_gcode_per_print_z_id.reset();
}
};
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
struct DataChecker
{
struct Error
{
float value;
float tag_value;
ExtrusionRole role;
};
std::string type;
float threshold{ 0.01f };
float last_tag_value{ 0.0f };
unsigned int count{ 0 };
std::vector<Error> errors;
DataChecker(const std::string& type, float threshold)
: type(type), threshold(threshold)
{}
void update(float value, ExtrusionRole role) {
if (role != erCustom) {
++count;
if (last_tag_value != 0.0f) {
if (std::abs(value - last_tag_value) / last_tag_value > threshold)
errors.push_back({ value, last_tag_value, role });
}
}
}
void reset() { last_tag_value = 0.0f; errors.clear(); count = 0; }
std::pair<float, float> get_min() const {
float delta_min = FLT_MAX;
float perc_min = 0.0f;
for (const Error& e : errors) {
if (delta_min > e.value - e.tag_value) {
delta_min = e.value - e.tag_value;
perc_min = 100.0f * delta_min / e.tag_value;
}
}
return { delta_min, perc_min };
}
std::pair<float, float> get_max() const {
float delta_max = -FLT_MAX;
float perc_max = 0.0f;
for (const Error& e : errors) {
if (delta_max < e.value - e.tag_value) {
delta_max = e.value - e.tag_value;
perc_max = 100.0f * delta_max / e.tag_value;
}
}
return { delta_max, perc_max };
}
void output() const {
if (!errors.empty()) {
std::cout << type << ":\n";
std::cout << "Errors: " << errors.size() << " (" << 100.0f * float(errors.size()) / float(count) << "%)\n";
auto [min, perc_min] = get_min();
auto [max, perc_max] = get_max();
std::cout << "min: " << min << "(" << perc_min << "%) - max: " << max << "(" << perc_max << "%)\n";
}
}
};
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
private:
GCodeReader m_parser;
EUnits m_units;
EPositioningType m_global_positioning_type;
EPositioningType m_e_local_positioning_type;
std::vector<Vec3f> m_extruder_offsets;
GCodeFlavor m_flavor;
float m_nozzle_volume;
AxisCoords m_start_position; // mm
AxisCoords m_end_position; // mm
AxisCoords m_origin; // mm
CachedPosition m_cached_position;
bool m_wiping;
bool m_flushing;
bool m_wipe_tower;
float m_remaining_volume;
std::vector<Extruder> m_filament_lists;
//BBS: x, y offset for gcode generated
double m_x_offset{ 0 };
double m_y_offset{ 0 };
//BBS: arc move related data
EMovePathType m_move_path_type{ EMovePathType::Noop_move };
Vec3f m_arc_center{ Vec3f::Zero() }; // mm
std::vector<Vec3f> m_interpolation_points;
unsigned int m_line_id;
unsigned int m_last_line_id;
float m_feedrate; // mm/s
float m_width; // mm
float m_height; // mm
float m_forced_width; // mm
float m_forced_height; // mm
float m_mm3_per_mm;
float m_fan_speed; // percentage
ExtrusionRole m_extrusion_role;
unsigned char m_extruder_id;
unsigned char m_last_extruder_id;
ExtruderColors m_extruder_colors;
ExtruderTemps m_extruder_temps;
int m_highest_bed_temp;
float m_extruded_last_z;
float m_first_layer_height; // mm
float m_zero_layer_height; // mm
bool m_processing_start_custom_gcode;
unsigned int m_g1_line_id;
unsigned int m_layer_id;
CpColor m_cp_color;
SeamsDetector m_seams_detector;
OptionsZCorrector m_options_z_corrector;
size_t m_last_default_color_id;
bool m_detect_layer_based_on_tag {false};
int m_seams_count;
#if ENABLE_GCODE_VIEWER_STATISTICS
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
enum class EProducer
{
Unknown,
BambuStudio,
Slic3rPE,
Slic3r,
SuperSlicer,
Cura,
Simplify3D,
CraftWare,
ideaMaker,
KissSlicer
};
static const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> Producers;
EProducer m_producer;
TimeProcessor m_time_processor;
UsedFilaments m_used_filaments;
GCodeProcessorResult m_result;
static unsigned int s_result_id;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
DataChecker m_mm3_per_mm_compare{ "mm3_per_mm", 0.01f };
DataChecker m_height_compare{ "height", 0.01f };
DataChecker m_width_compare{ "width", 0.01f };
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
public:
GCodeProcessor();
void apply_config(const PrintConfig& config);
void set_filaments(const std::vector<Extruder>&filament_lists) { m_filament_lists=filament_lists;}
void enable_stealth_time_estimator(bool enabled);
bool is_stealth_time_estimator_enabled() const {
return m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled;
}
void enable_machine_envelope_processing(bool enabled) { m_time_processor.machine_envelope_processing_enabled = enabled; }
void reset();
const GCodeProcessorResult& get_result() const { return m_result; }
GCodeProcessorResult& result() { return m_result; }
GCodeProcessorResult&& extract_result() { return std::move(m_result); }
// Load a G-code into a stand-alone G-code viewer.
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
void process_file(const std::string& filename, std::function<void()> cancel_callback = nullptr);
// Streaming interface, for processing G-codes just generated by PrusaSlicer in a pipelined fashion.
void initialize(const std::string& filename);
void process_buffer(const std::string& buffer);
void finalize(bool post_process);
float get_time(PrintEstimatedStatistics::ETimeMode mode) const;
float get_prepare_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::string get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const;
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const;
std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::vector<std::pair<ExtrusionRole, float>> get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::vector<float> get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const;
//BBS: set offset for gcode writer
void set_xy_offset(double x, double y) { m_x_offset = x; m_y_offset = y; }
// Orca: if true, only change new layer if ETags::Layer_Change occurs
// otherwise when we got a lift of z during extrusion, a new layer will be added
void detect_layer_based_on_tag(bool enabled) {
m_detect_layer_based_on_tag = enabled;
}
private:
void apply_config(const DynamicPrintConfig& config);
void apply_config_simplify3d(const std::string& filename);
void apply_config_superslicer(const std::string& filename);
void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled);
// Process tags embedded into comments
void process_tags(const std::string_view comment, bool producers_enabled);
bool process_producers_tags(const std::string_view comment);
bool process_bambuslicer_tags(const std::string_view comment);
bool process_cura_tags(const std::string_view comment);
bool process_simplify3d_tags(const std::string_view comment);
bool process_craftware_tags(const std::string_view comment);
bool process_ideamaker_tags(const std::string_view comment);
bool process_kissslicer_tags(const std::string_view comment);
bool detect_producer(const std::string_view comment);
// Move
void process_G0(const GCodeReader::GCodeLine& line);
void process_G1(const GCodeReader::GCodeLine& line);
void process_G2_G3(const GCodeReader::GCodeLine& line);
// BBS: handle delay command
void process_G4(const GCodeReader::GCodeLine& line);
// Retract
void process_G10(const GCodeReader::GCodeLine& line);
// Unretract
void process_G11(const GCodeReader::GCodeLine& line);
// Set Units to Inches
void process_G20(const GCodeReader::GCodeLine& line);
// Set Units to Millimeters
void process_G21(const GCodeReader::GCodeLine& line);
// Firmware controlled Retract
void process_G22(const GCodeReader::GCodeLine& line);
// Firmware controlled Unretract
void process_G23(const GCodeReader::GCodeLine& line);
// Move to origin
void process_G28(const GCodeReader::GCodeLine& line);
// BBS
void process_G29(const GCodeReader::GCodeLine& line);
// Set to Absolute Positioning
void process_G90(const GCodeReader::GCodeLine& line);
// Set to Relative Positioning
void process_G91(const GCodeReader::GCodeLine& line);
// Set Position
void process_G92(const GCodeReader::GCodeLine& line);
// Sleep or Conditional stop
void process_M1(const GCodeReader::GCodeLine& line);
// Set extruder to absolute mode
void process_M82(const GCodeReader::GCodeLine& line);
// Set extruder to relative mode
void process_M83(const GCodeReader::GCodeLine& line);
// Set extruder temperature
void process_M104(const GCodeReader::GCodeLine& line);
// Set fan speed
void process_M106(const GCodeReader::GCodeLine& line);
// Disable fan
void process_M107(const GCodeReader::GCodeLine& line);
// Set tool (Sailfish)
void process_M108(const GCodeReader::GCodeLine& line);
// Set extruder temperature and wait
void process_M109(const GCodeReader::GCodeLine& line);
// Recall stored home offsets
void process_M132(const GCodeReader::GCodeLine& line);
// Set tool (MakerWare)
void process_M135(const GCodeReader::GCodeLine& line);
//BBS: Set bed temperature
void process_M140(const GCodeReader::GCodeLine& line);
//BBS: wait bed temperature
void process_M190(const GCodeReader::GCodeLine& line);
//BBS: wait chamber temperature
void process_M191(const GCodeReader::GCodeLine& line);
// Set max printing acceleration
void process_M201(const GCodeReader::GCodeLine& line);
// Set maximum feedrate
void process_M203(const GCodeReader::GCodeLine& line);
// Set default acceleration
void process_M204(const GCodeReader::GCodeLine& line);
// Advanced settings
void process_M205(const GCodeReader::GCodeLine& line);
// Klipper SET_VELOCITY_LIMIT
void process_SET_VELOCITY_LIMIT(const GCodeReader::GCodeLine& line);
// Set extrude factor override percentage
void process_M221(const GCodeReader::GCodeLine& line);
// BBS: handle delay command. M400 is defined by BBL only
void process_M400(const GCodeReader::GCodeLine& line);
// Repetier: Store x, y and z position
void process_M401(const GCodeReader::GCodeLine& line);
// Repetier: Go to stored position
void process_M402(const GCodeReader::GCodeLine& line);
// Set allowable instantaneous speed change
void process_M566(const GCodeReader::GCodeLine& line);
// Unload the current filament into the MK3 MMU2 unit at the end of print.
void process_M702(const GCodeReader::GCodeLine& line);
// Processes T line (Select Tool)
void process_T(const GCodeReader::GCodeLine& line);
void process_T(const std::string_view command);
//BBS: different path_type is only used for arc move
void store_move_vertex(EMoveType type, EMovePathType path_type = EMovePathType::Noop_move);
void set_extrusion_role(ExtrusionRole role);
float minimum_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;
float minimum_travel_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;
float get_axis_max_feedrate(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
float get_axis_max_acceleration(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
float get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
Vec3f get_xyz_max_jerk(PrintEstimatedStatistics::ETimeMode mode) const;
float get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
void set_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
float get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
void set_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
float get_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
void set_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
float get_filament_load_time(size_t extruder_id);
float get_filament_unload_time(size_t extruder_id);
int get_filament_vitrification_temperature(size_t extrude_id);
void process_custom_gcode_time(CustomGCode::Type code);
void process_filaments(CustomGCode::Type code);
// Simulates firmware st_synchronize() call
void simulate_st_synchronize(float additional_time = 0.0f);
void update_estimated_times_stats();
//BBS:
void update_slice_warnings();
};
} /* namespace Slic3r */
#endif /* slic3r_GCodeProcessor_hpp_ */