From d9e9fb22068f463c8e85f710ec2114d78257afc1 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Wed, 21 Dec 2022 17:05:27 +0800 Subject: [PATCH] init --- src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/GCode.cpp | 286 +++++++++++++++++++---------------- src/libslic3r/GCode.hpp | 18 +-- src/libslic3r/Print.hpp | 6 +- src/libslic3r/calib.cpp | 191 +++++++++++++++++++++++ src/libslic3r/calib.hpp | 25 +++ src/slic3r/GUI/GLToolbar.cpp | 3 + src/slic3r/GUI/GLToolbar.hpp | 3 + src/slic3r/GUI/GUI_App.cpp | 4 +- src/slic3r/GUI/MainFrame.cpp | 45 ++++++ src/slic3r/GUI/MainFrame.hpp | 1 + src/slic3r/GUI/Plater.cpp | 43 +++++- src/slic3r/GUI/Plater.hpp | 2 +- 13 files changed, 475 insertions(+), 154 deletions(-) create mode 100644 src/libslic3r/calib.cpp create mode 100644 src/libslic3r/calib.hpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index a10cc5aa1..5605b36d4 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -369,6 +369,8 @@ set(lisbslic3r_sources Arachne/WallToolPaths.cpp Shape/TextShape.hpp Shape/TextShape.cpp + calib.hpp + calib.cpp ) if (APPLE) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 63853d48a..0664ea249 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -36,7 +36,7 @@ #include "SVG.hpp" #include - +#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>> 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>> 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)); diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index ccf254c57..52ae3b8d5 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -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 &by_region); - std::string extrude_infill(const Print &print, const std::vector &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& by_region); + std::string extrude_infill(const Print& print, const std::vector& by_region, bool ironing); + std::string extrude_support(const ExtrusionEntityCollection& support_fills); std::set m_objsWithBrim; // indicates the objs with brim std::set m_objSupportsWithBrim; // indicates the objs' supports with brim // Cache for custom seam enforcers/blockers for each layer. diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index b7a15f50e..500ce8086 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -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; diff --git a/src/libslic3r/calib.cpp b/src/libslic3r/calib.cpp new file mode 100644 index 000000000..ba30202d8 --- /dev/null +++ b/src/libslic3r/calib.cpp @@ -0,0 +1,191 @@ +#include "calib.hpp" +#include "Point.hpp" +#include "PrintConfig.hpp" +#include "GCodeWriter.hpp" +#include "GCode.hpp" +#include + +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 \ No newline at end of file diff --git a/src/libslic3r/calib.hpp b/src/libslic3r/calib.hpp new file mode 100644 index 000000000..734aaf658 --- /dev/null +++ b/src/libslic3r/calib.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#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 \ No newline at end of file diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp index 6a78edd90..d910e29db 100644 --- a/src/slic3r/GUI/GLToolbar.cpp +++ b/src/slic3r/GUI/GLToolbar.cpp @@ -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); diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp index 09da22d3c..ecdf9c7e0 100644 --- a/src/slic3r/GUI/GLToolbar.hpp +++ b/src/slic3r/GUI/GLToolbar.hpp @@ -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); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index eb68894b7..e23e5b0d9 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -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); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index acc994e18..9b8da6dd5 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -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(); diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 0a0c29561..fc3a7f997 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -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 }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 6f30a7bbe..9ba58fa4d 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -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 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()); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5617853fd..a081c3068 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -217,7 +217,7 @@ public: bool open_3mf_file(const fs::path &file_path); int get_3mf_file_count(std::vector 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();