This commit is contained in:
SoftFever 2022-12-21 17:05:27 +08:00
parent dc1fcf7ed6
commit d9e9fb2206
13 changed files with 475 additions and 154 deletions

View file

@ -369,6 +369,8 @@ set(lisbslic3r_sources
Arachne/WallToolPaths.cpp
Shape/TextShape.hpp
Shape/TextShape.cpp
calib.hpp
calib.cpp
)
if (APPLE)

View file

@ -36,7 +36,7 @@
#include "SVG.hpp"
#include <tbb/parallel_for.h>
#include "calib.hpp"
// Intel redesigned some TBB interface considerably when merging TBB with their oneAPI set of libraries, see GH #7332.
// We are using quite an old TBB 2017 U7. Before we update our build servers, let's use the old API, which is deprecated in up to date TBB.
#if ! defined(TBB_VERSION_MAJOR)
@ -1633,73 +1633,164 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
this->m_objSupportsWithBrim.insert(iter->first);
}
if (this->m_objsWithBrim.empty() && this->m_objSupportsWithBrim.empty()) m_brim_done = true;
if (print.is_calib_mode()) {
std::string gcode;
auto s = m_config.inner_wall_speed.value;
if (m_config.default_acceleration.value > 0) {
double acceleration = std::max(m_config.inner_wall_acceleration.value, m_config.outer_wall_acceleration.value);
gcode += m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5));
}
//BBS: open spaghetti detector
if (is_bbl_printers) {
// if (print.config().spaghetti_detector.value)
file.write("M981 S1 P20000 ;open spaghetti detector\n");
if (m_config.default_jerk.value > 0) {
double jerk = m_config.default_jerk.value;
gcode += m_writer.set_jerk_xy((unsigned int)floor(jerk + 0.5));
}
m_config.outer_wall_speed = print.default_region_config().outer_wall_speed;
m_config.inner_wall_speed = print.default_region_config().inner_wall_speed;
calib_pressure_advance pa_test(this);
gcode = pa_test.generate_test();
file.write(gcode);
}
else {
//BBS: open spaghetti detector
if (is_bbl_printers) {
// if (print.config().spaghetti_detector.value)
file.write("M981 S1 P20000 ;open spaghetti detector\n");
}
// Do all objects for each layer.
if (print.config().print_sequence == PrintSequence::ByObject) {
size_t finished_objects = 0;
const PrintObject *prev_object = (*print_object_instance_sequential_active)->print_object;
for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++ print_object_instance_sequential_active) {
const PrintObject &object = *(*print_object_instance_sequential_active)->print_object;
if (&object != prev_object || tool_ordering.first_extruder() != final_extruder_id) {
tool_ordering = ToolOrdering(object, final_extruder_id);
unsigned int new_extruder_id = tool_ordering.first_extruder();
if (new_extruder_id == (unsigned int)-1)
// Skip this object.
continue;
initial_extruder_id = new_extruder_id;
final_extruder_id = tool_ordering.last_extruder();
assert(final_extruder_id != (unsigned int)-1);
}
print.throw_if_canceled();
this->set_origin(unscale((*print_object_instance_sequential_active)->shift));
// Do all objects for each layer.
if (print.config().print_sequence == PrintSequence::ByObject) {
size_t finished_objects = 0;
const PrintObject* prev_object = (*print_object_instance_sequential_active)->print_object;
for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++print_object_instance_sequential_active) {
const PrintObject& object = *(*print_object_instance_sequential_active)->print_object;
if (&object != prev_object || tool_ordering.first_extruder() != final_extruder_id) {
tool_ordering = ToolOrdering(object, final_extruder_id);
unsigned int new_extruder_id = tool_ordering.first_extruder();
if (new_extruder_id == (unsigned int)-1)
// Skip this object.
continue;
initial_extruder_id = new_extruder_id;
final_extruder_id = tool_ordering.last_extruder();
assert(final_extruder_id != (unsigned int)-1);
}
print.throw_if_canceled();
this->set_origin(unscale((*print_object_instance_sequential_active)->shift));
// BBS: prime extruder if extruder change happens before this object instance
bool prime_extruder = false;
if (finished_objects > 0) {
// Move to the origin position for the copy we're going to print.
// This happens before Z goes down to layer 0 again, so that no collision happens hopefully.
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
m_avoid_crossing_perimeters.use_external_mp_once();
// BBS. change tool before moving to origin point.
if (m_writer.need_toolchange(initial_extruder_id)) {
const PrintObjectConfig& object_config = object.config();
coordf_t initial_layer_print_height = print.config().initial_layer_print_height.value;
file.write(this->set_extruder(initial_extruder_id, initial_layer_print_height));
prime_extruder = true;
// BBS: prime extruder if extruder change happens before this object instance
bool prime_extruder = false;
if (finished_objects > 0) {
// Move to the origin position for the copy we're going to print.
// This happens before Z goes down to layer 0 again, so that no collision happens hopefully.
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
m_avoid_crossing_perimeters.use_external_mp_once();
// BBS. change tool before moving to origin point.
if (m_writer.need_toolchange(initial_extruder_id)) {
const PrintObjectConfig& object_config = object.config();
coordf_t initial_layer_print_height = print.config().initial_layer_print_height.value;
file.write(this->set_extruder(initial_extruder_id, initial_layer_print_height));
prime_extruder = true;
}
else {
file.write(this->retract());
}
file.write(m_writer.travel_to_z(m_max_layer_z));
file.write(this->travel_to(Point(0, 0), erNone, "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();
// Ff we are printing the bottom layer of an object, and we have already finished
// another one, set first layer temperatures. This happens before the Z move
// is triggered, so machine has more time to reach such temperatures.
m_placeholder_parser.set("current_object_idx", int(finished_objects));
//BBS: remove printing_by_object_gcode
//std::string printing_by_object_gcode = this->placeholder_parser_process("printing_by_object_gcode", print.config().printing_by_object_gcode.value, initial_extruder_id);
std::string printing_by_object_gcode;
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
this->_print_first_layer_bed_temperature(file, print, printing_by_object_gcode, initial_extruder_id, false);
this->_print_first_layer_extruder_temperatures(file, print, printing_by_object_gcode, initial_extruder_id, false);
file.writeln(printing_by_object_gcode);
}
else {
file.write(this->retract());
// Reset the cooling buffer internal state (the current position, feed rate, accelerations).
m_cooling_buffer->reset(this->writer().get_position());
m_cooling_buffer->set_current_extruder(initial_extruder_id);
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file.
this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file, prime_extruder);
//BBS: close powerlost recovery
{
if (is_bbl_printers && m_second_layer_things_done) {
file.write("; close powerlost recovery\n");
file.write("M1003 S0\n");
}
}
file.write(m_writer.travel_to_z(m_max_layer_z));
file.write(this->travel_to(Point(0, 0), erNone, "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();
// Ff we are printing the bottom layer of an object, and we have already finished
// another one, set first layer temperatures. This happens before the Z move
// is triggered, so machine has more time to reach such temperatures.
m_placeholder_parser.set("current_object_idx", int(finished_objects));
//BBS: remove printing_by_object_gcode
//std::string printing_by_object_gcode = this->placeholder_parser_process("printing_by_object_gcode", print.config().printing_by_object_gcode.value, initial_extruder_id);
std::string printing_by_object_gcode;
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
this->_print_first_layer_bed_temperature(file, print, printing_by_object_gcode, initial_extruder_id, false);
this->_print_first_layer_extruder_temperatures(file, print, printing_by_object_gcode, initial_extruder_id, false);
file.writeln(printing_by_object_gcode);
#ifdef HAS_PRESSURE_EQUALIZER
if (m_pressure_equalizer)
file.write(m_pressure_equalizer->process("", true));
#endif /* HAS_PRESSURE_EQUALIZER */
++finished_objects;
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
// Reset it when starting another object from 1st layer.
m_second_layer_things_done = false;
prev_object = &object;
}
// Reset the cooling buffer internal state (the current position, feed rate, accelerations).
m_cooling_buffer->reset(this->writer().get_position());
m_cooling_buffer->set_current_extruder(initial_extruder_id);
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
}
else {
// Sort layers by Z.
// All extrusion moves with the same top layer height are extruded uninterrupted.
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
// Prusa Multi-Material wipe tower.
if (has_wipe_tower && !layers_to_print.empty()) {
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), print.get_plate_index(), print.get_plate_origin(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
//BBS
//file.write(m_writer.travel_to_z(initial_layer_print_height + m_config.z_offset.value, "Move to the first layer height"));
file.write(m_writer.travel_to_z(initial_layer_print_height, "Move to the first layer height"));
#if 0
if (print.config().single_extruder_multi_material_priming) {
file.write(m_wipe_tower->prime(*this));
// Verify, whether the print overaps the priming extrusions.
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
for (const PrintObject* print_object : print.objects())
bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz));
bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
bbox_prime.offset(0.5f);
bool overlap = bbox_prime.overlap(bbox_print);
if (print.config().gcode_flavor == gcfMarlinLegacy || print.config().gcode_flavor == gcfMarlinFirmware) {
file.write(this->retract());
file.write("M300 S800 P500\n"); // Beep for 500ms, tone 800Hz.
if (overlap) {
// Wait for the user to remove the priming extrusions.
file.write("M1 Remove priming towers and click button.\n");
}
else {
// Just wait for a bit to let the user check, that the priming succeeded.
//TODO Add a message explaining what the printer is waiting for. This needs a firmware fix.
file.write("M1 S10\n");
}
}
//BBS: only support Marlin
//else {
// This is not Marlin, M1 command is probably not supported.
//if (overlap) {
// print.active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
// _(L("Your print is very close to the priming regions. "
// "Make sure there is no collision.")));
//} else {
// // Just continue printing, no action necessary.
//}
//}
}
#endif
print.throw_if_canceled();
}
// Process all layers of all objects (non-sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file.
this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file, prime_extruder);
this->process_layers(print, tool_ordering, print_object_instances_ordering, layers_to_print, file);
//BBS: close powerlost recovery
{
if (is_bbl_printers && m_second_layer_things_done) {
@ -1711,82 +1802,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
if (m_pressure_equalizer)
file.write(m_pressure_equalizer->process("", true));
#endif /* HAS_PRESSURE_EQUALIZER */
++ finished_objects;
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
// Reset it when starting another object from 1st layer.
m_second_layer_things_done = false;
prev_object = &object;
if (m_wipe_tower)
// Purge the extruder, pull out the active filament.
file.write(m_wipe_tower->finalize(*this));
}
} else {
// Sort layers by Z.
// All extrusion moves with the same top layer height are extruded uninterrupted.
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
// Prusa Multi-Material wipe tower.
if (has_wipe_tower && ! layers_to_print.empty()) {
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), print.get_plate_index(), print.get_plate_origin(), * print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
//BBS
//file.write(m_writer.travel_to_z(initial_layer_print_height + m_config.z_offset.value, "Move to the first layer height"));
file.write(m_writer.travel_to_z(initial_layer_print_height, "Move to the first layer height"));
#if 0
if (print.config().single_extruder_multi_material_priming) {
file.write(m_wipe_tower->prime(*this));
// Verify, whether the print overaps the priming extrusions.
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
for (const PrintObject *print_object : print.objects())
bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz));
bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
bbox_prime.offset(0.5f);
bool overlap = bbox_prime.overlap(bbox_print);
if (print.config().gcode_flavor == gcfMarlinLegacy || print.config().gcode_flavor == gcfMarlinFirmware) {
file.write(this->retract());
file.write("M300 S800 P500\n"); // Beep for 500ms, tone 800Hz.
if (overlap) {
// Wait for the user to remove the priming extrusions.
file.write("M1 Remove priming towers and click button.\n");
} else {
// Just wait for a bit to let the user check, that the priming succeeded.
//TODO Add a message explaining what the printer is waiting for. This needs a firmware fix.
file.write("M1 S10\n");
}
}
//BBS: only support Marlin
//else {
// This is not Marlin, M1 command is probably not supported.
//if (overlap) {
// print.active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
// _(L("Your print is very close to the priming regions. "
// "Make sure there is no collision.")));
//} else {
// // Just continue printing, no action necessary.
//}
//}
}
#endif
print.throw_if_canceled();
}
// Process all layers of all objects (non-sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file.
this->process_layers(print, tool_ordering, print_object_instances_ordering, layers_to_print, file);
//BBS: close powerlost recovery
{
if (is_bbl_printers && m_second_layer_things_done) {
file.write("; close powerlost recovery\n");
file.write("M1003 S0\n");
}
}
#ifdef HAS_PRESSURE_EQUALIZER
if (m_pressure_equalizer)
file.write(m_pressure_equalizer->process("", true));
#endif /* HAS_PRESSURE_EQUALIZER */
if (m_wipe_tower)
// Purge the extruder, pull out the active filament.
file.write(m_wipe_tower->finalize(*this));
}
//BBS: the last retraction
// Write end commands to file.
file.write(this->retract(false, true));

View file

@ -194,6 +194,12 @@ public:
void set_layer_count(unsigned int value) { m_layer_count = value; }
void apply_print_config(const PrintConfig &print_config);
std::string travel_to(const Point& point, ExtrusionRole role, std::string comment);
bool needs_retraction(const Polyline& travel, ExtrusionRole role = erNone);
std::string retract(bool toolchange = false, bool is_last_retraction = false);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z);
// append full config to the given string
static void append_full_config(const Print& print, std::string& str);
@ -398,15 +404,9 @@ private:
// For sequential print, the instance of the object to be printing has to be defined.
const size_t single_object_instance_idx);
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region);
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing);
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
bool needs_retraction(const Polyline &travel, ExtrusionRole role = erNone);
std::string retract(bool toolchange = false, bool is_last_retraction = false);
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
std::string set_extruder(unsigned int extruder_id, double print_z);
std::string extrude_perimeters(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region);
std::string extrude_infill(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region, bool ironing);
std::string extrude_support(const ExtrusionEntityCollection& support_fills);
std::set<ObjectID> m_objsWithBrim; // indicates the objs with brim
std::set<ObjectID> m_objSupportsWithBrim; // indicates the objs' supports with brim
// Cache for custom seam enforcers/blockers for each layer.

