WIP: G-code find / replace using a new gcode_substitutions PrintConfig
parameter.
This commit is contained in:
parent
c54b8908dd
commit
658f01b64b
@ -98,6 +98,8 @@ add_library(libslic3r STATIC
|
|||||||
GCode/ThumbnailData.hpp
|
GCode/ThumbnailData.hpp
|
||||||
GCode/CoolingBuffer.cpp
|
GCode/CoolingBuffer.cpp
|
||||||
GCode/CoolingBuffer.hpp
|
GCode/CoolingBuffer.hpp
|
||||||
|
GCode/FindReplace.cpp
|
||||||
|
GCode/FindReplace.hpp
|
||||||
GCode/PostProcessor.cpp
|
GCode/PostProcessor.cpp
|
||||||
GCode/PostProcessor.hpp
|
GCode/PostProcessor.hpp
|
||||||
# GCode/PressureEqualizer.cpp
|
# GCode/PressureEqualizer.cpp
|
||||||
|
@ -1155,6 +1155,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||||||
m_enable_extrusion_role_markers = false;
|
m_enable_extrusion_role_markers = false;
|
||||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||||
|
|
||||||
|
if (! print.config().gcode_substitutions.values.empty())
|
||||||
|
m_find_replace = make_unique<GCodeFindReplace>(print.config());
|
||||||
|
|
||||||
// Write information on the generator.
|
// Write information on the generator.
|
||||||
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
||||||
|
|
||||||
@ -1560,13 +1563,21 @@ void GCode::process_layers(
|
|||||||
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in) -> std::string {
|
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in) -> std::string {
|
||||||
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
|
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
|
||||||
});
|
});
|
||||||
|
const auto find_replace = tbb::make_filter<std::string, std::string>(slic3r_tbb_filtermode::serial_in_order,
|
||||||
|
[&self = *this->m_find_replace.get()](std::string s) -> std::string {
|
||||||
|
return self.process_layer(std::move(s));
|
||||||
|
});
|
||||||
const auto output = tbb::make_filter<std::string, void>(slic3r_tbb_filtermode::serial_in_order,
|
const auto output = tbb::make_filter<std::string, void>(slic3r_tbb_filtermode::serial_in_order,
|
||||||
[&output_stream](std::string s) { output_stream.write(s); }
|
[&output_stream](std::string s) { output_stream.write(s); }
|
||||||
);
|
);
|
||||||
|
|
||||||
// The pipeline elements are joined using const references, thus no copying is performed.
|
// The pipeline elements are joined using const references, thus no copying is performed.
|
||||||
if (m_spiral_vase)
|
if (m_spiral_vase && m_find_replace)
|
||||||
|
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & find_replace & output);
|
||||||
|
else if (m_spiral_vase)
|
||||||
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & output);
|
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & output);
|
||||||
|
else if (m_find_replace)
|
||||||
|
tbb::parallel_pipeline(12, generator & cooling & find_replace & output);
|
||||||
else
|
else
|
||||||
tbb::parallel_pipeline(12, generator & cooling & output);
|
tbb::parallel_pipeline(12, generator & cooling & output);
|
||||||
}
|
}
|
||||||
@ -1603,13 +1614,21 @@ void GCode::process_layers(
|
|||||||
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in)->std::string {
|
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in)->std::string {
|
||||||
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
|
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
|
||||||
});
|
});
|
||||||
|
const auto find_replace = tbb::make_filter<std::string, std::string>(slic3r_tbb_filtermode::serial_in_order,
|
||||||
|
[&self = *this->m_find_replace.get()](std::string s) -> std::string {
|
||||||
|
return self.process_layer(std::move(s));
|
||||||
|
});
|
||||||
const auto output = tbb::make_filter<std::string, void>(slic3r_tbb_filtermode::serial_in_order,
|
const auto output = tbb::make_filter<std::string, void>(slic3r_tbb_filtermode::serial_in_order,
|
||||||
[&output_stream](std::string s) { output_stream.write(s); }
|
[&output_stream](std::string s) { output_stream.write(s); }
|
||||||
);
|
);
|
||||||
|
|
||||||
// The pipeline elements are joined using const references, thus no copying is performed.
|
// The pipeline elements are joined using const references, thus no copying is performed.
|
||||||
if (m_spiral_vase)
|
if (m_spiral_vase && m_find_replace)
|
||||||
|
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & find_replace & output);
|
||||||
|
else if (m_spiral_vase)
|
||||||
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & output);
|
tbb::parallel_pipeline(12, generator & spiral_vase & cooling & output);
|
||||||
|
else if (m_find_replace)
|
||||||
|
tbb::parallel_pipeline(12, generator & cooling & find_replace & output);
|
||||||
else
|
else
|
||||||
tbb::parallel_pipeline(12, generator & cooling & output);
|
tbb::parallel_pipeline(12, generator & cooling & output);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "PrintConfig.hpp"
|
#include "PrintConfig.hpp"
|
||||||
#include "GCode/AvoidCrossingPerimeters.hpp"
|
#include "GCode/AvoidCrossingPerimeters.hpp"
|
||||||
#include "GCode/CoolingBuffer.hpp"
|
#include "GCode/CoolingBuffer.hpp"
|
||||||
|
#include "GCode/FindReplace.hpp"
|
||||||
#include "GCode/SpiralVase.hpp"
|
#include "GCode/SpiralVase.hpp"
|
||||||
#include "GCode/ToolOrdering.hpp"
|
#include "GCode/ToolOrdering.hpp"
|
||||||
#include "GCode/WipeTower.hpp"
|
#include "GCode/WipeTower.hpp"
|
||||||
@ -393,6 +394,7 @@ private:
|
|||||||
|
|
||||||
std::unique_ptr<CoolingBuffer> m_cooling_buffer;
|
std::unique_ptr<CoolingBuffer> m_cooling_buffer;
|
||||||
std::unique_ptr<SpiralVase> m_spiral_vase;
|
std::unique_ptr<SpiralVase> m_spiral_vase;
|
||||||
|
std::unique_ptr<GCodeFindReplace> m_find_replace;
|
||||||
#ifdef HAS_PRESSURE_EQUALIZER
|
#ifdef HAS_PRESSURE_EQUALIZER
|
||||||
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
|
std::unique_ptr<PressureEqualizer> m_pressure_equalizer;
|
||||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||||
|
71
src/libslic3r/GCode/FindReplace.cpp
Normal file
71
src/libslic3r/GCode/FindReplace.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "FindReplace.hpp"
|
||||||
|
#include "../Utils.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
GCodeFindReplace::GCodeFindReplace(const PrintConfig &print_config)
|
||||||
|
{
|
||||||
|
const std::vector<std::string> &subst = print_config.gcode_substitutions.values;
|
||||||
|
|
||||||
|
if ((subst.size() % 3) != 0)
|
||||||
|
throw RuntimeError("Invalid length of gcode_substitutions parameter");
|
||||||
|
|
||||||
|
m_substitutions.reserve(subst.size() / 3);
|
||||||
|
for (size_t i = 0; i < subst.size(); i += 3) {
|
||||||
|
boost::regex pattern;
|
||||||
|
try {
|
||||||
|
pattern.assign(subst[i]);
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
throw RuntimeError(std::string("Invalid gcode_substitutions parameter, failed to compile regular expression: ") + ex.what());
|
||||||
|
}
|
||||||
|
m_substitutions.push_back({ std::move(pattern), subst[i + 1] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ToStringIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using iterator_category = std::output_iterator_tag;
|
||||||
|
using value_type = void;
|
||||||
|
using difference_type = void;
|
||||||
|
using pointer = void;
|
||||||
|
using reference = void;
|
||||||
|
|
||||||
|
ToStringIterator(std::string &data) : m_data(&data) {}
|
||||||
|
|
||||||
|
ToStringIterator& operator=(const char val) {
|
||||||
|
size_t needs = m_data->size() + 1;
|
||||||
|
if (m_data->capacity() < needs)
|
||||||
|
m_data->reserve(next_highest_power_of_2(needs));
|
||||||
|
m_data->push_back(val);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ToStringIterator& operator*() { return *this; }
|
||||||
|
ToStringIterator& operator++() { return *this; }
|
||||||
|
ToStringIterator operator++(int) { return *this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string *m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string GCodeFindReplace::process_layer(const std::string &ain)
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
const std::string *in = &ain;
|
||||||
|
std::string temp;
|
||||||
|
temp.reserve(in->size());
|
||||||
|
|
||||||
|
for (const Substitution &substitution : m_substitutions) {
|
||||||
|
temp.clear();
|
||||||
|
temp.reserve(in->size());
|
||||||
|
boost::regex_replace(ToStringIterator(temp), in->begin(), in->end(),
|
||||||
|
substitution.pattern, substitution.format, boost::match_default | boost::format_all);
|
||||||
|
std::swap(out, temp);
|
||||||
|
in = &out;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/libslic3r/GCode/FindReplace.hpp
Normal file
26
src/libslic3r/GCode/FindReplace.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef slic3r_FindReplace_hpp_
|
||||||
|
#define slic3r_FindReplace_hpp_
|
||||||
|
|
||||||
|
#include "../PrintConfig.hpp"
|
||||||
|
|
||||||
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class GCodeFindReplace {
|
||||||
|
public:
|
||||||
|
GCodeFindReplace(const PrintConfig &print_config);
|
||||||
|
|
||||||
|
std::string process_layer(const std::string &gcode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Substitution {
|
||||||
|
boost::regex pattern;
|
||||||
|
std::string format;
|
||||||
|
};
|
||||||
|
std::vector<Substitution> m_substitutions;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // slic3r_FindReplace_hpp_
|
@ -1357,6 +1357,12 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionBool(0));
|
def->set_default_value(new ConfigOptionBool(0));
|
||||||
|
|
||||||
|
def = this->add("gcode_substitutions", coStrings);
|
||||||
|
def->label = L("G-code substitutions");
|
||||||
|
def->tooltip = L("Find / replace patterns in G-code lines and substitute them.");
|
||||||
|
def->mode = comExpert;
|
||||||
|
def->set_default_value(new ConfigOptionStrings());
|
||||||
|
|
||||||
def = this->add("high_current_on_filament_swap", coBool);
|
def = this->add("high_current_on_filament_swap", coBool);
|
||||||
def->label = L("High extruder current on filament swap");
|
def->label = L("High extruder current on filament swap");
|
||||||
def->tooltip = L("It may be beneficial to increase the extruder motor current during the filament exchange"
|
def->tooltip = L("It may be beneficial to increase the extruder motor current during the filament exchange"
|
||||||
|
@ -641,6 +641,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||||||
((ConfigOptionBool, gcode_comments))
|
((ConfigOptionBool, gcode_comments))
|
||||||
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
|
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
|
||||||
((ConfigOptionBool, gcode_label_objects))
|
((ConfigOptionBool, gcode_label_objects))
|
||||||
|
((ConfigOptionStrings, gcode_substitutions))
|
||||||
((ConfigOptionString, layer_gcode))
|
((ConfigOptionString, layer_gcode))
|
||||||
((ConfigOptionFloat, max_print_speed))
|
((ConfigOptionFloat, max_print_speed))
|
||||||
((ConfigOptionFloat, max_volumetric_speed))
|
((ConfigOptionFloat, max_volumetric_speed))
|
||||||
|
Loading…
Reference in New Issue
Block a user