Skip to content

Commit cf84619

Browse files
igiannakasMGunlogsonbubnikv
authored
Porting of Pressure Equalizer feature from Prusa Slicer 2.6.x (#2161)
* Overhang perimeter handling Updated code to handle overhang perimeters as an overhang and not as a bridge. * Preparing to add curled extrusions identification * Porting curling calculations from Prusa Slier 2.6.1 * Prototype 1 - slowdown extended to detect curled edges and further reduce speed First prototype of the code submitted. * Working prototype - 2 Code is now finally working - external perimeters are slowed down as needed when there is likelyhood of curling up. ToDo: 1. Reslicing the model causes the algorithm not to run - need to find where this fails to trigger the call for this. 2. Slowdown of internal perimeters not working yet. * Updated to use overhang wall speed instead of bridging speed for this algorithm * Fixed bug in speed calculation and tweaked parameters for high speed printer Fixed bug in speed calculation and tweaked parameters for high speed printer * Attempting to fix "set started" not being set * Parameter tweak after print tests * Fixed estimation not running when model is re-sliced. * Removing debug printf statements and fixed threading flag. * Fixed threading * Parameter tweaks following print tests * Made this as an option in the GUI * Reintroduced handling of bridges as per original design * UI line toggling when option makes sense to be visible. * Fixed bug in field visibility & made it default to off * Code optimisation * Initial commit of code from Prusa Slicer 2.6.1 * Ported ExtrusionRole from Prusa Slicer 2.6.1 * fix compile errors * Update GCode.hpp * code changes to invoke pressure equalizer * attempting to trigger pressure equalizer (Not compiling) * Update Fill.cpp * Update Fill.cpp * Pressure equaliser layer result update * Further commits * Merged PR prusa3d/PrusaSlicer#9622 * First complete working version * Update PressureEqualizer.cpp * Implemented parameter in GUI * Toggle fields according to compatibility * Updated UI toggles between extrusion rate slope and arc fitting. * Updated tooltip * Introduced parameter smoothing segment length This parameter influences the number of division a line will undergo in response to the requirement to adhere to the extrusion rate flow adjustment. * Internal parameter and tool tip tweaking * Parameter and tool tip tweaking * Updated parameters and tooltip following testing. * Sync PressureEq with latest PrusaSlicer * Revert "Sync PressureEq with latest PrusaSlicer" This reverts commit 131fb94. --------- Co-authored-by: MGunlogson <[email protected]> Co-authored-by: Vojtech Bubnik <[email protected]>
1 parent 78a8bad commit cf84619

14 files changed

+826
-433
lines changed

src/libslic3r/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ set(lisbslic3r_sources
6262
ExtrusionEntity.hpp
6363
ExtrusionEntityCollection.cpp
6464
ExtrusionEntityCollection.hpp
65+
ExtrusionRole.cpp
66+
ExtrusionRole.hpp
6567
ExtrusionSimulator.cpp
6668
ExtrusionSimulator.hpp
6769
FileParserError.hpp
@@ -128,8 +130,8 @@ set(lisbslic3r_sources
128130
GCode/FanMover.hpp
129131
GCode/PostProcessor.cpp
130132
GCode/PostProcessor.hpp
131-
# GCode/PressureEqualizer.cpp
132-
# GCode/PressureEqualizer.hpp
133+
GCode/PressureEqualizer.cpp
134+
GCode/PressureEqualizer.hpp
133135
GCode/PrintExtents.cpp
134136
GCode/PrintExtents.hpp
135137
GCode/RetractWhenCrossingPerimeters.cpp

src/libslic3r/ExtrusionRole.cpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
///|/ Copyright (c) Prusa Research 2023 Pavel Mikuš @Godrak, Oleksandra Iushchenko @YuSanka, Vojtěch Bubník @bubnikv
2+
///|/
3+
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
4+
///|/
5+
#include "ExtrusionRole.hpp"
6+
#include "I18N.hpp"
7+
8+
#include <string>
9+
#include <string_view>
10+
#include <cassert>
11+
12+
13+
namespace Slic3r {
14+
15+
// Convert a rich bitmask based ExtrusionRole to a less expressive ordinal GCodeExtrusionRole.
16+
// GCodeExtrusionRole is to be serialized into G-code and deserialized by G-code viewer,
17+
GCodeExtrusionRole extrusion_role_to_gcode_extrusion_role(ExtrusionRole role)
18+
{
19+
if (role == erNone) return GCodeExtrusionRole::None;
20+
if (role == erOverhangPerimeter) return GCodeExtrusionRole::OverhangPerimeter;
21+
if (role == erExternalPerimeter) return GCodeExtrusionRole::ExternalPerimeter;
22+
if (role == erPerimeter) return GCodeExtrusionRole::Perimeter;
23+
if (role == erInternalInfill) return GCodeExtrusionRole::InternalInfill;
24+
if (role == erSolidInfill) return GCodeExtrusionRole::SolidInfill;
25+
if (role == erTopSolidInfill) return GCodeExtrusionRole::TopSolidInfill;
26+
if (role == erIroning) return GCodeExtrusionRole::Ironing;
27+
if (role == erBridgeInfill) return GCodeExtrusionRole::BridgeInfill;
28+
if (role == erGapFill) return GCodeExtrusionRole::GapFill;
29+
if (role == erSkirt) return GCodeExtrusionRole::Skirt;
30+
if (role == erSupportMaterial) return GCodeExtrusionRole::SupportMaterial;
31+
if (role == erSupportMaterialInterface) return GCodeExtrusionRole::SupportMaterialInterface;
32+
if (role == erWipeTower) return GCodeExtrusionRole::WipeTower;
33+
assert(false);
34+
return GCodeExtrusionRole::None;
35+
}
36+
37+
std::string gcode_extrusion_role_to_string(GCodeExtrusionRole role)
38+
{
39+
switch (role) {
40+
case GCodeExtrusionRole::None : return L("Unknown");
41+
case GCodeExtrusionRole::Perimeter : return L("Perimeter");
42+
case GCodeExtrusionRole::ExternalPerimeter : return L("External perimeter");
43+
case GCodeExtrusionRole::OverhangPerimeter : return L("Overhang perimeter");
44+
case GCodeExtrusionRole::InternalInfill : return L("Internal infill");
45+
case GCodeExtrusionRole::SolidInfill : return L("Solid infill");
46+
case GCodeExtrusionRole::TopSolidInfill : return L("Top solid infill");
47+
case GCodeExtrusionRole::Ironing : return L("Ironing");
48+
case GCodeExtrusionRole::BridgeInfill : return L("Bridge infill");
49+
case GCodeExtrusionRole::GapFill : return L("Gap fill");
50+
case GCodeExtrusionRole::Skirt : return L("Skirt/Brim");
51+
case GCodeExtrusionRole::SupportMaterial : return L("Support material");
52+
case GCodeExtrusionRole::SupportMaterialInterface : return L("Support material interface");
53+
case GCodeExtrusionRole::WipeTower : return L("Wipe tower");
54+
case GCodeExtrusionRole::Custom : return L("Custom");
55+
default : assert(false);
56+
}
57+
return {};
58+
}
59+
60+
GCodeExtrusionRole string_to_gcode_extrusion_role(const std::string_view role)
61+
{
62+
if (role == L("Perimeter"))
63+
return GCodeExtrusionRole::Perimeter;
64+
else if (role == L("External perimeter"))
65+
return GCodeExtrusionRole::ExternalPerimeter;
66+
else if (role == L("Overhang perimeter"))
67+
return GCodeExtrusionRole::OverhangPerimeter;
68+
else if (role == L("Internal infill"))
69+
return GCodeExtrusionRole::InternalInfill;
70+
else if (role == L("Solid infill"))
71+
return GCodeExtrusionRole::SolidInfill;
72+
else if (role == L("Top solid infill"))
73+
return GCodeExtrusionRole::TopSolidInfill;
74+
else if (role == L("Ironing"))
75+
return GCodeExtrusionRole::Ironing;
76+
else if (role == L("Bridge infill"))
77+
return GCodeExtrusionRole::BridgeInfill;
78+
else if (role == L("Gap fill"))
79+
return GCodeExtrusionRole::GapFill;
80+
else if (role == L("Skirt") || role == L("Skirt/Brim")) // "Skirt" is for backward compatibility with 2.3.1 and earlier
81+
return GCodeExtrusionRole::Skirt;
82+
else if (role == L("Support material"))
83+
return GCodeExtrusionRole::SupportMaterial;
84+
else if (role == L("Support material interface"))
85+
return GCodeExtrusionRole::SupportMaterialInterface;
86+
else if (role == L("Wipe tower"))
87+
return GCodeExtrusionRole::WipeTower;
88+
else if (role == L("Custom"))
89+
return GCodeExtrusionRole::Custom;
90+
else
91+
return GCodeExtrusionRole::None;
92+
}
93+
94+
}

src/libslic3r/ExtrusionRole.hpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
///|/ Copyright (c) 2023 Robert Schiele @schiele
2+
///|/ Copyright (c) Prusa Research 2023 Vojtěch Bubník @bubnikv
3+
///|/
4+
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
5+
///|/
6+
#ifndef slic3r_ExtrusionRole_hpp_
7+
#define slic3r_ExtrusionRole_hpp_
8+
9+
#include "enum_bitmask.hpp"
10+
#include "ExtrusionEntity.hpp"
11+
12+
#include <string>
13+
#include <string_view>
14+
#include <cstdint>
15+
16+
namespace Slic3r {
17+
18+
enum class ExtrusionRoleModifier : uint16_t {
19+
// 1) Extrusion types
20+
// Perimeter (external, inner, ...)
21+
Perimeter,
22+
// Infill (top / bottom / solid inner / sparse inner / bridging inner ...)
23+
Infill,
24+
// Variable width extrusion
25+
Thin,
26+
// Support material extrusion
27+
Support,
28+
Skirt,
29+
Wipe,
30+
// 2) Extrusion modifiers
31+
External,
32+
Solid,
33+
Ironing,
34+
Bridge,
35+
// 3) Special types
36+
// Indicator that the extrusion role was mixed from multiple differing extrusion roles,
37+
// for example from Support and SupportInterface.
38+
Mixed,
39+
// Stopper, there should be maximum 16 modifiers defined for uint16_t bit mask.
40+
Count
41+
};
42+
// There should be maximum 16 modifiers defined for uint16_t bit mask.
43+
static_assert(int(ExtrusionRoleModifier::Count) <= 16, "ExtrusionRoleModifier: there must be maximum 16 modifiers defined to fit a 16 bit bitmask");
44+
45+
using ExtrusionRoleModifiers = enum_bitmask<ExtrusionRoleModifier>;
46+
ENABLE_ENUM_BITMASK_OPERATORS(ExtrusionRoleModifier);
47+
48+
49+
50+
// Be careful when editing this list as many parts of the code depend
51+
// on the values of these ordinars, for example
52+
// GCodeViewer::Extrusion_Role_Colors
53+
enum class GCodeExtrusionRole : uint8_t {
54+
None,
55+
Perimeter,
56+
ExternalPerimeter,
57+
OverhangPerimeter,
58+
InternalInfill,
59+
SolidInfill,
60+
TopSolidInfill,
61+
Ironing,
62+
BridgeInfill,
63+
GapFill,
64+
Skirt,
65+
SupportMaterial,
66+
SupportMaterialInterface,
67+
WipeTower,
68+
// Custom (user defined) G-code block, for example start / end G-code.
69+
Custom,
70+
// Stopper to count number of enums.
71+
Count
72+
};
73+
74+
// Convert a rich bitmask based ExtrusionRole to a less expressive ordinal GCodeExtrusionRole.
75+
// GCodeExtrusionRole is to be serialized into G-code and deserialized by G-code viewer,
76+
GCodeExtrusionRole extrusion_role_to_gcode_extrusion_role(ExtrusionRole role);
77+
78+
std::string gcode_extrusion_role_to_string(GCodeExtrusionRole role);
79+
GCodeExtrusionRole string_to_gcode_extrusion_role(const std::string_view role);
80+
81+
}
82+
83+
#endif // slic3r_ExtrusionRole_hpp_

src/libslic3r/GCode.cpp

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1873,14 +1873,13 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
18731873

18741874
if (print.config().spiral_mode.value)
18751875
m_spiral_vase = make_unique<SpiralVase>(print.config());
1876-
#ifdef HAS_PRESSURE_EQUALIZER
1877-
if (print.config().max_volumetric_extrusion_rate_slope_positive.value > 0 ||
1878-
print.config().max_volumetric_extrusion_rate_slope_negative.value > 0)
1879-
m_pressure_equalizer = make_unique<PressureEqualizer>(&print.config());
1880-
m_enable_extrusion_role_markers = (bool)m_pressure_equalizer;
1881-
#else /* HAS_PRESSURE_EQUALIZER */
1882-
m_enable_extrusion_role_markers = false;
1883-
#endif /* HAS_PRESSURE_EQUALIZER */
1876+
1877+
if (print.config().max_volumetric_extrusion_rate_slope.value > 0){
1878+
m_pressure_equalizer = make_unique<PressureEqualizer>(print.config());
1879+
m_enable_extrusion_role_markers = (bool)m_pressure_equalizer;
1880+
} else
1881+
m_enable_extrusion_role_markers = false;
1882+
18841883

18851884
file.write_format("; HEADER_BLOCK_START\n");
18861885
// Write information on the generator.
@@ -2388,10 +2387,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
23882387
file.write("M1003 S0\n");
23892388
}
23902389
}
2391-
#ifdef HAS_PRESSURE_EQUALIZER
2392-
if (m_pressure_equalizer)
2393-
file.write(m_pressure_equalizer->process("", true));
2394-
#endif /* HAS_PRESSURE_EQUALIZER */
23952390
++ finished_objects;
23962391
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
23972392
// Reset it when starting another object from 1st layer.
@@ -2459,10 +2454,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
24592454
file.write("M1003 S0\n");
24602455
}
24612456
}
2462-
#ifdef HAS_PRESSURE_EQUALIZER
2463-
if (m_pressure_equalizer)
2464-
file.write(m_pressure_equalizer->process("", true));
2465-
#endif /* HAS_PRESSURE_EQUALIZER */
24662457
if (m_wipe_tower)
24672458
// Purge the extruder, pull out the active filament.
24682459
file.write(m_wipe_tower->finalize(*this));
@@ -2595,11 +2586,18 @@ void GCode::process_layers(
25952586
{
25962587
// The pipeline is variable: The vase mode filter is optional.
25972588
size_t layer_to_print_idx = 0;
2598-
const auto generator = tbb::make_filter<void, GCode::LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2599-
[this, &print, &tool_ordering, &print_object_instances_ordering, &layers_to_print, &layer_to_print_idx](tbb::flow_control& fc) -> GCode::LayerResult {
2600-
if (layer_to_print_idx == layers_to_print.size()) {
2601-
fc.stop();
2602-
return {};
2589+
const auto generator = tbb::make_filter<void, LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2590+
[this, &print, &tool_ordering, &print_object_instances_ordering, &layers_to_print, &layer_to_print_idx](tbb::flow_control& fc) -> LayerResult {
2591+
if (layer_to_print_idx >= layers_to_print.size()) {
2592+
if ((!m_pressure_equalizer && layer_to_print_idx == layers_to_print.size()) || (m_pressure_equalizer && layer_to_print_idx == (layers_to_print.size() + 1))) {
2593+
fc.stop();
2594+
return {};
2595+
} else {
2596+
// Pressure equalizer need insert empty input. Because it returns one layer back.
2597+
// Insert NOP (no operation) layer;
2598+
++layer_to_print_idx;
2599+
return LayerResult::make_nop_layer_result();
2600+
}
26032601
} else {
26042602
const std::pair<coordf_t, std::vector<LayerToPrint>>& layer = layers_to_print[layer_to_print_idx++];
26052603
const LayerTools& layer_tools = tool_ordering.tools_for_layer(layer.first);
@@ -2612,13 +2610,23 @@ void GCode::process_layers(
26122610
return this->process_layer(print, layer.second, layer_tools, &layer == &layers_to_print.back(), &print_object_instances_ordering, size_t(-1));
26132611
}
26142612
});
2615-
const auto spiral_mode = tbb::make_filter<GCode::LayerResult, GCode::LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2616-
[&spiral_mode = *this->m_spiral_vase.get()](GCode::LayerResult in) -> GCode::LayerResult {
2613+
2614+
const auto spiral_mode = tbb::make_filter<LayerResult, LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2615+
[&spiral_mode = *this->m_spiral_vase.get()](LayerResult in) -> LayerResult {
2616+
if (in.nop_layer_result)
2617+
return in;
2618+
26172619
spiral_mode.enable(in.spiral_vase_enable);
26182620
return { spiral_mode.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush };
26192621
});
2620-
const auto cooling = tbb::make_filter<GCode::LayerResult, std::string>(slic3r_tbb_filtermode::serial_in_order,
2621-
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in) -> std::string {
2622+
const auto pressure_equalizer = tbb::make_filter<LayerResult, LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2623+
[pressure_equalizer = this->m_pressure_equalizer.get()](LayerResult in) -> LayerResult {
2624+
return pressure_equalizer->process_layer(std::move(in));
2625+
});
2626+
const auto cooling = tbb::make_filter<LayerResult, std::string>(slic3r_tbb_filtermode::serial_in_order,
2627+
[&cooling_buffer = *this->m_cooling_buffer.get()](LayerResult in) -> std::string {
2628+
if (in.nop_layer_result)
2629+
return in.gcode;
26222630
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
26232631
});
26242632
const auto output = tbb::make_filter<std::string, void>(slic3r_tbb_filtermode::serial_in_order,
@@ -2627,6 +2635,7 @@ void GCode::process_layers(
26272635

26282636
const auto fan_mover = tbb::make_filter<std::string, std::string>(slic3r_tbb_filtermode::serial_in_order,
26292637
[&fan_mover = this->m_fan_mover, &config = this->config(), &writer = this->m_writer](std::string in)->std::string {
2638+
26302639
CNumericLocalesSetter locales_setter;
26312640

26322641
if (config.fan_speedup_time.value != 0 || config.fan_kickstart.value > 0) {
@@ -2645,10 +2654,14 @@ void GCode::process_layers(
26452654
});
26462655

26472656
// The pipeline elements are joined using const references, thus no copying is performed.
2648-
if (m_spiral_vase)
2649-
tbb::parallel_pipeline(12, generator & spiral_mode & cooling & fan_mover & output);
2657+
if (m_spiral_vase && m_pressure_equalizer)
2658+
tbb::parallel_pipeline(12, generator & spiral_mode & pressure_equalizer & cooling & fan_mover & output);
2659+
else if (m_spiral_vase)
2660+
tbb::parallel_pipeline(12, generator & spiral_mode & cooling & fan_mover & output);
2661+
else if (m_pressure_equalizer)
2662+
tbb::parallel_pipeline(12, generator & pressure_equalizer & cooling & fan_mover & output);
26502663
else
2651-
tbb::parallel_pipeline(12, generator & cooling & fan_mover & output);
2664+
tbb::parallel_pipeline(12, generator & cooling & fan_mover & output);
26522665
}
26532666

26542667
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
@@ -2665,8 +2678,8 @@ void GCode::process_layers(
26652678
{
26662679
// The pipeline is variable: The vase mode filter is optional.
26672680
size_t layer_to_print_idx = 0;
2668-
const auto generator = tbb::make_filter<void, GCode::LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2669-
[this, &print, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx, prime_extruder](tbb::flow_control& fc) -> GCode::LayerResult {
2681+
const auto generator = tbb::make_filter<void, LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2682+
[this, &print, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx, prime_extruder](tbb::flow_control& fc) -> LayerResult {
26702683
if (layer_to_print_idx == layers_to_print.size()) {
26712684
fc.stop();
26722685
return {};
@@ -2679,13 +2692,13 @@ void GCode::process_layers(
26792692
return this->process_layer(print, { std::move(layer) }, tool_ordering.tools_for_layer(layer.print_z()), &layer == &layers_to_print.back(), nullptr, single_object_idx, prime_extruder);
26802693
}
26812694
});
2682-
const auto spiral_mode = tbb::make_filter<GCode::LayerResult, GCode::LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2683-
[&spiral_mode = *this->m_spiral_vase.get()](GCode::LayerResult in)->GCode::LayerResult {
2695+
const auto spiral_mode = tbb::make_filter<LayerResult, LayerResult>(slic3r_tbb_filtermode::serial_in_order,
2696+
[&spiral_mode = *this->m_spiral_vase.get()](LayerResult in)->LayerResult {
26842697
spiral_mode.enable(in.spiral_vase_enable);
26852698
return { spiral_mode.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush };
26862699
});
2687-
const auto cooling = tbb::make_filter<GCode::LayerResult, std::string>(slic3r_tbb_filtermode::serial_in_order,
2688-
[&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in)->std::string {
2700+
const auto cooling = tbb::make_filter<LayerResult, std::string>(slic3r_tbb_filtermode::serial_in_order,
2701+
[&cooling_buffer = *this->m_cooling_buffer.get()](LayerResult in)->std::string {
26892702
return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush);
26902703
});
26912704
const auto output = tbb::make_filter<std::string, void>(slic3r_tbb_filtermode::serial_in_order,
@@ -3216,7 +3229,7 @@ inline std::string get_instance_name(const PrintObject *object, const PrintInsta
32163229
// In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated.
32173230
// For multi-material prints, this routine minimizes extruder switches by gathering extruder specific extrusion paths
32183231
// and performing the extruder specific extrusions together.
3219-
GCode::LayerResult GCode::process_layer(
3232+
LayerResult GCode::process_layer(
32203233
const Print &print,
32213234
// Set of object & print layers of the same PrintObject and with the same print_z.
32223235
const std::vector<LayerToPrint> &layers,
@@ -3255,7 +3268,7 @@ GCode::LayerResult GCode::process_layer(
32553268
else if (support_layer != nullptr)
32563269
layer_ptr = support_layer;
32573270
const Layer& layer = *layer_ptr;
3258-
GCode::LayerResult result { {}, layer.id(), false, last_layer };
3271+
LayerResult result { {}, layer.id(), false, last_layer };
32593272
if (layer_tools.extruders.empty())
32603273
// Nothing to extrude.
32613274
return result;
@@ -3878,14 +3891,6 @@ GCode::LayerResult GCode::process_layer(
38783891
// Flush the cooling buffer at each object layer or possibly at the last layer, even if it contains just supports (This should not happen).
38793892
object_layer || last_layer);
38803893

3881-
#ifdef HAS_PRESSURE_EQUALIZER
3882-
// Apply pressure equalization if enabled;
3883-
// printf("G-code before filter:\n%s\n", gcode.c_str());
3884-
if (m_pressure_equalizer)
3885-
gcode = m_pressure_equalizer->process(gcode.c_str(), false);
3886-
// printf("G-code after filter:\n%s\n", out.c_str());
3887-
#endif /* HAS_PRESSURE_EQUALIZER */
3888-
38893894
file.write(gcode);
38903895
#endif
38913896

0 commit comments

Comments
 (0)