View file

@ -735,7 +735,8 @@ public:
//SoftFever
bool &is_BBL_printer() { return m_isBBLPrinter; }
const bool is_BBL_printer() const { return m_isBBLPrinter; }
bool &is_calib_mode() { return m_calib_mode; }
const bool is_calib_mode() const { return m_calib_mode; }
protected:
// Invalidates the step, and its depending steps in Print.
bool invalidate_step(PrintStep step);
@ -787,6 +788,9 @@ private:
Vec3d m_origin;
//BBS: modified_count
int m_modified_count {0};
//SoftFever: calibration mode, change to enum later
bool m_calib_mode;
// To allow GCode to set the Print's GCodeExport step status.
friend class GCode;

191
src/libslic3r/calib.cpp Normal file
View file

@ -0,0 +1,191 @@
#include "calib.hpp"
#include "Point.hpp"
#include "PrintConfig.hpp"
#include "GCodeWriter.hpp"
#include "GCode.hpp"
#include <map>
namespace Slic3r {
calib_pressure_advance::calib_pressure_advance(GCode* gcodegen) :mp_gcodegen(gcodegen), m_length_short(20.0), m_length_long(40.0) {}
std::string calib_pressure_advance::generate_test(double start_pa/*= 0*/, double step_pa /*= 0.005*/, int count/*= 10*/) {
auto bed_sizes = mp_gcodegen->config().printable_area.values;
auto w = bed_sizes[2].x() - bed_sizes[0].x();
auto h = bed_sizes[2].y() - bed_sizes[0].y();
auto startx = (w - 100) / 2;
auto starty = (h - count * 5) / 2;
return print_pa_lines(startx, starty, start_pa, step_pa, count);
}
std::string calib_pressure_advance::move_to(Vec2d pt) {
std::stringstream gcode;
gcode << mp_gcodegen->retract();
gcode << mp_gcodegen->writer().travel_to_xy(pt);
gcode << mp_gcodegen->unretract();
return gcode.str();
}
std::string calib_pressure_advance::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num) {
auto& writer = mp_gcodegen->writer();
const double e = 0.04; // filament_mm/extrusion_mm
const double y_offset = 5;
const double fast = std::max(mp_gcodegen->config().get_abs_value("inner_wall_speed"), mp_gcodegen->config().get_abs_value("outer_wall_speed")) * 60.0;
const double slow = std::max(1200.0, fast * 0.1);
std::stringstream gcode;
gcode << mp_gcodegen->writer().travel_to_z(0.2);
double y_pos = start_y;
for (int i = 0; i < num; ++i) {
gcode << writer.set_pressure_advance(start_pa + i * step_pa);
gcode << move_to(Vec2d(start_x, y_pos + i * y_offset));
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + i * y_offset), e * m_length_short);
gcode << writer.set_speed(fast);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + i * y_offset), e * m_length_long);
gcode << writer.set_speed(slow);
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long + m_length_short, y_pos + i * y_offset), e * m_length_short);
}
// draw indicator lines
gcode << writer.set_speed(fast);
gcode << move_to(Vec2d(start_x + m_length_short, y_pos + (num - 1) * y_offset + 2));
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + (num - 1) * y_offset + 7), e * 7);
gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * y_offset + 7));
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * y_offset + 2), e * 7);
for (int i = 0; i < num; i += 2) {
gcode << draw_number(start_x + m_length_short + m_length_long + m_length_short + 3, y_pos + i * y_offset + y_offset / 2, start_pa + i * step_pa);
}
return gcode.str();
}
std::string calib_pressure_advance::draw_digit(double startx, double starty, char c) {
auto& writer = mp_gcodegen->writer();
std::stringstream gcode;
const double lw = 0.48;
const double len = 2;
const double gap = lw / 2.0;
const double e = 0.04; // filament_mm/extrusion_mm
// 0-------1
// | |
// 3-------2
// | |
// 4-------5
const Vec2d p0(startx, starty);
const Vec2d p1(startx + len, starty);
const Vec2d p2(startx + len, starty - len);
const Vec2d p3(startx, starty - len);
const Vec2d p4(startx, starty - len * 2);
const Vec2d p5(startx + len, starty - len * 2);
switch (c)
{
case '0':
gcode << move_to(p0);
gcode << writer.extrude_to_xy(p1, e * len);
gcode << writer.extrude_to_xy(p5, e * len * 2);
gcode << writer.extrude_to_xy(p4, e * len);
gcode << writer.extrude_to_xy(p0 - Vec2d(0, gap), e * len * 2);
break;
case '1':
gcode << move_to(p0 + Vec2d(len / 2, 0));
gcode << writer.extrude_to_xy(p4 + Vec2d(len / 2, 0), e * len * 2);
break;
case '2':
gcode << move_to(p0);
gcode << writer.extrude_to_xy(p1, e * len);
gcode << writer.extrude_to_xy(p2, e * len);
gcode << writer.extrude_to_xy(p3, e * len);
gcode << writer.extrude_to_xy(p4, e * len);
gcode << writer.extrude_to_xy(p5, e * len);
break;
case '3':
gcode << move_to(p0);
gcode << writer.extrude_to_xy(p1, e * len);
gcode << writer.extrude_to_xy(p5, e * len * 2);
gcode << writer.extrude_to_xy(p4, e * len);
gcode << move_to(p2 - Vec2d(gap, 0));
gcode << writer.extrude_to_xy(p3, e * len);
break;
case '4':
gcode << move_to(p0);
gcode << writer.extrude_to_xy(p3, e * len);
gcode << writer.extrude_to_xy(p2, e * len);
gcode << move_to(p1);
gcode << writer.extrude_to_xy(p5, e * len * 2);
break;
case '5':
gcode << move_to(p1);
gcode << writer.extrude_to_xy(p0, e * len);
gcode << writer.extrude_to_xy(p3, e * len);
gcode << writer.extrude_to_xy(p2, e * len);
gcode << writer.extrude_to_xy(p5, e * len);
gcode << writer.extrude_to_xy(p4, e * len);
break;
case '6':
gcode << move_to(p1);
gcode << writer.extrude_to_xy(p0, e * len);
gcode << writer.extrude_to_xy(p4, e * len * 2);
gcode << writer.extrude_to_xy(p5, e * len);
gcode << writer.extrude_to_xy(p2, e * len);
gcode << writer.extrude_to_xy(p3, e * len);
break;
case '7':
gcode << move_to(p0);
gcode << writer.extrude_to_xy(p1, e * len);
gcode << writer.extrude_to_xy(p5, e * len * 2);
break;
case '8':
gcode << move_to(p2);
gcode << writer.extrude_to_xy(p3, e * len);
gcode << writer.extrude_to_xy(p4, e * len);
gcode << writer.extrude_to_xy(p5, e * len);
gcode << writer.extrude_to_xy(p1, e * len * 2);
gcode << writer.extrude_to_xy(p0, e * len);
gcode << writer.extrude_to_xy(p3, e * len);
break;
case '9':
gcode << move_to(p5);
gcode << writer.extrude_to_xy(p1, e * len * 2);
gcode << writer.extrude_to_xy(p0, e * len);
gcode << writer.extrude_to_xy(p3, e * len);
gcode << writer.extrude_to_xy(p2, e * len);
break;
case '.':
gcode << move_to(p4 + Vec2d(len / 2, 0));
gcode << writer.extrude_to_xy(p4 + Vec2d(len / 2, len / 2), e * len);
break;
default:
break;
}
return gcode.str();
}
// draw number
std::string calib_pressure_advance::draw_number(double startx, double starty, double value) {
double spacing = 3.0;
auto sNumber = std::to_string(value);
sNumber.erase(sNumber.find_last_not_of('0') + 1, std::string::npos);
sNumber.erase(sNumber.find_last_not_of('.') + 1, std::string::npos);
std::stringstream gcode;
gcode << mp_gcodegen->writer().set_speed(3600);
for (int i = 0; i < sNumber.length(); ++i) {
if (i > 5)
break;
gcode << draw_digit(startx + i * spacing, starty, sNumber[i]);
}
return gcode.str();
}
} // namespace Slic3r

25
src/libslic3r/calib.hpp Normal file
View file

@ -0,0 +1,25 @@
#pragma once
#include <string>
#include "Point.hpp"
namespace Slic3r {
class GCode;
class calib_pressure_advance
{
public:
calib_pressure_advance(GCode* gcodegen);
~calib_pressure_advance() {}
std::string generate_test(double start_pa = 0, double step_pa = 0.005, int count = 20);
private:
std::string move_to(Vec2d pt);
std::string print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num);
std::string draw_digit(double startx, double starty, char c);
std::string draw_number(double startx, double starty, double value);
private:
GCode* mp_gcodegen;
double m_length_short, m_length_long;
};
} // namespace Slic3r

View file

@ -32,6 +32,9 @@ wxDEFINE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
//SoftFever: goodie bag
wxDEFINE_EVENT(EVT_GLTOOLBAR_PA_CALIB, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDEFINE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);

View file

@ -32,6 +32,9 @@ wxDECLARE_EVENT(EVT_GLTOOLBAR_PRINT_SELECT, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_SEND_TO_PRINTER_ALL, SimpleEvent);
//SoftFever: goodie bag event
wxDECLARE_EVENT(EVT_GLTOOLBAR_PA_CALIB, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_ADD, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE, SimpleEvent);
wxDECLARE_EVENT(EVT_GLTOOLBAR_DELETE_ALL, SimpleEvent);

View file

@ -728,7 +728,7 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
/* FT_OBJ */ { "OBJ files"sv, { ".obj"sv } },
/* FT_AMF */ { "AMF files"sv, { ".amf"sv, ".zip.amf"sv, ".xml"sv } },
/* FT_3MF */ { "3MF files"sv, { ".3mf"sv } },
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv } },
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv, ".3mf"sv } },
/* FT_MODEL */ {"Supported files"sv, {".3mf"sv, ".stl"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv }},
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv} },
/* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } },
@ -3235,7 +3235,7 @@ void GUI_App::load_gcode(wxWindow* parent, wxString& input_file) const
{
input_file.Clear();
wxFileDialog dialog(parent ? parent : GetTopWindow(),
_L("Choose one file (gcode/.gco/.g/.ngc/ngc):"),
_L("Choose one file (gcode/3mf):"),
app_config->get_last_dir(), "",
file_wildcards(FT_GCODE), wxFD_OPEN | wxFD_FILE_MUST_EXIST);

View file

@ -831,6 +831,7 @@ void MainFrame::show_option(bool show)
m_print_btn->Hide();
m_slice_option_btn->Hide();
m_print_option_btn->Hide();
m_goodie_bag_btn->Hide();
Layout();
}
} else {
@ -839,6 +840,7 @@ void MainFrame::show_option(bool show)
m_print_btn->Show();
m_slice_option_btn->Show();
m_print_option_btn->Show();
m_goodie_bag_btn->Show();
Layout();
}
}
@ -1354,12 +1356,18 @@ wxBoxSizer* MainFrame::create_side_tools()
m_slice_select = eSlicePlate;
m_print_select = ePrintPlate;
m_goodie_bag_btn = new SideButton(this, _L("Goodiebag"), "");
m_slice_btn = new SideButton(this, _L("Slice"), "");
m_slice_option_btn = new SideButton(this, "", "sidebutton_dropdown", 0, FromDIP(14));
m_print_btn = new SideButton(this, _L("Print"), "");
m_print_option_btn = new SideButton(this, "", "sidebutton_dropdown", 0, FromDIP(14));
update_side_button_style();
m_goodie_bag_btn->Enable();
m_print_option_btn->Enable();
sizer->Add(m_goodie_bag_btn, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
sizer->Add(FromDIP(15), 0, 0, 0, 0);
m_slice_option_btn->Enable();
m_print_option_btn->Enable();
sizer->Add(m_slice_option_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
@ -1371,6 +1379,33 @@ wxBoxSizer* MainFrame::create_side_tools()
sizer->Layout();
m_goodie_bag_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
{
SidePopup* p = new SidePopup(this);
SideButton* calib_pa_btn = new SideButton(p, _L("Calibrate PA"), "");
calib_pa_btn->SetCornerRadius(0);
//SideButton* send_file_btn = new SideButton(p, _L("send file"), "");
//send_file_btn->SetCornerRadius(0);
calib_pa_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
//this->m_plater->select_view_3D("Preview");
m_plater->update();
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_PA_CALIB));
this->m_tabpanel->SetSelection(tpPreview);
});
//send_file_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
// //this->m_plater->select_view_3D("Preview");
// wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SEND_GCODE_FILE));
// });
p->append_button(calib_pa_btn);
//p->append_button(send_file_btn);
p->Popup(m_goodie_bag_btn);
}
);
m_slice_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
{
//this->m_plater->select_view_3D("Preview");
@ -1556,6 +1591,7 @@ wxBoxSizer* MainFrame::create_side_tools()
p->append_button(send_to_printer_btn);
p->append_button(send_to_printer_all_btn);
p->append_button(export_sliced_file_btn);
//p->append_button(export_gcode_btn);
p->append_button(export_all_sliced_file_btn);
}
@ -1703,6 +1739,14 @@ void MainFrame::update_side_button_style()
// BBS
int em = em_unit();
m_goodie_bag_btn->SetLayoutStyle(1);
m_goodie_bag_btn->SetTextLayout(SideButton::EHorizontalOrientation::HO_Center, FromDIP(15));
m_goodie_bag_btn->SetMinSize(wxSize(-1, FromDIP(24)));
m_goodie_bag_btn->SetCornerRadius(FromDIP(12));
m_goodie_bag_btn->SetExtraSize(wxSize(FromDIP(38), FromDIP(10)));
m_goodie_bag_btn->SetBottomColour(wxColour(0x3B4446));
m_slice_btn->SetLayoutStyle(1);
/*m_slice_btn->SetLayoutStyle(1);
m_slice_btn->SetTextLayout(SideButton::EHorizontalOrientation::HO_Center, FromDIP(15));
m_slice_btn->SetMinSize(wxSize(-1, FromDIP(24)));
@ -1786,6 +1830,7 @@ void MainFrame::on_dpi_changed(const wxRect& suggested_rect)
update_side_button_style();
m_goodie_bag_btn->Rescale();
m_slice_btn->Rescale();
m_print_btn->Rescale();
m_slice_option_btn->Rescale();

View file

@ -355,6 +355,7 @@ public:
// BBS
mutable int m_print_select{ ePrintAll };
mutable int m_slice_select{ eSliceAll };
SideButton* m_goodie_bag_btn{ nullptr };
SideButton* m_slice_btn{ nullptr };
SideButton* m_slice_option_btn{ nullptr };
SideButton* m_print_btn{ nullptr };

View file

@ -2032,6 +2032,7 @@ struct Plater::priv
//BBS: GUI refactor: GLToolbar
void on_action_open_project(SimpleEvent&);
void on_action_slice_plate(SimpleEvent&);
void on_action_calib_pa(SimpleEvent&);
void on_action_slice_all(SimpleEvent&);
void on_action_publish(wxCommandEvent &evt);
void on_action_print_plate(SimpleEvent&);
@ -2441,6 +2442,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
q->Bind(EVT_GLVIEWTOOLBAR_PREVIEW, [q](SimpleEvent&) { q->select_view_3D("Preview", false); });
q->Bind(EVT_GLTOOLBAR_SLICE_PLATE, &priv::on_action_slice_plate, this);
q->Bind(EVT_GLTOOLBAR_SLICE_ALL, &priv::on_action_slice_all, this);
q->Bind(EVT_GLTOOLBAR_SLICE_ALL, &priv::on_action_calib_pa, this);
q->Bind(EVT_GLTOOLBAR_PRINT_PLATE, &priv::on_action_print_plate, this);
q->Bind(EVT_GLTOOLBAR_SELECT_SLICED_PLATE, &priv::on_action_select_sliced_plate, this);
q->Bind(EVT_GLTOOLBAR_PRINT_ALL, &priv::on_action_print_all, this);
@ -5994,6 +5996,25 @@ void Plater::priv::on_action_slice_plate(SimpleEvent&)
}
}
//BBS: GUI refactor: slice plate
void Plater::priv::on_action_calib_pa(SimpleEvent&)
{
if (q != nullptr) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received calib pa event\n" ;
if(fff_print.model().objects.empty())
//add model
q->add_model(false,Slic3r::resources_dir()+"/calib/sf_placeholder.stl");
fff_print.is_calib_mode() = true;
//BBS update extruder params and speed table before slicing
Plater::setExtruderParams(Slic3r::Model::extruderParamsMap);
Plater::setPrintSpeedTable(Slic3r::Model::printSpeedMap);
m_slice_all = false;
q->reslice();
q->select_view_3D("Preview");
}
}
//BBS: GUI refactor: slice all
void Plater::priv::on_action_slice_all(SimpleEvent&)
{
@ -7800,16 +7821,22 @@ bool Plater::up_to_date(bool saved, bool backup)
!Slic3r::has_other_changes(backup));
}
void Plater::add_model(bool imperial_units/* = false*/)
void Plater::add_model(bool imperial_units/* = false*/, std::string fname/* = ""*/)
{
wxArrayString input_files;
wxGetApp().import_model(this, input_files);
if (input_files.empty())
return;
std::vector<fs::path> paths;
for (const auto &file : input_files)
paths.emplace_back(into_path(file));
if(fname.empty()){
wxArrayString input_files;
wxGetApp().import_model(this, input_files);
if (input_files.empty())
return;
for (const auto &file : input_files)
paths.emplace_back(into_path(file));
}
else{
paths.emplace_back(fname);
}
std::string snapshot_label;
assert(! paths.empty());

View file

@ -217,7 +217,7 @@ public:
bool open_3mf_file(const fs::path &file_path);
int get_3mf_file_count(std::vector<fs::path> paths);
void add_file();
void add_model(bool imperial_units = false);
void add_model(bool imperial_units = false, std::string fname = "");
void import_sl1_archive();
void extract_config_from_project();
void load_gcode();