mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-11-01 13:12:38 -06:00
Merge branch 'SoftFever' into feature/small_perimeter
This commit is contained in:
commit
397e0f0a29
151 changed files with 7256 additions and 357 deletions
|
|
@ -65,19 +65,19 @@ std::string AppConfig::get_hms_host()
|
|||
{
|
||||
std::string sel = get("iot_environment");
|
||||
std::string host = "";
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
if (sel == ENV_DEV_HOST)
|
||||
host = "e-dev.bambu-lab.com";
|
||||
else if (sel == ENV_QAT_HOST)
|
||||
host = "e-qa.bambu-lab.com";
|
||||
else if (sel == ENV_PRE_HOST)
|
||||
host = "e-pre.bambu-lab.com";
|
||||
else if (sel == ENV_PRODUCT_HOST)
|
||||
host = "e.bambulab.com";
|
||||
return host;
|
||||
#else
|
||||
// #if !BBL_RELEASE_TO_PUBLIC
|
||||
// if (sel == ENV_DEV_HOST)
|
||||
// host = "e-dev.bambu-lab.com";
|
||||
// else if (sel == ENV_QAT_HOST)
|
||||
// host = "e-qa.bambu-lab.com";
|
||||
// else if (sel == ENV_PRE_HOST)
|
||||
// host = "e-pre.bambu-lab.com";
|
||||
// else if (sel == ENV_PRODUCT_HOST)
|
||||
// host = "e.bambulab.com";
|
||||
// return host;
|
||||
// #else
|
||||
return "e.bambulab.com";
|
||||
#endif
|
||||
// #endif
|
||||
}
|
||||
|
||||
void AppConfig::reset()
|
||||
|
|
@ -293,15 +293,15 @@ void AppConfig::set_defaults()
|
|||
set("curr_bed_type", "0");
|
||||
}
|
||||
|
||||
#if BBL_RELEASE_TO_PUBLIC
|
||||
// #if BBL_RELEASE_TO_PUBLIC
|
||||
if (get("iot_environment").empty()) {
|
||||
set("iot_environment", "3");
|
||||
}
|
||||
#else
|
||||
if (get("iot_environment").empty()) {
|
||||
set("iot_environment", "1");
|
||||
}
|
||||
#endif
|
||||
// #else
|
||||
// if (get("iot_environment").empty()) {
|
||||
// set("iot_environment", "1");
|
||||
// }
|
||||
// #endif
|
||||
|
||||
// Remove legacy window positions/sizes
|
||||
erase("app", "main_frame_maximized");
|
||||
|
|
@ -1030,29 +1030,29 @@ void AppConfig::update_last_backup_dir(const std::string& dir)
|
|||
|
||||
std::string AppConfig::get_region()
|
||||
{
|
||||
#if BBL_RELEASE_TO_PUBLIC
|
||||
// #if BBL_RELEASE_TO_PUBLIC
|
||||
return this->get("region");
|
||||
#else
|
||||
std::string sel = get("iot_environment");
|
||||
std::string region;
|
||||
if (sel == ENV_DEV_HOST)
|
||||
region = "ENV_CN_DEV";
|
||||
else if (sel == ENV_QAT_HOST)
|
||||
region = "ENV_CN_QA";
|
||||
else if (sel == ENV_PRE_HOST)
|
||||
region = "ENV_CN_PRE";
|
||||
if (region.empty())
|
||||
return this->get("region");
|
||||
return region;
|
||||
#endif
|
||||
// #else
|
||||
// std::string sel = get("iot_environment");
|
||||
// std::string region;
|
||||
// if (sel == ENV_DEV_HOST)
|
||||
// region = "ENV_CN_DEV";
|
||||
// else if (sel == ENV_QAT_HOST)
|
||||
// region = "ENV_CN_QA";
|
||||
// else if (sel == ENV_PRE_HOST)
|
||||
// region = "ENV_CN_PRE";
|
||||
// if (region.empty())
|
||||
// return this->get("region");
|
||||
// return region;
|
||||
// #endif
|
||||
}
|
||||
|
||||
std::string AppConfig::get_country_code()
|
||||
{
|
||||
std::string region = get_region();
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
if (is_engineering_region()) { return region; }
|
||||
#endif
|
||||
// #if !BBL_RELEASE_TO_PUBLIC
|
||||
// if (is_engineering_region()) { return region; }
|
||||
// #endif
|
||||
if (region == "CHN" || region == "China")
|
||||
return "CN";
|
||||
else if (region == "USA")
|
||||
|
|
|
|||
|
|
@ -55,6 +55,16 @@ inline bool is_perimeter(ExtrusionRole role)
|
|||
|| role == erOverhangPerimeter;
|
||||
}
|
||||
|
||||
inline bool is_internal_perimeter(ExtrusionRole role)
|
||||
{
|
||||
return role == erPerimeter;
|
||||
}
|
||||
|
||||
inline bool is_external_perimeter(ExtrusionRole role)
|
||||
{
|
||||
return role == erExternalPerimeter;
|
||||
}
|
||||
|
||||
inline bool is_infill(ExtrusionRole role)
|
||||
{
|
||||
return role == erBridgeInfill
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ struct SurfaceFillParams
|
|||
this->overlap == rhs.overlap &&
|
||||
this->angle == rhs.angle &&
|
||||
this->bridge == rhs.bridge &&
|
||||
// this->bridge_angle == rhs.bridge_angle &&
|
||||
this->bridge_angle == rhs.bridge_angle &&
|
||||
this->density == rhs.density &&
|
||||
// this->dont_adjust == rhs.dont_adjust &&
|
||||
this->anchor_length == rhs.anchor_length &&
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#include "libslic3r.h"
|
||||
#include "LocalesUtils.hpp"
|
||||
#include "libslic3r/format.hpp"
|
||||
|
||||
#include "Time.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <chrono>
|
||||
|
|
@ -79,7 +79,7 @@ static const float g_min_purge_volume = 100.f;
|
|||
static const float g_purge_volume_one_time = 135.f;
|
||||
static const int g_max_flush_count = 4;
|
||||
|
||||
bool GCode::gcode_label_objects = false;
|
||||
bool GCode::gcode_label_objects = true;
|
||||
|
||||
// Only add a newline in case the current G-code does not end with a newline.
|
||||
static inline void check_add_eol(std::string& gcode)
|
||||
|
|
@ -908,6 +908,11 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
|
|||
BOOST_LOG_TRIVIAL(info) << boost::format("Will export G-code to %1% soon")%path;
|
||||
print->set_started(psGCodeExport);
|
||||
|
||||
if (print->is_BBL_printer())
|
||||
gcode_label_objects = false;
|
||||
else
|
||||
gcode_label_objects = true;
|
||||
|
||||
// check if any custom gcode contains keywords used by the gcode processor to
|
||||
// produce time estimation and gcode toolpaths
|
||||
std::vector<std::pair<std::string, std::string>> validation_res = DoExport::validate_custom_gcode(*print);
|
||||
|
|
@ -1164,10 +1169,10 @@ namespace DoExport {
|
|||
print_statistics.clear();
|
||||
print_statistics.total_toolchanges = std::max(0, wipe_tower_data.number_of_toolchanges);
|
||||
if (! extruders.empty()) {
|
||||
//std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
|
||||
//std::pair<std::string, unsigned int> out_filament_used_cm3("; filament used [cm3] = ", 0);
|
||||
//std::pair<std::string, unsigned int> out_filament_used_g ("; filament used [g] = ", 0);
|
||||
//std::pair<std::string, unsigned int> out_filament_cost ("; filament cost = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_mm ("; filament used [mm] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_cm3("; filament used [cm3] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_used_g ("; filament used [g] = ", 0);
|
||||
std::pair<std::string, unsigned int> out_filament_cost ("; filament cost = ", 0);
|
||||
for (const Extruder &extruder : extruders) {
|
||||
double used_filament = extruder.used_filament() + (has_wipe_tower ? wipe_tower_data.used_filament[extruder.id()] : 0.f);
|
||||
double extruded_volume = extruder.extruded_volume() + (has_wipe_tower ? wipe_tower_data.used_filament[extruder.id()] * 2.4052f : 0.f); // assumes 1.75mm filament diameter
|
||||
|
|
@ -1187,14 +1192,14 @@ namespace DoExport {
|
|||
dst.first += buf;
|
||||
++ dst.second;
|
||||
};
|
||||
//append(out_filament_used_mm, "%.2lf", used_filament);
|
||||
//append(out_filament_used_cm3, "%.2lf", extruded_volume * 0.001);
|
||||
append(out_filament_used_mm, "%.2lf", used_filament);
|
||||
append(out_filament_used_cm3, "%.2lf", extruded_volume * 0.001);
|
||||
if (filament_weight > 0.) {
|
||||
print_statistics.total_weight = print_statistics.total_weight + filament_weight;
|
||||
//append(out_filament_used_g, "%.2lf", filament_weight);
|
||||
append(out_filament_used_g, "%.2lf", filament_weight);
|
||||
if (filament_cost > 0.) {
|
||||
print_statistics.total_cost = print_statistics.total_cost + filament_cost;
|
||||
//append(out_filament_cost, "%.2lf", filament_cost);
|
||||
append(out_filament_cost, "%.2lf", filament_cost);
|
||||
}
|
||||
}
|
||||
print_statistics.total_used_filament += used_filament;
|
||||
|
|
@ -1202,12 +1207,12 @@ namespace DoExport {
|
|||
print_statistics.total_wipe_tower_filament += has_wipe_tower ? used_filament - extruder.used_filament() : 0.;
|
||||
print_statistics.total_wipe_tower_cost += has_wipe_tower ? (extruded_volume - extruder.extruded_volume())* extruder.filament_density() * 0.001 * extruder.filament_cost() * 0.001 : 0.;
|
||||
}
|
||||
//filament_stats_string_out += out_filament_used_mm.first;
|
||||
//filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
||||
//if (out_filament_used_g.second)
|
||||
//filament_stats_string_out += "\n" + out_filament_used_g.first;
|
||||
//if (out_filament_cost.second)
|
||||
// filament_stats_string_out += "\n" + out_filament_cost.first;
|
||||
filament_stats_string_out += out_filament_used_mm.first;
|
||||
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
||||
if (out_filament_used_g.second)
|
||||
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
||||
if (out_filament_cost.second)
|
||||
filament_stats_string_out += "\n" + out_filament_cost.first;
|
||||
}
|
||||
return filament_stats_string_out;
|
||||
}
|
||||
|
|
@ -1285,7 +1290,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
|
||||
// modifies m_silent_time_estimator_enabled
|
||||
DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled);
|
||||
|
||||
const bool is_bbl_printers = print.is_BBL_printer();
|
||||
// resets analyzer's tracking data
|
||||
m_last_height = 0.f;
|
||||
m_last_layer_z = 0.f;
|
||||
|
|
@ -1349,30 +1354,65 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str());
|
||||
file.write_format("; HEADER_BLOCK_END\n\n");
|
||||
|
||||
//BBS: write global config at the beginning of gcode file because printer need these config information
|
||||
// Append full config, delimited by two 'phony' configuration keys CONFIG_BLOCK_START and CONFIG_BLOCK_END.
|
||||
// The delimiters are structured as configuration key / value pairs to be parsable by older versions of PrusaSlicer G-code viewer.
|
||||
|
||||
// BBS: write global config at the beginning of gcode file because printer
|
||||
// need these config information
|
||||
// Append full config, delimited by two 'phony' configuration keys
|
||||
// CONFIG_BLOCK_START and CONFIG_BLOCK_END. The delimiters are structured
|
||||
// as configuration key / value pairs to be parsable by older versions of
|
||||
// PrusaSlicer G-code viewer.
|
||||
{
|
||||
if (is_bbl_printers) {
|
||||
file.write("; CONFIG_BLOCK_START\n");
|
||||
std::string full_config;
|
||||
append_full_config(print, full_config);
|
||||
if (!full_config.empty())
|
||||
file.write(full_config);
|
||||
file.write(full_config);
|
||||
|
||||
// SoftFever: write compatiple image
|
||||
std::vector<int> temps_per_bed;
|
||||
int first_layer_bed_temperature = 0;
|
||||
get_bed_temperature(0, true, temps_per_bed,
|
||||
first_layer_bed_temperature);
|
||||
file.write_format("; first_layer_bed_temperature = %d\n",
|
||||
first_layer_bed_temperature);
|
||||
file.write_format(
|
||||
"; first_layer_temperature = %d\n",
|
||||
print.config().nozzle_temperature_initial_layer.get_at(0));
|
||||
file.write("; CONFIG_BLOCK_END\n\n");
|
||||
} else {
|
||||
file.write_format("; hack-fix: write fake slicer info here so that "
|
||||
"Moonraker will extract thumbs.\n");
|
||||
file.write_format(
|
||||
"; %s\n\n",
|
||||
std::string(
|
||||
std::string("generated by SuperSlicer " SLIC3R_VERSION " on ") +
|
||||
Slic3r::Utils::utc_timestamp())
|
||||
.c_str());
|
||||
|
||||
// BBS: add plate id into thumbnail render logic
|
||||
// if (const auto [thumbnails, thumbnails_format] = std::make_pair(
|
||||
// print.full_print_config().option<ConfigOptionPoints>("thumbnails"),
|
||||
// print.full_print_config().option<ConfigOptionEnum<GCodeThumbnailsFormat>>("thumbnails_format"));
|
||||
// thumbnails)
|
||||
// GCodeThumbnails::export_thumbnails_to_file(
|
||||
// thumbnail_cb, thumbnails->values, thumbnails_format ? thumbnails_format->value : GCodeThumbnailsFormat::PNG,
|
||||
// [&file](const char* sz) { file.write(sz); },
|
||||
// [&print]() { print.throw_if_canceled(); });
|
||||
|
||||
|
||||
DoExport::export_thumbnails_to_file(
|
||||
thumbnail_cb, print.get_plate_index(), print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values,
|
||||
[&file](const char *sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
}
|
||||
}
|
||||
|
||||
//BBS: add plate id into thumbnail render logic
|
||||
//DoExport::export_thumbnails_to_file(thumbnail_cb, print.get_plate_index(), THUMBNAIL_SIZE,
|
||||
// [&file](const char* sz) { file.write(sz); },
|
||||
// [&print]() { print.throw_if_canceled(); });
|
||||
|
||||
|
||||
|
||||
// Write some terse information on the slicing parameters.
|
||||
const PrintObject *first_object = print.objects().front();
|
||||
const double layer_height = first_object->config().layer_height.value;
|
||||
const double initial_layer_print_height = print.config().initial_layer_print_height.value;
|
||||
//BBS: remove useless information in gcode file
|
||||
#if 0
|
||||
for (size_t region_id = 0; region_id < print.num_print_regions(); ++ region_id) {
|
||||
const PrintRegion ®ion = print.get_print_region(region_id);
|
||||
file.write_format("; external perimeters extrusion width = %.2fmm\n", region.flow(*first_object, frExternalPerimeter, layer_height).width());
|
||||
|
|
@ -1386,8 +1426,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
file.write_format("; first layer extrusion width = %.2fmm\n", region.flow(*first_object, frPerimeter, initial_layer_print_height, true).width());
|
||||
file.write_format("\n");
|
||||
}
|
||||
print.throw_if_canceled();
|
||||
#endif
|
||||
|
||||
file.write_format("; EXECUTABLE_BLOCK_START\n");
|
||||
// adds tags for time estimators
|
||||
|
|
@ -1512,7 +1550,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
m_placeholder_parser.set("first_layer_print_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
|
||||
m_placeholder_parser.set("first_layer_print_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
|
||||
}
|
||||
|
||||
float outer_wall_volumetric_speed = 0.0f;
|
||||
{
|
||||
int curr_bed_type = m_config.curr_bed_type.getInt();
|
||||
|
||||
|
|
@ -1524,6 +1562,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
m_placeholder_parser.set("bed_temperature", new ConfigOptionInts(*bed_temp_opt));
|
||||
m_placeholder_parser.set("bed_temperature_initial_layer_single", new ConfigOptionInt(first_bed_temp_opt->get_at(initial_extruder_id)));
|
||||
m_placeholder_parser.set("bed_temperature_initial_layer_vector", new ConfigOptionString(""));
|
||||
m_placeholder_parser.set("chamber_temperature",new ConfigOptionInt(m_config.chamber_temperature));
|
||||
|
||||
//BBS: calculate the volumetric speed of outer wall. Ignore pre-object setting and multi-filament, and just use the default setting
|
||||
{
|
||||
|
|
@ -1535,7 +1574,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
}
|
||||
Flow outer_wall_flow = Flow(outer_wall_line_width, m_config.layer_height, m_config.nozzle_diameter.get_at(initial_extruder_id));
|
||||
float outer_wall_speed = print.default_region_config().outer_wall_speed.value;
|
||||
float outer_wall_volumetric_speed = outer_wall_speed * outer_wall_flow.mm3_per_mm();
|
||||
outer_wall_volumetric_speed = outer_wall_speed * outer_wall_flow.mm3_per_mm();
|
||||
if (outer_wall_volumetric_speed > filament_max_volumetric_speed)
|
||||
outer_wall_volumetric_speed = filament_max_volumetric_speed;
|
||||
m_placeholder_parser.set("outer_wall_volumetric_speed", new ConfigOptionFloat(outer_wall_volumetric_speed));
|
||||
|
|
@ -1598,8 +1637,23 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
if (this->m_objsWithBrim.empty() && this->m_objSupportsWithBrim.empty()) m_brim_done = true;
|
||||
|
||||
//BBS: open spaghetti detector
|
||||
// if (print.config().spaghetti_detector.value)
|
||||
file.write("M981 S1 P20000 ;open spaghetti detector\n");
|
||||
if (is_bbl_printers) {
|
||||
// if (print.config().spaghetti_detector.value)
|
||||
file.write("M981 S1 P20000 ;open spaghetti detector\n");
|
||||
file.write_format("M900 K%.3f M%0.3f ; Override pressure advance value\n",
|
||||
m_config.pressure_advance.values.front(),
|
||||
outer_wall_volumetric_speed / (1.75 * 1.75 / 4 * 3.14) *
|
||||
m_config.pressure_advance.values.front());
|
||||
} else {
|
||||
if (m_config.enable_pressure_advance.value) {
|
||||
if(print.config().gcode_flavor.value == gcfKlipper)
|
||||
file.write_format("SET_PRESSURE_ADVANCE ADVANCE=%.3f ; Override pressure advance value\n",
|
||||
m_config.pressure_advance.values.front());
|
||||
else
|
||||
file.write_format("M900 K%.3f ; Override pressure advance value\n",
|
||||
m_config.pressure_advance.values.front());
|
||||
}
|
||||
}
|
||||
|
||||
// Do all objects for each layer.
|
||||
if (print.config().print_sequence == PrintSequence::ByObject) {
|
||||
|
|
@ -1663,7 +1717,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
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 (m_second_layer_things_done) {
|
||||
if (is_bbl_printers && m_second_layer_things_done) {
|
||||
file.write("; close powerlost recovery\n");
|
||||
file.write("M1003 S0\n");
|
||||
}
|
||||
|
|
@ -1734,7 +1788,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
this->process_layers(print, tool_ordering, print_object_instances_ordering, layers_to_print, file);
|
||||
//BBS: close powerlost recovery
|
||||
{
|
||||
if (m_second_layer_things_done) {
|
||||
if (is_bbl_printers && m_second_layer_things_done) {
|
||||
file.write("; close powerlost recovery\n");
|
||||
file.write("M1003 S0\n");
|
||||
}
|
||||
|
|
@ -1754,10 +1808,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
file.write(m_writer.set_fan(0));
|
||||
//BBS: make sure the additional fan is closed when end
|
||||
file.write(m_writer.set_additional_fan(0));
|
||||
//BBS: close spaghetti detector
|
||||
//Note: M981 is also used to tell xcam the last layer is finished, so we need always send it even if spaghetti option is disabled.
|
||||
//if (print.config().spaghetti_detector.value)
|
||||
file.write("M981 S0 P20000 ; close spaghetti detector\n");
|
||||
if (is_bbl_printers) {
|
||||
//BBS: close spaghetti detector
|
||||
//Note: M981 is also used to tell xcam the last layer is finished, so we need always send it even if spaghetti option is disabled.
|
||||
//if (print.config().spaghetti_detector.value)
|
||||
file.write("M981 S0 P20000 ; close spaghetti detector\n");
|
||||
}
|
||||
|
||||
// adds tag for processor
|
||||
file.write_format(";%s%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Role).c_str(), ExtrusionEntity::role_to_string(erCustom).c_str());
|
||||
|
|
@ -1800,11 +1856,41 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
m_writer.extruders(),
|
||||
// Modifies
|
||||
print.m_print_statistics));
|
||||
//file.write("\n");
|
||||
//file.write_format("; total filament weight [g] = %.2lf\n", print.m_print_statistics.total_weight);
|
||||
//file.write_format("; total filament cost = %.2lf\n", print.m_print_statistics.total_cost);
|
||||
//if (print.m_print_statistics.total_toolchanges > 0)
|
||||
// file.write_format("; total filament change = %i\n", print.m_print_statistics.total_toolchanges);
|
||||
if (!is_bbl_printers) {
|
||||
file.write("\n");
|
||||
file.write("; CONFIG_BLOCK_START\n");
|
||||
std::string full_config;
|
||||
append_full_config(print, full_config);
|
||||
if (!full_config.empty())
|
||||
file.write(full_config);
|
||||
|
||||
// SoftFever: write compatiple info
|
||||
std::vector<int> temps_per_bed;
|
||||
int first_layer_bed_temperature = 0;
|
||||
get_bed_temperature(0, true, temps_per_bed, first_layer_bed_temperature);
|
||||
file.write_format("; first_layer_bed_temperature = %d\n",
|
||||
first_layer_bed_temperature);
|
||||
file.write_format(
|
||||
"; first_layer_temperature = %d\n",
|
||||
print.config().nozzle_temperature_initial_layer.get_at(0));
|
||||
file.write("; CONFIG_BLOCK_END\n\n");
|
||||
file.write_format("; total filament used [g] = %.2lf\n",
|
||||
print.m_print_statistics.total_weight);
|
||||
file.write_format("; total filament cost = %.2lf\n",
|
||||
print.m_print_statistics.total_cost);
|
||||
if (print.m_print_statistics.total_toolchanges > 0)
|
||||
file.write_format("; total filament change = %i\n",
|
||||
print.m_print_statistics.total_toolchanges);
|
||||
|
||||
file.write_format("; total layers count = %i\n", m_layer_count);
|
||||
file.write_format(
|
||||
";%s\n",
|
||||
GCodeProcessor::reserved_tag(
|
||||
GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder)
|
||||
.c_str());
|
||||
|
||||
}
|
||||
file.write("\n");
|
||||
|
||||
print.throw_if_canceled();
|
||||
}
|
||||
|
|
@ -2501,28 +2587,41 @@ GCode::LayerResult GCode::process_layer(
|
|||
double acceleration = m_config.initial_layer_acceleration.value;
|
||||
gcode += m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5));
|
||||
}
|
||||
|
||||
if (m_config.default_jerk.value > 0 && m_config.initial_layer_jerk.value > 0) {
|
||||
double jerk = m_config.initial_layer_jerk.value;
|
||||
gcode += m_writer.set_jerk_xy((unsigned int)floor(jerk + 0.5));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (! first_layer && ! m_second_layer_things_done) {
|
||||
//BBS: open powerlost recovery
|
||||
if (print.is_BBL_printer()) {
|
||||
// BBS: open powerlost recovery
|
||||
{
|
||||
gcode += "; open powerlost recovery\n";
|
||||
gcode += "M1003 S1\n";
|
||||
gcode += "; open powerlost recovery\n";
|
||||
gcode += "M1003 S1\n";
|
||||
}
|
||||
// BBS: open first layer inspection at second layer
|
||||
if (print.config().scan_first_layer.value) {
|
||||
// BBS: retract first to avoid droping when scan model
|
||||
gcode += this->retract();
|
||||
gcode += "M976 S1 P1 ; scan model before printing 2nd layer\n";
|
||||
gcode += "M400 P100\n";
|
||||
gcode += this->unretract();
|
||||
// BBS: retract first to avoid droping when scan model
|
||||
gcode += this->retract();
|
||||
gcode += "M976 S1 P1 ; scan model before printing 2nd layer\n";
|
||||
gcode += "M400 P100\n";
|
||||
gcode += this->unretract();
|
||||
}
|
||||
|
||||
}
|
||||
//BBS: reset acceleration at sencond layer
|
||||
if (m_config.default_acceleration.value > 0 && m_config.initial_layer_acceleration.value > 0) {
|
||||
double acceleration = m_config.default_acceleration.value;
|
||||
gcode += m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5));
|
||||
}
|
||||
|
||||
if (m_config.default_jerk.value > 0 && m_config.initial_layer_jerk.value > 0) {
|
||||
double jerk = m_config.default_jerk.value;
|
||||
gcode += m_writer.set_jerk_xy((unsigned int)floor(jerk + 0.5));
|
||||
}
|
||||
|
||||
// Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
|
||||
// nozzle_temperature_initial_layer vs. temperature settings.
|
||||
for (const Extruder &extruder : m_writer.extruders()) {
|
||||
|
|
@ -3237,9 +3336,13 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||
}
|
||||
|
||||
//BBS: don't reset acceleration when printing first layer. During first layer, acceleration is always same value.
|
||||
if (!this->on_first_layer())
|
||||
if (!this->on_first_layer()){
|
||||
// reset acceleration
|
||||
gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));
|
||||
if(m_config.default_acceleration.value > 0)
|
||||
gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));
|
||||
if(m_config.default_jerk.value > 0)
|
||||
gcode += m_writer.set_jerk_xy((unsigned int)(m_config.default_jerk.value + 0.5));
|
||||
}
|
||||
|
||||
// BBS
|
||||
if (m_wipe.enable) {
|
||||
|
|
@ -3312,9 +3415,12 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
|
|||
m_wipe.path.reverse();
|
||||
}
|
||||
//BBS: don't reset acceleration when printing first layer. During first layer, acceleration is always same value.
|
||||
if (!this->on_first_layer())
|
||||
if (!this->on_first_layer()) {
|
||||
// reset acceleration
|
||||
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
||||
if(m_config.default_jerk.value > 0)
|
||||
gcode += m_writer.set_jerk_xy((unsigned int)floor(m_config.default_jerk.value + 0.5));
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
|
@ -3340,9 +3446,13 @@ std::string GCode::extrude_path(ExtrusionPath path, std::string description, dou
|
|||
m_wipe.path.reverse();
|
||||
}
|
||||
//BBS: don't reset acceleration when printing first layer. During first layer, acceleration is always same value.
|
||||
if (!this->on_first_layer())
|
||||
if (!this->on_first_layer()){
|
||||
// reset acceleration
|
||||
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
||||
if(m_config.default_jerk.value > 0)
|
||||
gcode += m_writer.set_jerk_xy((unsigned int)floor(m_config.default_jerk.value + 0.5));
|
||||
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
|
@ -3541,6 +3651,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
} else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) {
|
||||
acceleration = m_config.perimeter_acceleration.value;
|
||||
#endif
|
||||
} else if (m_config.outer_wall_acceleration.value > 0 && is_external_perimeter(path.role())) {
|
||||
acceleration = m_config.outer_wall_acceleration.value;
|
||||
} else if (m_config.inner_wall_acceleration.value > 0 && is_internal_perimeter(path.role())) {
|
||||
acceleration = m_config.inner_wall_acceleration.value;
|
||||
} else if (m_config.top_surface_acceleration.value > 0 && is_top_surface(path.role())) {
|
||||
acceleration = m_config.top_surface_acceleration.value;
|
||||
} else {
|
||||
|
|
@ -3549,6 +3663,23 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
gcode += m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5));
|
||||
}
|
||||
|
||||
// adjust X Y jerk
|
||||
if (m_config.default_jerk.value > 0) {
|
||||
double jerk;
|
||||
if (this->on_first_layer() && m_config.initial_layer_jerk.value > 0) {
|
||||
jerk = m_config.initial_layer_jerk.value;
|
||||
} else if (m_config.outer_wall_jerk.value > 0 && is_external_perimeter(path.role())) {
|
||||
jerk = m_config.outer_wall_jerk.value;
|
||||
} else if (m_config.inner_wall_jerk.value > 0 && is_internal_perimeter(path.role())) {
|
||||
jerk = m_config.inner_wall_jerk.value;
|
||||
} else if (m_config.top_surface_jerk.value > 0 && is_top_surface(path.role())) {
|
||||
jerk = m_config.top_surface_jerk.value;
|
||||
} else {
|
||||
jerk = m_config.default_jerk.value;
|
||||
}
|
||||
gcode += m_writer.set_jerk_xy((unsigned int)floor(jerk + 0.5));
|
||||
}
|
||||
|
||||
// calculate extrusion length per distance unit
|
||||
double e_per_mm = m_writer.extruder()->e_per_mm3() * path.mm3_per_mm;
|
||||
|
||||
|
|
@ -3761,7 +3892,34 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
|
|||
bool could_be_wipe_disabled = false;
|
||||
// Save state of use_external_mp_once for the case that will be needed to call twice m_avoid_crossing_perimeters.travel_to.
|
||||
const bool used_external_mp_once = m_avoid_crossing_perimeters.used_external_mp_once();
|
||||
std::string gcode;
|
||||
|
||||
// SoftFever
|
||||
if (this->on_first_layer()) {
|
||||
if(m_config.default_acceleration.value > 0)
|
||||
{
|
||||
auto jerk = (unsigned int)floor(m_config.initial_layer_jerk.value + 0.5);
|
||||
auto accel = (unsigned int)floor(m_config.initial_layer_acceleration.value + 0.5);
|
||||
if(jerk > 0)
|
||||
gcode += m_writer.set_jerk_xy(jerk);
|
||||
|
||||
if(accel > 0)
|
||||
gcode += m_writer.set_acceleration(accel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_config.default_jerk.value > 0)
|
||||
{
|
||||
auto jerk = (unsigned int)floor(m_config.travel_jerk.value + 0.5);
|
||||
auto accel = (unsigned int)floor(m_config.travel_acceleration.value + 0.5);
|
||||
if(jerk > 0)
|
||||
gcode += m_writer.set_jerk_xy(jerk);
|
||||
|
||||
if(accel > 0)
|
||||
gcode += m_writer.set_acceleration(accel);
|
||||
}
|
||||
}
|
||||
// if a retraction would be needed, try to use reduce_crossing_wall to plan a
|
||||
// multi-hop travel path inside the configuration space
|
||||
if (needs_retraction
|
||||
|
|
@ -3777,7 +3935,6 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
|
|||
m_avoid_crossing_perimeters.reset_once_modifiers();
|
||||
|
||||
// generate G-code for the travel move
|
||||
std::string gcode;
|
||||
if (needs_retraction) {
|
||||
if (m_config.reduce_crossing_wall && could_be_wipe_disabled)
|
||||
m_wipe.reset_path();
|
||||
|
|
@ -3808,9 +3965,9 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
|
|||
if (i == travel.size() - 1 && !m_spiral_vase) {
|
||||
Vec2d dest2d = this->point_to_gcode(travel.points[i]);
|
||||
Vec3d dest3d(dest2d(0), dest2d(1), m_nominal_z);
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment);
|
||||
gcode += m_writer.travel_to_xyz(dest3d, comment+" travel_to_xyz");
|
||||
} else {
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment);
|
||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment+" travel_to_xy");
|
||||
}
|
||||
}
|
||||
this->set_last_pos(travel.points.back());
|
||||
|
|
@ -3884,7 +4041,11 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction)
|
|||
if (m_writer.extruder()->retraction_length() > 0) {
|
||||
// BBS: don't do lazy_lift when enable spiral vase
|
||||
size_t extruder_id = m_writer.extruder()->id();
|
||||
gcode += m_writer.lift(!m_spiral_vase ? LiftType::SpiralLift : LiftType::NormalLift);
|
||||
auto _lift = m_config.z_lift_type.value;
|
||||
if(m_spiral_vase)
|
||||
_lift = NormalLift;
|
||||
|
||||
gcode += m_writer.lift(_lift);
|
||||
}
|
||||
|
||||
return gcode;
|
||||
|
|
|
|||
|
|
@ -453,10 +453,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
|
|||
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
char buf[128];
|
||||
//sprintf(buf, "; estimated printing time (%s mode) = %s\n",
|
||||
// (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
|
||||
// get_time_dhms(machine.time).c_str());
|
||||
sprintf(buf, "; total estimated time: %s\n", get_time_dhms(machine.time).c_str());
|
||||
sprintf(buf, "; estimated printing time: %s\n", get_time_dhms(machine.time).c_str());
|
||||
ret += buf;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,8 +99,7 @@ public:
|
|||
}
|
||||
|
||||
WipeTowerWriter& disable_linear_advance() {
|
||||
m_gcode += (m_gcode_flavor == gcfRepRapSprinter || m_gcode_flavor == gcfRepRapFirmware
|
||||
? (std::string("M572 D") + std::to_string(m_current_tool) + " S0\n")
|
||||
m_gcode += (m_gcode_flavor == gcfKlipper ? (std::string("SET_PRESSURE_ADVANCE ADVANCE=0\n"))
|
||||
: std::string("M900 K0\n"));
|
||||
return *this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,15 +15,16 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
const bool GCodeWriter::full_gcode_comment = false;
|
||||
const bool GCodeWriter::full_gcode_comment = true;
|
||||
const double GCodeWriter::slope_threshold = 3 * PI / 180;
|
||||
|
||||
void GCodeWriter::apply_print_config(const PrintConfig &print_config)
|
||||
{
|
||||
this->config.apply(print_config, true);
|
||||
m_single_extruder_multi_material = print_config.single_extruder_multi_material.value;
|
||||
bool is_marlin = print_config.gcode_flavor.value == gcfMarlinLegacy || print_config.gcode_flavor.value == gcfMarlinFirmware;
|
||||
bool is_marlin = print_config.gcode_flavor.value == gcfMarlinLegacy || print_config.gcode_flavor.value == gcfMarlinFirmware || print_config.gcode_flavor.value == gcfKlipper;
|
||||
m_max_acceleration = std::lrint(is_marlin ? print_config.machine_max_acceleration_extruding.values.front() : 0);
|
||||
m_max_jerk = std::lrint(is_marlin ? std::min(print_config.machine_max_jerk_x.values.front(), print_config.machine_max_jerk_y.values.front()) : 0);
|
||||
}
|
||||
|
||||
void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
|
||||
|
|
@ -54,7 +55,8 @@ std::string GCodeWriter::preamble()
|
|||
FLAVOR_IS(gcfMarlinFirmware) ||
|
||||
FLAVOR_IS(gcfTeacup) ||
|
||||
FLAVOR_IS(gcfRepetier) ||
|
||||
FLAVOR_IS(gcfSmoothie))
|
||||
FLAVOR_IS(gcfSmoothie) ||
|
||||
FLAVOR_IS(gcfKlipper))
|
||||
{
|
||||
if (RELATIVE_E_AXIS) {
|
||||
gcode << "M83 ; only support relative e\n";
|
||||
|
|
@ -183,6 +185,30 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
|
|||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_jerk_xy(unsigned int jerk)
|
||||
{
|
||||
// Clamp the jerk to the allowed maximum.
|
||||
if (m_max_jerk > 0 && jerk > m_max_jerk)
|
||||
jerk = m_max_jerk;
|
||||
|
||||
if (jerk < 1 || jerk == m_last_jerk)
|
||||
return std::string();
|
||||
|
||||
m_last_jerk = jerk;
|
||||
|
||||
std::ostringstream gcode;
|
||||
if(FLAVOR_IS(gcfKlipper))
|
||||
gcode << "SET_VELOCITY_LIMIT SQUARE_CORNER_VELOCITY=" << jerk;
|
||||
else
|
||||
gcode << "M205 X" << jerk << " Y" << jerk;
|
||||
|
||||
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust jerk";
|
||||
gcode << "\n";
|
||||
|
||||
return gcode.str();
|
||||
|
||||
}
|
||||
|
||||
std::string GCodeWriter::reset_e(bool force)
|
||||
{
|
||||
if (FLAVOR_IS(gcfMach3)
|
||||
|
|
|
|||
|
|
@ -11,12 +11,6 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class LiftType {
|
||||
NormalLift,
|
||||
LazyLift,
|
||||
SpiralLift
|
||||
};
|
||||
|
||||
class GCodeWriter {
|
||||
public:
|
||||
GCodeConfig config;
|
||||
|
|
@ -26,6 +20,7 @@ public:
|
|||
multiple_extruders(false), m_extruder(nullptr),
|
||||
m_single_extruder_multi_material(false),
|
||||
m_last_acceleration(0), m_max_acceleration(0),
|
||||
m_last_jerk(0), m_max_jerk(0),
|
||||
/*m_last_bed_temperature(0), */m_last_bed_temperature_reached(true),
|
||||
m_lifted(0),
|
||||
m_to_lift(0),
|
||||
|
|
@ -51,6 +46,7 @@ public:
|
|||
// BBS
|
||||
std::string set_bed_temperature(std::vector<int> temps_per_bed, int default_temp, bool wait = false);
|
||||
std::string set_acceleration(unsigned int acceleration);
|
||||
std::string set_jerk_xy(unsigned int jerk);
|
||||
std::string reset_e(bool force = false);
|
||||
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
|
||||
// return false if this extruder was already selected
|
||||
|
|
@ -104,6 +100,13 @@ private:
|
|||
// Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware.
|
||||
// If set to zero, the limit is not in action.
|
||||
unsigned int m_max_acceleration;
|
||||
unsigned int m_max_jerk;
|
||||
unsigned int m_last_jerk;
|
||||
|
||||
unsigned int m_travel_acceleration;
|
||||
unsigned int m_travel_jerk;
|
||||
|
||||
|
||||
//BBS
|
||||
unsigned int m_last_additional_fan_speed;
|
||||
// BBS
|
||||
|
|
|
|||
|
|
@ -296,8 +296,10 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||
printf("Processing bridge at layer %zu:\n", this->layer()->id());
|
||||
#endif
|
||||
//BBS: use 0 as custom angle to enable auto detection all the time
|
||||
double custom_angle = Geometry::deg2rad(0.0);
|
||||
if (bd.detect_angle(custom_angle)) {
|
||||
double custom_angle = Geometry::deg2rad(this->region().config().bridge_angle.value);
|
||||
if(custom_angle > 0)
|
||||
bridges[idx_last].bridge_angle = custom_angle;
|
||||
else if (bd.detect_angle(custom_angle)) {
|
||||
bridges[idx_last].bridge_angle = bd.angle;
|
||||
if (this->layer()->object()->has_support()) {
|
||||
// polygons_append(this->bridged, bd.coverage());
|
||||
|
|
|
|||
|
|
@ -412,6 +412,8 @@ void PerimeterGenerator::process()
|
|||
for (const Surface &surface : this->slices->surfaces) {
|
||||
// detect how many perimeters must be generated for this island
|
||||
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
|
||||
if (this->layer_id == 0 && this->config->only_one_wall_first_layer)
|
||||
loop_number = 0;
|
||||
//BBS: set the topmost layer to be one wall
|
||||
if (loop_number > 0 && config->only_one_wall_top && this->upper_slices == nullptr)
|
||||
loop_number = 0;
|
||||
|
|
|
|||
|
|
@ -697,8 +697,9 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
"inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "sparse_infill_speed", "internal_solid_infill_speed",
|
||||
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed",
|
||||
"bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
|
||||
"initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_distance", "skirt_height", "draft_shield",
|
||||
"bridge_speed", "bridge_angle", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
|
||||
"outer_wall_acceleration", "inner_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "travel_acceleration", "skirt_loops", "skirt_distance", "skirt_height", "draft_shield",
|
||||
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk",
|
||||
"brim_width", "brim_object_gap", "brim_type", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers",
|
||||
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
|
||||
"support_base_pattern", "support_base_pattern_spacing", "support_style",
|
||||
|
|
@ -722,14 +723,17 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"detect_narrow_internal_solid_infill",
|
||||
"gcode_add_line_number", "enable_arc_fitting", "infill_combination", "adaptive_layer_height",
|
||||
"support_bottom_interface_spacing", "enable_overhang_speed", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
|
||||
"initial_layer_infill_speed", "only_one_wall_top",
|
||||
"timelapse_type"
|
||||
"initial_layer_infill_speed", "only_one_wall_top", "only_one_wall_first_layer",
|
||||
"timelapse_type",
|
||||
//SoftFever
|
||||
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio"
|
||||
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_filament_options {
|
||||
/*"filament_colour", */"filament_diameter", "filament_type", "filament_soluble", "filament_is_support", "filament_max_volumetric_speed",
|
||||
"filament_flow_ratio", "filament_density", "filament_cost", "filament_minimal_purge_on_wipe_tower",
|
||||
"nozzle_temperature", "nozzle_temperature_initial_layer",
|
||||
"filament_flow_ratio", "enable_pressure_advance", "pressure_advance", "filament_density", "filament_cost", "filament_minimal_purge_on_wipe_tower",
|
||||
"chamber_temperature", "nozzle_temperature", "nozzle_temperature_initial_layer",
|
||||
// BBS
|
||||
"cool_plate_temp", "eng_plate_temp", "hot_plate_temp", "textured_plate_temp", "cool_plate_temp_initial_layer", "eng_plate_temp_initial_layer", "hot_plate_temp_initial_layer","textured_plate_temp_initial_layer",
|
||||
// "bed_type",
|
||||
|
|
@ -757,18 +761,20 @@ static std::vector<std::string> s_Preset_machine_limits_options {
|
|||
|
||||
static std::vector<std::string> s_Preset_printer_options {
|
||||
"printer_technology",
|
||||
"printable_area", "bed_exclude_area", "gcode_flavor",
|
||||
"printable_area", "bed_exclude_area", "gcode_flavor","z_lift_type",
|
||||
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode",
|
||||
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"default_print_profile", "inherits",
|
||||
"silent_mode",
|
||||
// BBS
|
||||
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "machine_pause_gcode", "template_custom_gcode",
|
||||
"nozzle_type", "auxiliary_fan", "nozzle_volume",
|
||||
"nozzle_type", "nozzle_diameter", "auxiliary_fan", "nozzle_volume",
|
||||
//SoftFever
|
||||
"host_type", "print_host", "printhost_apikey",
|
||||
"printhost_cafile","printhost_port","printhost_authorization_type",
|
||||
"printhost_user", "printhost_password", "printhost_ssl_ignore_revoke"
|
||||
"printhost_user",
|
||||
"printhost_password",
|
||||
"printhost_ssl_ignore_revoke", "thumbnails"
|
||||
};
|
||||
|
||||
static std::vector<std::string> s_Preset_sla_print_options {
|
||||
|
|
@ -2238,6 +2244,21 @@ void add_correct_opts_to_diff(const std::string &opt_key, t_config_option_keys&
|
|||
}
|
||||
}
|
||||
|
||||
// template<class T>
|
||||
// void add_correct_opt_to_diff(const std::string &opt_key, t_config_option_keys& vec, const ConfigBase &other, const ConfigBase &this_c)
|
||||
// {
|
||||
// const T* opt_init = static_cast<const T*>(other.option(opt_key));
|
||||
// const T* opt_cur = static_cast<const T*>(this_c.option(opt_key));
|
||||
// int opt_init_max_id = opt_init->values.size() - 1;
|
||||
// for (int i = 0; i < int(opt_cur->values.size()); i++)
|
||||
// {
|
||||
// int init_id = i <= opt_init_max_id ? i : 0;
|
||||
// if (opt_cur->values[i] != opt_init->values[init_id])
|
||||
// vec.emplace_back(opt_key + "#" + std::to_string(i));
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// Use deep_diff to correct return of changed options, considering individual options for each extruder.
|
||||
inline t_config_option_keys deep_diff(const ConfigBase &config_this, const ConfigBase &config_other)
|
||||
{
|
||||
|
|
@ -2248,7 +2269,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
|
|||
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
|
||||
{
|
||||
//BBS: add bed_exclude_area
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers") {
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails") {
|
||||
// Scalar variable, or a vector variable, which is independent from number of extruders,
|
||||
// thus the vector is presented to the user as a single input.
|
||||
diff.emplace_back(opt_key);
|
||||
|
|
@ -2261,6 +2282,7 @@ inline t_config_option_keys deep_diff(const ConfigBase &config_this, const Confi
|
|||
case coBools: add_correct_opts_to_diff<ConfigOptionBools >(opt_key, diff, config_other, config_this); break;
|
||||
case coFloats: add_correct_opts_to_diff<ConfigOptionFloats >(opt_key, diff, config_other, config_this); break;
|
||||
case coStrings: add_correct_opts_to_diff<ConfigOptionStrings >(opt_key, diff, config_other, config_this); break;
|
||||
// case coString: add_correct_opts_to_diff<ConfigOptionString >(opt_key, diff, config_other, config_this); break;
|
||||
case coPercents:add_correct_opts_to_diff<ConfigOptionPercents >(opt_key, diff, config_other, config_this); break;
|
||||
case coPoints: add_correct_opts_to_diff<ConfigOptionPoints >(opt_key, diff, config_other, config_this); break;
|
||||
// BBS
|
||||
|
|
@ -2741,6 +2763,8 @@ void PhysicalPrinterCollection::load_printers(
|
|||
// see https://github.com/prusa3d/PrusaSlicer/issues/732
|
||||
boost::filesystem::path dir = boost::filesystem::absolute(boost::filesystem::path(dir_path) / subdir).make_preferred();
|
||||
m_dir_path = dir.string();
|
||||
if(!boost::filesystem::exists(dir))
|
||||
return;
|
||||
std::string errors_cummulative;
|
||||
// Store the loaded printers into a new vector, otherwise the binary search for already existing presets would be broken.
|
||||
std::deque<PhysicalPrinter> printers_loaded;
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ static std::vector<std::string> s_project_options {
|
|||
"wipe_tower_y",
|
||||
"wipe_tower_rotation_angle",
|
||||
"curr_bed_type",
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
// #if !BBL_RELEASE_TO_PUBLIC
|
||||
"flush_multiplier",
|
||||
#endif
|
||||
// #endif
|
||||
};
|
||||
|
||||
//BBS: add BBL as default
|
||||
|
|
@ -90,7 +90,7 @@ PresetBundle::PresetBundle()
|
|||
for (size_t i = 0; i < 1; ++i) {
|
||||
// The following ugly switch is to avoid printers.preset(0) to return the edited instance, as the 0th default is the current one.
|
||||
Preset &preset = this->printers.default_preset(i);
|
||||
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant"}) preset.config.optptr(key, true);
|
||||
for (const char *key : {"printer_settings_id", "printer_model", "printer_variant", "thumbnails"}) preset.config.optptr(key, true);
|
||||
//if (i == 0) {
|
||||
preset.config.optptr("default_print_profile", true);
|
||||
preset.config.option<ConfigOptionStrings>("default_filament_profile", true);
|
||||
|
|
@ -1419,8 +1419,10 @@ DynamicPrintConfig PresetBundle::full_config() const
|
|||
DynamicPrintConfig PresetBundle::full_config_secure() const
|
||||
{
|
||||
DynamicPrintConfig config = this->full_config();
|
||||
//BBS example: config.erase("print_host");
|
||||
return config;
|
||||
//FIXME legacy, the keys should not be there after conversion to a Physical Printer profile.
|
||||
config.erase("print_host");
|
||||
config.erase("printhost_apikey");
|
||||
config.erase("printhost_cafile"); return config;
|
||||
}
|
||||
|
||||
const std::set<std::string> ignore_settings_list ={
|
||||
|
|
@ -2960,7 +2962,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_
|
|||
//parse error
|
||||
std::string subfile_path = path + "/" + vendor_name + "/" + subfile.second;
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", got error when parse process setting from %1%") % subfile_path;
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly") % subfile_path %vendor_system_path).str());
|
||||
throw ConfigurationError((boost::format("Failed loading configuration file %1%\nSuggest cleaning the directory %2% firstly.\nReason: %3%") % subfile_path %vendor_system_path %reason).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3435,4 +3437,4 @@ void PresetBundle::set_default_suppressed(bool default_suppressed)
|
|||
printers.set_default_suppressed(default_suppressed);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
} // namespace Slic3r
|
||||
|
|
@ -68,7 +68,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
//BBS: add bed_exclude_area
|
||||
"bed_exclude_area",
|
||||
"before_layer_change_gcode",
|
||||
"enable_overhang_bridge_fan"
|
||||
"enable_pressure_advance",
|
||||
"pressure_advance",
|
||||
"enable_overhang_bridge_fan",
|
||||
"overhang_fan_speed",
|
||||
"overhang_fan_threshold",
|
||||
"slow_down_for_layer_cooling",
|
||||
|
|
@ -90,8 +92,11 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"filament_diameter",
|
||||
"filament_density",
|
||||
"filament_cost",
|
||||
"outer_wall_acceleration",
|
||||
"inner_wall_acceleration",
|
||||
"initial_layer_acceleration",
|
||||
"top_surface_acceleration",
|
||||
"travel_acceleration",
|
||||
// BBS
|
||||
"cool_plate_temp_initial_layer",
|
||||
"eng_plate_temp_initial_layer",
|
||||
|
|
@ -124,10 +129,13 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"filament_start_gcode",
|
||||
"change_filament_gcode",
|
||||
"wipe",
|
||||
"z_lift_type",
|
||||
// BBS
|
||||
"wipe_distance",
|
||||
"curr_bed_type",
|
||||
"nozzle_volume"
|
||||
"nozzle_volume",
|
||||
"chamber_temperature",
|
||||
"thumbnails"
|
||||
};
|
||||
|
||||
static std::unordered_set<std::string> steps_ignore;
|
||||
|
|
@ -164,6 +172,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
} else if (
|
||||
opt_key == "print_sequence"
|
||||
|| opt_key == "filament_type"
|
||||
|| opt_key == "chamber_temperature"
|
||||
|| opt_key == "nozzle_temperature_initial_layer"
|
||||
|| opt_key == "filament_minimal_purge_on_wipe_tower"
|
||||
|| opt_key == "filament_max_volumetric_speed"
|
||||
|
|
|
|||
|
|
@ -728,7 +728,11 @@ public:
|
|||
// Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
|
||||
std::vector<Point> first_layer_wipe_tower_corners(bool check_wipe_tower_existance=true) const;
|
||||
|
||||
protected:
|
||||
//SoftFever
|
||||
bool &is_BBL_printer() { return m_isBBLPrinter; }
|
||||
const bool is_BBL_printer() const { return m_isBBLPrinter; }
|
||||
|
||||
protected:
|
||||
// Invalidates the step, and its depending steps in Print.
|
||||
bool invalidate_step(PrintStep step);
|
||||
|
||||
|
|
@ -750,6 +754,9 @@ private:
|
|||
PrintRegionConfig m_default_region_config;
|
||||
PrintObjectPtrs m_objects;
|
||||
PrintRegionPtrs m_print_regions;
|
||||
|
||||
//SoftFever
|
||||
bool m_isBBLPrinter;
|
||||
|
||||
// Ordered collections of extrusion paths to build skirt loops and brim.
|
||||
ExtrusionEntityCollection m_skirt;
|
||||
|
|
|
|||
|
|
@ -72,18 +72,18 @@ static t_config_enum_values s_keys_map_PrinterTechnology {
|
|||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrinterTechnology)
|
||||
|
||||
static t_config_enum_values s_keys_map_PrintHostType{
|
||||
static t_config_enum_values s_keys_map_PrintHostType {
|
||||
{ "prusalink", htPrusaLink },
|
||||
{ "octoprint", htOctoPrint },
|
||||
//{ "duet", htDuet },
|
||||
//{ "flashair", htFlashAir },
|
||||
//{ "astrobox", htAstroBox },
|
||||
//{ "repetier", htRepetier },
|
||||
//{ "mks", htMKS }
|
||||
{ "duet", htDuet },
|
||||
{ "flashair", htFlashAir },
|
||||
{ "astrobox", htAstroBox },
|
||||
{ "repetier", htRepetier },
|
||||
{ "mks", htMKS }
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrintHostType)
|
||||
|
||||
static t_config_enum_values s_keys_map_AuthorizationType{
|
||||
static t_config_enum_values s_keys_map_AuthorizationType {
|
||||
{ "key", atKeyPassword },
|
||||
{ "user", atUserPassword }
|
||||
};
|
||||
|
|
@ -98,6 +98,7 @@ static t_config_enum_values s_keys_map_GCodeFlavor {
|
|||
{ "makerware", gcfMakerWare },
|
||||
{ "marlin2", gcfMarlinFirmware },
|
||||
{ "sailfish", gcfSailfish },
|
||||
{ "klipper", gcfKlipper },
|
||||
{ "smoothie", gcfSmoothie },
|
||||
{ "mach3", gcfMach3 },
|
||||
{ "machinekit", gcfMachinekit },
|
||||
|
|
@ -105,6 +106,15 @@ static t_config_enum_values s_keys_map_GCodeFlavor {
|
|||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(GCodeFlavor)
|
||||
|
||||
|
||||
static t_config_enum_values s_keys_map_LiftType {
|
||||
{ "NormalLift", int(LiftType::NormalLift) },
|
||||
{ "LazyLift", int(LiftType::LazyLift) },
|
||||
{ "SpiralLift", int(LiftType::SpiralLift) }
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(LiftType)
|
||||
|
||||
|
||||
static t_config_enum_values s_keys_map_FuzzySkinType {
|
||||
{ "none", int(FuzzySkinType::None) },
|
||||
{ "external", int(FuzzySkinType::External) },
|
||||
|
|
@ -317,7 +327,7 @@ void PrintConfigDef::init_common_params()
|
|||
def = this->add("printable_area", coPoints);
|
||||
def->label = L("Printable area");
|
||||
//BBS
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPoints{ Vec2d(0, 0), Vec2d(200, 0), Vec2d(200, 200), Vec2d(0, 200) });
|
||||
|
||||
//BBS: add "bed_exclude_area"
|
||||
|
|
@ -575,7 +585,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->multiline = true;
|
||||
def->full_width = true;
|
||||
def->height = 5;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("bottom_shell_layers", coInt);
|
||||
|
|
@ -644,12 +654,38 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(1));
|
||||
|
||||
def = this->add("top_solid_infill_flow_ratio", coFloat);
|
||||
def->label = L("Top surface flow ratio");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("This factor affects the amount of material for top solid infill. "
|
||||
"You can decrease it slightly to have smooth surface finish");
|
||||
def->min = 0;
|
||||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(1));
|
||||
|
||||
def = this->add("bottom_solid_infill_flow_ratio", coFloat);
|
||||
def->label = L("Bottom surface flow ratio");
|
||||
def->category = L("Advanced");
|
||||
def->tooltip = L("This factor affects the amount of material for bottom solid infill");
|
||||
def->min = 0;
|
||||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(1));
|
||||
|
||||
|
||||
def = this->add("only_one_wall_top", coBool);
|
||||
def->label = L("Only one wall on top surfaces");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("Use only one wall on flat top surface, to give more space to the top infill pattern");
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("only_one_wall_first_layer", coBool);
|
||||
def->label = L("Only one wall on first layer");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("Use only one wall on first layer, to give more space to the bottom infill pattern");
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("enable_overhang_speed", coBool);
|
||||
def->label = L("Slow down for overhang");
|
||||
def->category = L("Speed");
|
||||
|
|
@ -975,7 +1011,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_labels.push_back("3");
|
||||
def->enum_labels.push_back("4");
|
||||
def->enum_labels.push_back("5");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
|
||||
def = this->add("extruder_clearance_height_to_rod", coFloat);
|
||||
def->label = L("Height to rod");
|
||||
|
|
@ -1009,7 +1045,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Only used as a visual help on UI");
|
||||
def->gui_type = ConfigOptionDef::GUIType::color;
|
||||
// Empty string means no color assigned yet.
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionStrings { "" });
|
||||
|
||||
def = this->add("extruder_offset", coPoints);
|
||||
|
|
@ -1019,7 +1055,7 @@ void PrintConfigDef::init_fff_params()
|
|||
// "with respect to the first one. It expects positive coordinates (they will be subtracted "
|
||||
// "from the XY coordinate).");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPoints { Vec2d(0,0) });
|
||||
|
||||
def = this->add("filament_flow_ratio", coFloats);
|
||||
|
|
@ -1032,6 +1068,18 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 1. });
|
||||
|
||||
def = this->add("enable_pressure_advance", coBool);
|
||||
def->label = L("Enable pressure advance");
|
||||
def->tooltip = L("Enable pressure advance, auto calibration result will be overwriten once enabled.");
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("pressure_advance", coFloats);
|
||||
def->label = L("Pressure advance");
|
||||
def->tooltip = L("Pressure advnce(Klipper) AKA Linear advance factor(Marlin)");
|
||||
def->max = 2;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0.02 });
|
||||
|
||||
def = this->add("line_width", coFloat);
|
||||
def->label = L("Default");
|
||||
def->category = L("Quality");
|
||||
|
|
@ -1062,7 +1110,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->label = L("Color");
|
||||
def->tooltip = L("Only used as a visual help on UI");
|
||||
def->gui_type = ConfigOptionDef::GUIType::color;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionStrings{ "#00AE42" });
|
||||
|
||||
def = this->add("filament_max_volumetric_speed", coFloats);
|
||||
|
|
@ -1077,13 +1125,13 @@ void PrintConfigDef::init_fff_params()
|
|||
|
||||
def = this->add("filament_minimal_purge_on_wipe_tower", coFloats);
|
||||
def->label = L("Minimal purge on wipe tower");
|
||||
//def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside "
|
||||
// "the nozzle may not be known, and the filament pressure is likely not yet stable. "
|
||||
// "Before purging the print head into an infill or a sacrificial object, Slic3r will always prime "
|
||||
// "this amount of material into the wipe tower to produce successive infill or sacrificial object extrusions reliably.");
|
||||
def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside "
|
||||
"the nozzle may not be known, and the filament pressure is likely not yet stable. "
|
||||
"Before purging the print head into an infill or a sacrificial object, Slic3r will always prime "
|
||||
"this amount of material into the wipe tower to produce successive infill or sacrificial object extrusions reliably.");
|
||||
def->sidetext = L("mm³");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 15. });
|
||||
|
||||
def = this->add("machine_load_filament_time", coFloat);
|
||||
|
|
@ -1139,13 +1187,13 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("filament_soluble", coBools);
|
||||
def->label = L("Soluble material");
|
||||
def->tooltip = L("Soluble material is commonly used to print support and support interface");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBools { false });
|
||||
|
||||
def = this->add("filament_is_support", coBools);
|
||||
def->label = L("Support material");
|
||||
def->tooltip = L("Support material is commonly used to print support and support interface");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBools { false });
|
||||
|
||||
// BBS
|
||||
|
|
@ -1186,6 +1234,16 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(45));
|
||||
|
||||
def = this->add("bridge_angle", coFloat);
|
||||
def->label = L("Bridge infill direction");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Angle for bridge infill pattern, which controls the start or main direction of line");
|
||||
def->sidetext = L("°");
|
||||
def->min = 0;
|
||||
def->max = 360;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("sparse_infill_density", coPercent);
|
||||
def->label = L("Sparse infill density");
|
||||
def->category = L("Strength");
|
||||
|
|
@ -1240,6 +1298,30 @@ void PrintConfigDef::init_fff_params()
|
|||
#endif // HAS_LIGHTNING_INFILL
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipCubic));
|
||||
|
||||
def = this->add("outer_wall_acceleration", coFloat);
|
||||
def->label = L("Outer wall");
|
||||
def->tooltip = L("Acceleration of outer walls");
|
||||
def->sidetext = L("mm/s²");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(10000));
|
||||
|
||||
def = this->add("inner_wall_acceleration", coFloat);
|
||||
def->label = L("Inner wall");
|
||||
def->tooltip = L("Acceleration of inner walls");
|
||||
def->sidetext = L("mm/s²");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(10000));
|
||||
|
||||
def = this->add("travel_acceleration", coFloat);
|
||||
def->label = L("Travel");
|
||||
def->tooltip = L("Acceleration of travel moves");
|
||||
def->sidetext = L("mm/s²");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(10000));
|
||||
|
||||
def = this->add("top_surface_acceleration", coFloat);
|
||||
def->label = L("Top surface");
|
||||
def->tooltip = L("Acceleration of top surface infill. Using a lower value may improve top surface quality");
|
||||
|
|
@ -1256,6 +1338,54 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(300));
|
||||
|
||||
def = this->add("default_jerk", coFloat);
|
||||
def->label = L("Default");
|
||||
def->tooltip = L("Default");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("outer_wall_jerk", coFloat);
|
||||
def->label = L("Outer wall");
|
||||
def->tooltip = L("Jerk of outer walls");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(9));
|
||||
|
||||
def = this->add("inner_wall_jerk", coFloat);
|
||||
def->label = L("Inner wall");
|
||||
def->tooltip = L("Jerk of inner walls");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(9));
|
||||
|
||||
def = this->add("top_surface_jerk", coFloat);
|
||||
def->label = L("Top surface");
|
||||
def->tooltip = L("Jerk for top surface");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 1;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(9));
|
||||
|
||||
def = this->add("initial_layer_jerk", coFloat);
|
||||
def->label = L("Initial layer");
|
||||
def->tooltip = L("Jerk for initial layer");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 1;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(9));
|
||||
|
||||
def = this->add("travel_jerk", coFloat);
|
||||
def->label = L("Travel");
|
||||
def->tooltip = L("Jerk for travel");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 1;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(12));
|
||||
|
||||
def = this->add("initial_layer_line_width", coFloat);
|
||||
def->label = L("Initial layer");
|
||||
def->category = L("Quality");
|
||||
|
|
@ -1338,7 +1468,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("The width within which to jitter. It's adversed to be below outer wall line width");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.3));
|
||||
|
||||
def = this->add("fuzzy_skin_point_distance", coFloat);
|
||||
|
|
@ -1346,7 +1476,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->category = L("Others");
|
||||
def->tooltip = L("The average diatance between the random points introducded on each line segment");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.8));
|
||||
|
||||
def = this->add("gap_infill_speed", coFloat);
|
||||
|
|
@ -1376,7 +1506,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("scan_first_layer", coBool);
|
||||
def->label = L("Scan first layer");
|
||||
def->tooltip = L("Enable this to enable the camera on printer to check the quality of first layer");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
//BBS
|
||||
// def = this->add("spaghetti_detector", coBool);
|
||||
|
|
@ -1398,13 +1528,13 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_labels.push_back(L("Hardened steel"));
|
||||
def->enum_labels.push_back(L("Stainless steel"));
|
||||
def->enum_labels.push_back(L("Brass"));
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<NozzleType>(ntUndefine));
|
||||
|
||||
def = this->add("auxiliary_fan", coBool);
|
||||
def->label = L("Auxiliary part cooling fan");
|
||||
def->tooltip = L("Enable this option if machine has auxiliary part cooling fan");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("gcode_flavor", coEnum);
|
||||
|
|
@ -1412,7 +1542,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("What kind of gcode the printer is compatible with");
|
||||
def->enum_keys_map = &ConfigOptionEnum<GCodeFlavor>::get_enum_values();
|
||||
def->enum_values.push_back("marlin");
|
||||
//def->enum_values.push_back("reprap");
|
||||
def->enum_values.push_back("klipper");
|
||||
//def->enum_values.push_back("reprapfirmware");
|
||||
//def->enum_values.push_back("repetier");
|
||||
//def->enum_values.push_back("teacup");
|
||||
|
|
@ -1435,6 +1565,7 @@ void PrintConfigDef::init_fff_params()
|
|||
//def->enum_labels.push_back("Machinekit");
|
||||
//def->enum_labels.push_back("Smoothie");
|
||||
//def->enum_labels.push_back(L("No extrusion"));
|
||||
def->enum_labels.push_back(L("Klipper"));
|
||||
def->mode = comAdvanced;
|
||||
def->readonly = false;
|
||||
def->set_default_value(new ConfigOptionEnum<GCodeFlavor>(gcfMarlinLegacy));
|
||||
|
|
@ -1500,13 +1631,13 @@ void PrintConfigDef::init_fff_params()
|
|||
def->cli = ConfigOptionDef::nocli;
|
||||
|
||||
def = this->add("interface_shells", coBool);
|
||||
//def->label = L("Interface shells");
|
||||
def->label = L("Interface shells");
|
||||
def->label = "Interface shells";
|
||||
//def->tooltip = L("Force the generation of solid shells between adjacent materials/volumes. "
|
||||
// "Useful for multi-extruder prints with translucent materials or manual soluble "
|
||||
// "support material");
|
||||
def->tooltip = L("Force the generation of solid shells between adjacent materials/volumes. "
|
||||
"Useful for multi-extruder prints with translucent materials or manual soluble "
|
||||
"support material");
|
||||
def->category = L("Quality");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("ironing_type", coEnum);
|
||||
|
|
@ -1554,7 +1685,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Print speed of ironing lines");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(20));
|
||||
|
||||
def = this->add("layer_change_gcode", coString);
|
||||
|
|
@ -1715,7 +1846,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Maximum acceleration for travel (M204 T)");
|
||||
def->sidetext = L("mm/s²");
|
||||
def->min = 0;
|
||||
def->readonly = true;
|
||||
def->readonly = false;
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionFloats{ 1500., 1250. });
|
||||
|
||||
|
|
@ -1735,7 +1866,7 @@ void PrintConfigDef::init_fff_params()
|
|||
"the maximum layer hight when enable adaptive layer height");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0. });
|
||||
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
|
|
@ -1787,7 +1918,7 @@ void PrintConfigDef::init_fff_params()
|
|||
"the minimum layer hight when enable adaptive layer height");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0.07 });
|
||||
|
||||
def = this->add("slow_down_min_speed", coFloats);
|
||||
|
|
@ -1795,44 +1926,45 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("The minimum printing speed when slow down for cooling");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 10. });
|
||||
|
||||
def = this->add("nozzle_diameter", coFloats);
|
||||
def->label = L("Nozzle diameter");
|
||||
def->tooltip = L("Diameter of nozzle");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0.4 });
|
||||
|
||||
def = this->add("host_type", coEnum);
|
||||
def->label = L("Host Type");
|
||||
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field must contain "
|
||||
"the kind of the host.");
|
||||
"the kind of the host.");
|
||||
def->enum_keys_map = &ConfigOptionEnum<PrintHostType>::get_enum_values();
|
||||
def->enum_values.push_back("prusalink");
|
||||
def->enum_values.push_back("octoprint");
|
||||
//def->enum_values.push_back("duet");
|
||||
//def->enum_values.push_back("flashair");
|
||||
//def->enum_values.push_back("astrobox");
|
||||
//def->enum_values.push_back("repetier");
|
||||
//def->enum_values.push_back("mks");
|
||||
def->enum_values.push_back("duet");
|
||||
def->enum_values.push_back("flashair");
|
||||
def->enum_values.push_back("astrobox");
|
||||
def->enum_values.push_back("repetier");
|
||||
def->enum_values.push_back("mks");
|
||||
def->enum_labels.push_back("PrusaLink");
|
||||
def->enum_labels.push_back("OctoPrint");
|
||||
//def->enum_labels.push_back("Duet");
|
||||
//def->enum_labels.push_back("FlashAir");
|
||||
//def->enum_labels.push_back("AstroBox");
|
||||
//def->enum_labels.push_back("Repetier");
|
||||
//def->enum_labels.push_back("MKS");
|
||||
def->enum_labels.push_back("Duet");
|
||||
def->enum_labels.push_back("FlashAir");
|
||||
def->enum_labels.push_back("AstroBox");
|
||||
def->enum_labels.push_back("Repetier");
|
||||
def->enum_labels.push_back("MKS");
|
||||
def->mode = comAdvanced;
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
def->set_default_value(new ConfigOptionEnum<PrintHostType>(htOctoPrint));
|
||||
|
||||
|
||||
def = this->add("nozzle_volume", coFloat);
|
||||
def->label = L("Nozzle volume");
|
||||
def->tooltip = L("Volume of nozzle between the cutter and the end of nozzle");
|
||||
def->sidetext = L("mm³");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->readonly = true;
|
||||
def->set_default_value(new ConfigOptionFloat { 0.0 });
|
||||
|
||||
|
|
@ -1856,15 +1988,15 @@ void PrintConfigDef::init_fff_params()
|
|||
def->label = L("Filename format");
|
||||
def->tooltip = L("User can self-define the project file name when export");
|
||||
def->full_width = true;
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionString("[input_filename_base].gcode"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString("{input_filename_base}_{filament_type[0]}_{print_time}.gcode"));
|
||||
|
||||
def = this->add("detect_overhang_wall", coBool);
|
||||
def->label = L("Detect overhang wall");
|
||||
def->category = L("Quality");
|
||||
def->tooltip = L("Detect the overhang percentage relative to line width and use different speed to print. "
|
||||
"For 100%% overhang, bridge speed is used.");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("wall_filament", coInt);
|
||||
|
|
@ -1936,7 +2068,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Z gap between object and raft. Ignored for soluble interface");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.1));
|
||||
|
||||
def = this->add("raft_expansion", coFloat);
|
||||
|
|
@ -1945,7 +2077,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Expand all raft layers in XY plane");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(1.5));
|
||||
|
||||
def = this->add("raft_first_layer_density", coPercent);
|
||||
|
|
@ -1955,7 +2087,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->sidetext = L("%");
|
||||
def->min = 10;
|
||||
def->max = 100;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPercent(90));
|
||||
|
||||
def = this->add("raft_first_layer_expansion", coFloat);
|
||||
|
|
@ -1964,7 +2096,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Expand the first raft or support layer to improve bed plate adhesion");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
//BBS: change from 3.0 to 2.0
|
||||
def->set_default_value(new ConfigOptionFloat(2.0));
|
||||
|
||||
|
|
@ -1976,7 +2108,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->sidetext = L("layers");
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("resolution", coFloat);
|
||||
|
|
@ -1999,7 +2131,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->label = L("Retract amount before wipe");
|
||||
def->tooltip = L("The length of fast retraction before wipe, relative to retraction length");
|
||||
def->sidetext = L("%");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPercents { 100 });
|
||||
|
||||
def = this->add("retract_when_changing_layer", coBools);
|
||||
|
|
@ -2025,7 +2157,7 @@ void PrintConfigDef::init_fff_params()
|
|||
// "by the specified amount (the length is measured on raw filament, before it enters "
|
||||
// "the extruder).");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 10. });
|
||||
|
||||
def = this->add("z_hop", coFloats);
|
||||
|
|
@ -2038,21 +2170,21 @@ void PrintConfigDef::init_fff_params()
|
|||
def->set_default_value(new ConfigOptionFloats { 0.4 });
|
||||
|
||||
def = this->add("retract_restart_extra", coFloats);
|
||||
//def->label = L("Extra length on restart");
|
||||
def->label = L("Extra length on restart");
|
||||
def->label = "Extra length on restart";
|
||||
//def->tooltip = L("When the retraction is compensated after the travel move, the extruder will push "
|
||||
// "this additional amount of filament. This setting is rarely needed.");
|
||||
def->tooltip = L("When the retraction is compensated after the travel move, the extruder will push "
|
||||
"this additional amount of filament. This setting is rarely needed.");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0. });
|
||||
|
||||
def = this->add("retract_restart_extra_toolchange", coFloats);
|
||||
//def->label = L("Extra length on restart");
|
||||
def->label = L("Extra length on restart");
|
||||
def->label = "Extra length on restart";
|
||||
//def->tooltip = L("When the retraction is compensated after changing tool, the extruder will push "
|
||||
// "this additional amount of filament.");
|
||||
def->tooltip = L("When the retraction is compensated after changing tool, the extruder will push "
|
||||
"this additional amount of filament.");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 0. });
|
||||
|
||||
def = this->add("retraction_speed", coFloats);
|
||||
|
|
@ -2093,7 +2225,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->max = 10;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(2));
|
||||
|
||||
def = this->add("skirt_height", coInt);
|
||||
|
|
@ -2101,7 +2233,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->label = "Skirt height";
|
||||
//def->tooltip = L("How many layers of skirt. Usually only one layer");
|
||||
def->sidetext = L("layers");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->max = 10000;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
|
||||
|
|
@ -2303,7 +2435,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->sidetext = L("°");
|
||||
def->min = 0;
|
||||
def->max = 359;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("support_on_build_plate_only", coBool);
|
||||
|
|
@ -2419,7 +2551,7 @@ void PrintConfigDef::init_fff_params()
|
|||
//TRN To be shown in Print Settings "Bottom interface layers". Have to be as short as possible
|
||||
def->enum_labels.push_back("-1");
|
||||
append(def->enum_labels, support_interface_top_layers->enum_labels);
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("support_interface_spacing", coFloat);
|
||||
|
|
@ -2438,7 +2570,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("Spacing of bottom interface lines. Zero means solid interface");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.5));
|
||||
|
||||
def = this->add("support_interface_speed", coFloat);
|
||||
|
|
@ -2515,7 +2647,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_values.push_back("snug");
|
||||
def->enum_labels.push_back(L("Grid"));
|
||||
def->enum_labels.push_back(L("Snug"));
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<SupportMaterialStyle>(smsGrid));
|
||||
|
||||
def = this->add("independent_support_layer_height", coBool);
|
||||
|
|
@ -2581,6 +2713,15 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("chamber_temperature", coInt);
|
||||
def->label = L("Chamber temperature");
|
||||
def->tooltip = L("Target chamber temperature");
|
||||
def->sidetext = L("°C");
|
||||
def->full_label = L("Chamber temperature");
|
||||
def->min = 0;
|
||||
def->max = max_temp;
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("nozzle_temperature", coInts);
|
||||
def->label = L("Other layers");
|
||||
def->tooltip = L("Nozzle temperature for layers after the initial one");
|
||||
|
|
@ -2697,6 +2838,19 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBools { false });
|
||||
|
||||
def = this->add("z_lift_type", coEnum);
|
||||
def->label = L("Z hop type");
|
||||
def->tooltip = L("Z hop type");
|
||||
def->enum_keys_map = &ConfigOptionEnum<LiftType>::get_enum_values();
|
||||
def->enum_values.push_back("NormalLift");
|
||||
def->enum_values.push_back("SpiralLift");
|
||||
// def->enum_values.push_back("LazyLift");
|
||||
def->enum_labels.push_back(L("NormalLift"));
|
||||
def->enum_labels.push_back(L("SpiralLift"));
|
||||
// def->enum_labels.push_back(L("LazyLift"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<LiftType>(LiftType::SpiralLift));
|
||||
|
||||
def = this->add("wipe_distance", coFloats);
|
||||
def->label = L("Wipe Distance");
|
||||
def->tooltip = L("Discribe how long the nozzle will move along the last path when retracting");
|
||||
|
|
@ -2735,7 +2889,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->label = L("Flush multiplier");
|
||||
def->tooltip = L("");
|
||||
def->sidetext = L("");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->min = 0;
|
||||
def->set_default_value(new ConfigOptionFloat(1.0));
|
||||
|
||||
|
|
@ -2836,6 +2990,13 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("thumbnails", coPoints);
|
||||
def->label = L("G-code thumbnails");
|
||||
def->tooltip = L("Picture sizes to be stored into a .gcode and .sl1 / .sl1s files, in the following format: \"XxY, XxY, ...\"");
|
||||
def->mode = comAdvanced;
|
||||
def->gui_type = ConfigOptionDef::GUIType::one_string;
|
||||
def->set_default_value(new ConfigOptionPoints{Vec2d(300, 300)});
|
||||
|
||||
// Declare retract values for filament profile, overriding the printer's extruder profile.
|
||||
for (const char *opt_key : {
|
||||
// floats
|
||||
|
|
@ -2857,8 +3018,6 @@ void PrintConfigDef::init_fff_params()
|
|||
if ((strcmp(opt_key, "retraction_length") == 0) ||
|
||||
(strcmp(opt_key, "z_hop") == 0))
|
||||
def->mode = comSimple;
|
||||
else if (strcmp(opt_key, "retract_before_wipe") == 0)
|
||||
def->mode = comDevelop;
|
||||
else
|
||||
def->mode = comAdvanced;
|
||||
switch (def->type) {
|
||||
|
|
@ -2875,7 +3034,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("This option will auto detect narrow internal solid infill area."
|
||||
" If enabled, concentric pattern will be used for the area to speed printing up."
|
||||
" Otherwise, rectilinear pattern is used defaultly.");
|
||||
def->mode = comDevelop;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
}
|
||||
|
||||
|
|
@ -3629,7 +3788,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
static std::set<std::string> ignore = {
|
||||
"acceleration", "scale", "rotate", "duplicate", "duplicate_grid",
|
||||
"bed_size",
|
||||
"print_center", "g0", "pressure_advance", "wipe_tower_per_color_wipe"
|
||||
"print_center", "g0", "wipe_tower_per_color_wipe"
|
||||
#ifndef HAS_PRESSURE_EQUALIZER
|
||||
, "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative"
|
||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@
|
|||
namespace Slic3r {
|
||||
|
||||
enum GCodeFlavor : unsigned char {
|
||||
gcfMarlinLegacy, gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
|
||||
gcfSmoothie, gcfNoExtrusion,
|
||||
gcfMarlinLegacy, gcfKlipper, gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
|
||||
gcfSmoothie, gcfNoExtrusion
|
||||
};
|
||||
|
||||
enum class FuzzySkinType {
|
||||
|
|
@ -118,6 +118,12 @@ enum SeamPosition {
|
|||
spNearest, spAligned, spRear, spRandom
|
||||
};
|
||||
|
||||
enum LiftType {
|
||||
NormalLift,
|
||||
SpiralLift,
|
||||
LazyLift
|
||||
};
|
||||
|
||||
enum SLAMaterial {
|
||||
slamTough,
|
||||
slamFlex,
|
||||
|
|
@ -658,7 +664,10 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloat, bottom_shell_thickness))
|
||||
((ConfigOptionFloat, bridge_flow))
|
||||
((ConfigOptionFloat, bridge_speed))
|
||||
((ConfigOptionFloat, bridge_angle))
|
||||
((ConfigOptionEnum<InfillPattern>, top_surface_pattern))
|
||||
((ConfigOptionFloat, top_solid_infill_flow_ratio))
|
||||
((ConfigOptionFloat, bottom_solid_infill_flow_ratio))
|
||||
((ConfigOptionEnum<InfillPattern>, bottom_surface_pattern))
|
||||
((ConfigOptionFloat, outer_wall_line_width))
|
||||
((ConfigOptionFloat, outer_wall_speed))
|
||||
|
|
@ -705,6 +714,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloat, overhang_3_4_speed))
|
||||
((ConfigOptionFloat, overhang_4_4_speed))
|
||||
((ConfigOptionBool, only_one_wall_top))
|
||||
((ConfigOptionBool, only_one_wall_first_layer))
|
||||
)
|
||||
|
||||
PRINT_CONFIG_CLASS_DEFINE(
|
||||
|
|
@ -748,6 +758,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionString, machine_end_gcode))
|
||||
((ConfigOptionStrings, filament_end_gcode))
|
||||
((ConfigOptionFloats, filament_flow_ratio))
|
||||
((ConfigOptionBool, enable_pressure_advance))
|
||||
((ConfigOptionFloats, pressure_advance))
|
||||
((ConfigOptionFloats, filament_diameter))
|
||||
((ConfigOptionFloats, filament_density))
|
||||
((ConfigOptionStrings, filament_type))
|
||||
|
|
@ -774,6 +786,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloats, retraction_length))
|
||||
((ConfigOptionFloats, retract_length_toolchange))
|
||||
((ConfigOptionFloats, z_hop))
|
||||
((ConfigOptionEnum<LiftType>, z_lift_type))
|
||||
((ConfigOptionFloats, retract_restart_extra))
|
||||
((ConfigOptionFloats, retract_restart_extra_toolchange))
|
||||
((ConfigOptionFloats, retraction_speed))
|
||||
|
|
@ -790,6 +803,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
//BBS
|
||||
((ConfigOptionEnum<NozzleType>, nozzle_type))
|
||||
((ConfigOptionBool, auxiliary_fan))
|
||||
|
||||
)
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::Print.
|
||||
|
|
@ -830,11 +844,21 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
((ConfigOptionBools, reduce_fan_stop_start_freq))
|
||||
((ConfigOptionInts, fan_cooling_layer_time))
|
||||
((ConfigOptionStrings, filament_colour))
|
||||
((ConfigOptionFloat, outer_wall_acceleration))
|
||||
((ConfigOptionFloat, inner_wall_acceleration))
|
||||
((ConfigOptionFloat, top_surface_acceleration))
|
||||
((ConfigOptionFloat, initial_layer_acceleration))
|
||||
((ConfigOptionFloat, travel_acceleration))
|
||||
((ConfigOptionFloat, initial_layer_line_width))
|
||||
((ConfigOptionFloat, initial_layer_print_height))
|
||||
((ConfigOptionFloat, initial_layer_speed))
|
||||
((ConfigOptionFloat, default_jerk))
|
||||
((ConfigOptionFloat, outer_wall_jerk))
|
||||
((ConfigOptionFloat, inner_wall_jerk))
|
||||
((ConfigOptionFloat, top_surface_jerk))
|
||||
((ConfigOptionFloat, initial_layer_jerk))
|
||||
((ConfigOptionFloat, travel_jerk))
|
||||
|
||||
//BBS
|
||||
((ConfigOptionFloat, initial_layer_infill_speed))
|
||||
((ConfigOptionInts, nozzle_temperature_initial_layer))
|
||||
|
|
@ -861,6 +885,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
((ConfigOptionBool, spiral_mode))
|
||||
((ConfigOptionInt, standby_temperature_delta))
|
||||
((ConfigOptionInts, nozzle_temperature))
|
||||
((ConfigOptionInt , chamber_temperature))
|
||||
((ConfigOptionBools, wipe))
|
||||
// BBS
|
||||
((ConfigOptionInts, bed_temperature_difference))
|
||||
|
|
@ -888,7 +913,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
((ConfigOptionBool, has_prime_tower))
|
||||
((ConfigOptionFloat, nozzle_volume))
|
||||
((ConfigOptionEnum<TimelapseType>, timelapse_type))
|
||||
|
||||
((ConfigOptionPoints, thumbnails))
|
||||
)
|
||||
|
||||
// This object is mapped to Perl as Slic3r::Config::Full.
|
||||
|
|
|
|||
|
|
@ -667,6 +667,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
} else if (
|
||||
opt_key == "wall_loops"
|
||||
|| opt_key == "only_one_wall_top"
|
||||
|| opt_key == "only_one_wall_first_layer"
|
||||
|| opt_key == "initial_layer_line_width"
|
||||
|| opt_key == "inner_wall_line_width"
|
||||
|| opt_key == "infill_wall_overlap") {
|
||||
|
|
@ -762,13 +763,15 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|| opt_key == "minimum_sparse_infill_area"
|
||||
|| opt_key == "sparse_infill_filament"
|
||||
|| opt_key == "solid_infill_filament"
|
||||
|| opt_key == "sparse_infill_line_width") {
|
||||
|| opt_key == "sparse_infill_line_width"
|
||||
|| opt_key == "infill_direction"
|
||||
|| opt_key == "bridge_angle") {
|
||||
steps.emplace_back(posPrepareInfill);
|
||||
} else if (
|
||||
opt_key == "top_surface_pattern"
|
||||
|| opt_key == "bottom_surface_pattern"
|
||||
|| opt_key == "external_fill_link_max_length"
|
||||
|| opt_key == "infill_direction"
|
||||
|| opt_key == "sparse_infill_pattern"
|
||||
|| opt_key == "top_surface_line_width"
|
||||
|| opt_key == "initial_layer_line_width") {
|
||||
steps.emplace_back(posInfill);
|
||||
|
|
|
|||
|
|
@ -22,10 +22,15 @@ Flow PrintRegion::flow(const PrintObject &object, FlowRole role, double layer_he
|
|||
{
|
||||
const PrintConfig &print_config = object.print()->config();
|
||||
ConfigOptionFloat config_width;
|
||||
double flow_ratio = 1.0;
|
||||
// Get extrusion width from configuration.
|
||||
// (might be an absolute value, or a percent value, or zero for auto)
|
||||
if (first_layer && print_config.initial_layer_line_width.value > 0) {
|
||||
config_width = print_config.initial_layer_line_width;
|
||||
if (first_layer) {
|
||||
if(role != frExternalPerimeter)
|
||||
flow_ratio = m_config.bottom_solid_infill_flow_ratio;
|
||||
if(print_config.initial_layer_line_width.value > 0) {
|
||||
config_width = print_config.initial_layer_line_width;
|
||||
}
|
||||
} else if (role == frExternalPerimeter) {
|
||||
config_width = m_config.outer_wall_line_width;
|
||||
} else if (role == frPerimeter) {
|
||||
|
|
@ -36,6 +41,7 @@ Flow PrintRegion::flow(const PrintObject &object, FlowRole role, double layer_he
|
|||
config_width = m_config.internal_solid_infill_line_width;
|
||||
} else if (role == frTopSolidInfill) {
|
||||
config_width = m_config.top_surface_line_width;
|
||||
flow_ratio = m_config.top_solid_infill_flow_ratio;
|
||||
} else {
|
||||
throw Slic3r::InvalidArgument("Unknown role");
|
||||
}
|
||||
|
|
@ -46,7 +52,7 @@ Flow PrintRegion::flow(const PrintObject &object, FlowRole role, double layer_he
|
|||
// Get the configured nozzle_diameter for the extruder associated to the flow role requested.
|
||||
// Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
|
||||
auto nozzle_diameter = float(print_config.nozzle_diameter.get_at(this->extruder(role) - 1));
|
||||
return Flow::new_from_config_width(role, config_width, nozzle_diameter, float(layer_height));
|
||||
return Flow::new_from_config_width(role, config_width, nozzle_diameter, float(layer_height)).with_flow_ratio(flow_ratio);
|
||||
}
|
||||
|
||||
coordf_t PrintRegion::nozzle_dmr_avg(const PrintConfig &print_config) const
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#define SLIC3R_APP_NAME "@SLIC3R_APP_NAME@"
|
||||
#define SLIC3R_APP_KEY "@SLIC3R_APP_KEY@"
|
||||
#define SLIC3R_VERSION "@SLIC3R_VERSION@"
|
||||
#define SoftFever_VERSION "@SoftFever_VERSION@"
|
||||
#define SLIC3R_BUILD_ID "@SLIC3R_BUILD_ID@"
|
||||
//#define SLIC3R_RC_VERSION "@SLIC3R_VERSION@"
|
||||
#define BBL_RELEASE_TO_PUBLIC @BBL_RELEASE_TO_PUBLIC@
|
||||
|
|
|
|||
|
|
@ -1106,7 +1106,7 @@ std::string string_printf(const char *format, ...)
|
|||
|
||||
std::string header_slic3r_generated()
|
||||
{
|
||||
return std::string(SLIC3R_APP_NAME " " SLIC3R_VERSION);
|
||||
return std::string(SLIC3R_APP_NAME "-SoftFever" " " SLIC3R_VERSION);
|
||||
}
|
||||
|
||||
std::string header_gcodeviewer_generated()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
project(minilzo)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
add_library(minilzo INTERFACE)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ endif()
|
|||
else(Qhull_FOUND)
|
||||
|
||||
project(qhull)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
# Define qhull_VERSION in CMakeLists.txt, Makefile, qhull-exports.def, qhull_p-exports.def, qhull_r-exports.def, qhull-warn.pri
|
||||
set(qhull_VERSION2 "2015.2 2016/01/18") # not used, See global.c, global_r.c, rbox.c, rbox_r.c
|
||||
|
|
|
|||
|
|
@ -181,6 +181,10 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/SavePresetDialog.cpp
|
||||
GUI/GUI_Colors.hpp
|
||||
GUI/GUI_Colors.cpp
|
||||
GUI/PhysicalPrinterDialog.hpp
|
||||
GUI/PhysicalPrinterDialog.cpp
|
||||
GUI/PrintHostDialogs.cpp
|
||||
GUI/PrintHostDialogs.hpp
|
||||
GUI/GUI_Factories.cpp
|
||||
GUI/GUI_Factories.hpp
|
||||
GUI/GUI_ObjectList.cpp
|
||||
|
|
@ -231,6 +235,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/Monitor.hpp
|
||||
GUI/WebViewDialog.cpp
|
||||
GUI/WebViewDialog.hpp
|
||||
GUI/PrinterWebView.cpp
|
||||
GUI/PrinterWebView.hpp
|
||||
GUI/WebDownPluginDlg.hpp
|
||||
GUI/WebDownPluginDlg.cpp
|
||||
GUI/WebGuideDialog.hpp
|
||||
|
|
@ -368,6 +374,10 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/Calibration.cpp
|
||||
GUI/PrintOptionsDialog.hpp
|
||||
GUI/PrintOptionsDialog.cpp
|
||||
GUI/BonjourDialog.hpp
|
||||
GUI/BonjourDialog.cpp
|
||||
GUI/BedShapeDialog.hpp
|
||||
GUI/BedShapeDialog.cpp
|
||||
Utils/json_diff.hpp
|
||||
Utils/json_diff.cpp
|
||||
GUI/KBShortcutsDialog.hpp
|
||||
|
|
@ -399,6 +409,22 @@ set(SLIC3R_GUI_SOURCES
|
|||
Utils/PrintHost.cpp
|
||||
Utils/NetworkAgent.cpp
|
||||
Utils/NetworkAgent.hpp
|
||||
Utils/OctoPrint.cpp
|
||||
Utils/OctoPrint.hpp
|
||||
Utils/PrintHost.cpp
|
||||
Utils/PrintHost.hpp
|
||||
Utils/Serial.cpp
|
||||
Utils/Serial.hpp
|
||||
Utils/MKS.hpp
|
||||
Utils/MKS.cpp
|
||||
Utils/Duet.cpp
|
||||
Utils/Duet.hpp
|
||||
Utils/FlashAir.cpp
|
||||
Utils/FlashAir.hpp
|
||||
Utils/AstroBox.cpp
|
||||
Utils/AstroBox.hpp
|
||||
Utils/Repetier.cpp
|
||||
Utils/Repetier.hpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
|||
|
|
@ -244,11 +244,8 @@ AboutDialog::AboutDialog()
|
|||
// version
|
||||
{
|
||||
vesizer->Add(0, FromDIP(165), 1, wxEXPAND, FromDIP(5));
|
||||
#if BBL_INTERNAL_TESTING
|
||||
auto version_string = _L("Internal Version") + " " + std::string(SLIC3R_VERSION);
|
||||
#else
|
||||
auto version_string = _L("Version") + " " + std::string(SLIC3R_VERSION);
|
||||
#endif
|
||||
|
||||
auto version_string = _L("SoftFever Version") + " " + std::string(SoftFever_VERSION);
|
||||
wxStaticText* version = new wxStaticText(this, wxID_ANY, version_string.c_str(), wxDefaultPosition, wxDefaultSize);
|
||||
wxFont version_font = GetFont();
|
||||
#ifdef __WXMSW__
|
||||
|
|
|
|||
|
|
@ -250,13 +250,13 @@ void BBLTopbar::Init(wxFrame* parent)
|
|||
this->AddSpacer(FromDIP(10));
|
||||
this->AddStretchSpacer(1);
|
||||
|
||||
#if !BBL_RELEASE_TO_PUBLIC
|
||||
// #if !BBL_RELEASE_TO_PUBLIC
|
||||
/*wxBitmap m_publish_bitmap = create_scaled_bitmap("topbar_publish", nullptr, TOPBAR_ICON_SIZE);
|
||||
m_publish_item = this->AddTool(ID_PUBLISH, "", m_publish_bitmap);
|
||||
wxBitmap m_publish_disable_bitmap = create_scaled_bitmap("topbar_publish_disable", nullptr, TOPBAR_ICON_SIZE);
|
||||
m_publish_item->SetDisabledBitmap(m_publish_disable_bitmap);
|
||||
this->AddSpacer(FromDIP(12));*/
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
/*wxBitmap model_store_bitmap = create_scaled_bitmap("topbar_store", nullptr, TOPBAR_ICON_SIZE);
|
||||
m_model_store_item = this->AddTool(ID_MODEL_STORE, "", model_store_bitmap);
|
||||
|
|
|
|||
|
|
@ -183,6 +183,13 @@ std::string BackgroundSlicingProcess::output_filepath_for_project(const boost::f
|
|||
void BackgroundSlicingProcess::process_fff()
|
||||
{
|
||||
assert(m_print == m_fff_print);
|
||||
PresetBundle &preset_bundle = *wxGetApp().preset_bundle;
|
||||
|
||||
m_fff_print->is_BBL_printer() =
|
||||
preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(
|
||||
&preset_bundle);
|
||||
|
||||
|
||||
//BBS: add the logic to process from an existed gcode file
|
||||
if (m_print->finished()) {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" %1%: skip slicing, to process previous gcode file")%__LINE__;
|
||||
|
|
@ -837,8 +844,9 @@ void BackgroundSlicingProcess::prepare_upload()
|
|||
m_upload_job.upload_data.upload_path = output_name_str;
|
||||
} else {
|
||||
m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||
|
||||
ThumbnailsList thumbnails = this->render_thumbnails(
|
||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
||||
// true, false, true, true); // renders also supports and pad
|
||||
Zipper zipper{source_path.string()};
|
||||
m_sla_archive.export_print(zipper, *m_sla_print, m_upload_job.upload_data.upload_path.string());
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ void BedShape::append_option_line(ConfigOptionsGroupShp optgroup, Parameter para
|
|||
def.max = 600;
|
||||
def.label = get_option_label(param);
|
||||
def.tooltip = L("Distance of the 0,0 G-code coordinate from the front left corner of the rectangle.");
|
||||
def.readonly = true;
|
||||
key = "rect_origin";
|
||||
break;
|
||||
case Parameter::Diameter:
|
||||
|
|
@ -191,9 +192,9 @@ void BedShapePanel::build_panel(const ConfigOptionPoints& default_pt, const Conf
|
|||
BedShape::append_option_line(optgroup, BedShape::Parameter::RectOrigin);
|
||||
activate_options_page(optgroup);
|
||||
|
||||
optgroup = init_shape_options_page(BedShape::get_name(BedShape::PageType::Circle));
|
||||
BedShape::append_option_line(optgroup, BedShape::Parameter::Diameter);
|
||||
activate_options_page(optgroup);
|
||||
// optgroup = init_shape_options_page(BedShape::get_name(BedShape::PageType::Circle));
|
||||
// BedShape::append_option_line(optgroup, BedShape::Parameter::Diameter);
|
||||
// activate_options_page(optgroup);
|
||||
|
||||
optgroup = init_shape_options_page(BedShape::get_name(BedShape::PageType::Custom));
|
||||
|
||||
|
|
|
|||
|
|
@ -554,17 +554,14 @@ void Camera::look_at(const Vec3d& position, const Vec3d& target, const Vec3d& up
|
|||
|
||||
void Camera::set_default_orientation()
|
||||
{
|
||||
// BBS modify default orientation
|
||||
look_at(m_target - 0.707 * m_distance * Vec3d::UnitY() + 0.707 * m_distance * Vec3d::UnitZ(), m_target, Vec3d::UnitY() + Vec3d::UnitZ());
|
||||
|
||||
/*m_zenit = 45.0f;
|
||||
m_zenit = 45.0f;
|
||||
const double theta_rad = Geometry::deg2rad(-(double)m_zenit);
|
||||
const double phi_rad = Geometry::deg2rad(45.0);
|
||||
const double sin_theta = ::sin(theta_rad);
|
||||
const Vec3d camera_pos = m_target + m_distance * Vec3d(sin_theta * ::sin(phi_rad), sin_theta * ::cos(phi_rad), ::cos(theta_rad));
|
||||
m_view_rotation = Eigen::AngleAxisd(theta_rad, Vec3d::UnitX()) * Eigen::AngleAxisd(phi_rad, Vec3d::UnitZ());
|
||||
m_view_rotation.normalize();
|
||||
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());*/
|
||||
m_view_matrix.fromPositionOrientationScale(m_view_rotation * (-camera_pos), m_view_rotation, Vec3d::Ones());
|
||||
}
|
||||
|
||||
Vec3d Camera::validate_target(const Vec3d& target) const
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
toggle_field(el, has_solid_infill);
|
||||
|
||||
for (auto el : { "infill_direction", "sparse_infill_line_width",
|
||||
"sparse_infill_speed", "bridge_speed" })
|
||||
"sparse_infill_speed", "bridge_speed", "bridge_angle" })
|
||||
toggle_field(el, have_infill || has_solid_infill);
|
||||
|
||||
toggle_field("top_shell_thickness", ! has_spiral_vase && has_top_solid_infill);
|
||||
|
|
@ -483,9 +483,14 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
|
||||
bool have_default_acceleration = config->opt_float("default_acceleration") > 0;
|
||||
//BBS
|
||||
for (auto el : { "initial_layer_acceleration", "top_surface_acceleration" })
|
||||
for (auto el : { "outer_wall_acceleration", "inner_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration","travel_acceleration" })
|
||||
toggle_field(el, have_default_acceleration);
|
||||
|
||||
bool have_default_jerk = config->opt_float("default_jerk") > 0;
|
||||
|
||||
for (auto el : { "outer_wall_jerk", "inner_wall_jerk", "initial_layer_jerk", "top_surface_jerk","travel_jerk" })
|
||||
toggle_field(el, have_default_jerk);
|
||||
|
||||
bool have_skirt = config->opt_int("skirt_loops") > 0;
|
||||
toggle_field("skirt_height", have_skirt && config->opt_enum<DraftShield>("draft_shield") != dsEnabled);
|
||||
for (auto el : { "skirt_distance", "draft_shield"})
|
||||
|
|
|
|||
|
|
@ -2394,7 +2394,7 @@ ConfigWizard::ConfigWizard(wxWindow *parent)
|
|||
p->load_vendors();
|
||||
//BBS: add bed exclude areas
|
||||
p->custom_config.reset(DynamicPrintConfig::new_from_defaults_keys({
|
||||
"gcode_flavor", "printable_area", "bed_exclude_area", "nozzle_diameter", "filament_diameter", "nozzle_temperature", /*"bed_temperature",*/
|
||||
"gcode_flavor", "printable_area", "bed_exclude_area", "filament_diameter", "nozzle_temperature", "thumbnails"/*"bed_temperature",*/
|
||||
}));
|
||||
|
||||
auto *vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
|
|
|||
|
|
@ -4708,12 +4708,12 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
double width = volumes_box.max.x() - volumes_box.min.x();
|
||||
double depth = volumes_box.max.y() - volumes_box.min.y();
|
||||
double height = volumes_box.max.z() - volumes_box.min.z();
|
||||
volumes_box.max.x() = volumes_box.max.x() + width * 0.25f;
|
||||
volumes_box.min.x() = volumes_box.min.x() - width * 0.25f;
|
||||
volumes_box.max.y() = volumes_box.max.y() + depth * 0.25f;
|
||||
volumes_box.min.y() = volumes_box.min.y() - depth * 0.25f;
|
||||
volumes_box.max.z() = volumes_box.max.z() + height * 0.25f;
|
||||
volumes_box.min.z() = volumes_box.min.z() - height * 0.25f;
|
||||
volumes_box.max.x() = volumes_box.max.x() + width * 0.05f;
|
||||
volumes_box.min.x() = volumes_box.min.x() - width * 0.05f;
|
||||
volumes_box.max.y() = volumes_box.max.y() + depth * 0.05f;
|
||||
volumes_box.min.y() = volumes_box.min.y() - depth * 0.05f;
|
||||
volumes_box.max.z() = volumes_box.max.z() + height * 0.05f;
|
||||
volumes_box.min.z() = volumes_box.min.z() - height * 0.05f;
|
||||
|
||||
Camera camera;
|
||||
camera.set_type(camera_type);
|
||||
|
|
@ -4728,16 +4728,11 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
camera.zoom_to_box(volumes_box);
|
||||
const Vec3d& target = camera.get_target();
|
||||
double distance = camera.get_distance();
|
||||
//camera.select_view("topfront");
|
||||
camera.look_at(target - 0.707 * distance * Vec3d::UnitY() + 0.3 * distance * Vec3d::UnitZ(), target, Vec3d::UnitY() + Vec3d::UnitZ());
|
||||
camera.select_view("iso");
|
||||
camera.apply_view_matrix();
|
||||
|
||||
camera.apply_projection(plate_build_volume);
|
||||
|
||||
//double near_z = -1.0;
|
||||
//double far_z = -1.0;
|
||||
//camera.apply_projection(volumes_box, near_z, far_z);
|
||||
|
||||
//GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
|
||||
if (shader == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("render_thumbnail: shader is null, return directly");
|
||||
|
|
@ -4745,7 +4740,7 @@ void GLCanvas3D::render_thumbnail_internal(ThumbnailData& thumbnail_data, const
|
|||
}
|
||||
|
||||
//if (thumbnail_params.transparent_background)
|
||||
glsafe(::glClearColor(0.906f, 0.906f, 0.906f, 1.0f));
|
||||
glsafe(::glClearColor(0.2f, 0.2f, 0.2f, 0.0f));
|
||||
|
||||
glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||
}
|
||||
break;
|
||||
case coPoints:{
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area") {
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "thumbnails") {
|
||||
config.option<ConfigOptionPoints>(opt_key)->values = boost::any_cast<std::vector<Vec2d>>(value);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,14 +280,15 @@ public:
|
|||
memDc.SetTextForeground(wxColor(134, 134, 134));
|
||||
memDc.DrawLabel(m_constant_text.version, version_rect, wxALIGN_LEFT | wxALIGN_BOTTOM);
|
||||
|
||||
#if BBL_INTERNAL_TESTING
|
||||
wxSize text_rect = memDc.GetTextExtent("Internal Version");
|
||||
// #if BBL_INTERNAL_TESTING
|
||||
auto sf_version = wxString::Format("SoftFever %s",std::string(SoftFever_VERSION)).ToStdString();
|
||||
wxSize text_rect = memDc.GetTextExtent(sf_version);
|
||||
int start_x = (title_rect.GetLeft() + version_rect.GetRight()) / 2 - text_rect.GetWidth();
|
||||
int start_y = version_rect.GetBottom() + 10;
|
||||
wxRect internal_sign_rect(wxPoint(start_x, start_y), wxSize(text_rect));
|
||||
memDc.SetFont(m_constant_text.title_font);
|
||||
memDc.DrawLabel("Internal Version", internal_sign_rect, wxALIGN_TOP | wxALIGN_LEFT);
|
||||
#endif
|
||||
memDc.SetFont(m_constant_text.version_font);
|
||||
memDc.DrawLabel(sf_version, internal_sign_rect, wxALIGN_CENTER);
|
||||
// #endif
|
||||
|
||||
// load bitmap for logo
|
||||
BitmapCache bmp_cache;
|
||||
|
|
@ -554,11 +555,11 @@ private:
|
|||
title = wxGetApp().is_editor() ? SLIC3R_APP_FULL_NAME : GCODEVIEWER_APP_NAME;
|
||||
|
||||
// dynamically get the version to display
|
||||
#if BBL_INTERNAL_TESTING
|
||||
version = _L("Internal Version") + " " + std::string(SLIC3R_VERSION);
|
||||
#else
|
||||
version = _L("Version") + " " + std::string(SLIC3R_VERSION);
|
||||
#endif
|
||||
// #if BBL_INTERNAL_TESTING
|
||||
// version = _L("Internal Version") + " " + std::string(SLIC3R_VERSION);
|
||||
// #else
|
||||
version = _L("SoftFever Version") + " " + std::string(SoftFever_VERSION);
|
||||
// #endif
|
||||
|
||||
// credits infornation
|
||||
credits = title;
|
||||
|
|
@ -1812,7 +1813,7 @@ void GUI_App::init_download_path()
|
|||
void GUI_App::init_app_config()
|
||||
{
|
||||
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
|
||||
SetAppName(SLIC3R_APP_KEY);
|
||||
SetAppName("BambuStudio-SoftFever");
|
||||
// SetAppName(SLIC3R_APP_KEY "-alpha");
|
||||
// SetAppName(SLIC3R_APP_KEY "-beta");
|
||||
// SetAppDisplayName(SLIC3R_APP_NAME);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "ConfigWizard.hpp"
|
||||
#include "OpenGLManager.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/DeviceManager.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
|
|
@ -45,6 +46,7 @@ class AppConfig;
|
|||
class PresetBundle;
|
||||
class PresetUpdater;
|
||||
class ModelObject;
|
||||
// class PrintHostJobQueue;
|
||||
class Model;
|
||||
class DeviceManager;
|
||||
class NetworkAgent;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CAT
|
|||
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1},
|
||||
{"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1},
|
||||
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1},
|
||||
{"infill_combination", "",1}, {"infill_wall_overlap", "",1}, {"infill_direction", "",1}, {"minimum_sparse_infill_area", "",1}
|
||||
{"infill_combination", "",1}, {"infill_wall_overlap", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
|
||||
}},
|
||||
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},
|
||||
{"enable_overhang_speed", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ wxDEFINE_EVENT(EVT_USER_LOGIN, wxCommandEvent);
|
|||
// BBS: backup
|
||||
wxDEFINE_EVENT(EVT_BACKUP_POST, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_LOAD_URL, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_LOAD_PRINTER_URL, wxCommandEvent);
|
||||
|
||||
enum class ERescaleTarget
|
||||
{
|
||||
|
|
@ -934,6 +935,13 @@ void MainFrame::init_tabpanel()
|
|||
m_monitor = new MonitorPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_tabpanel->AddPage(m_monitor, _L("Device"), std::string("tab_monitor_active"), std::string("tab_monitor_active"));
|
||||
|
||||
m_printer_view = new PrinterWebView(m_tabpanel);
|
||||
Bind(EVT_LOAD_PRINTER_URL, [this](wxCommandEvent &evt) {
|
||||
wxString url = evt.GetString();
|
||||
//select_tab(MainFrame::tpMonitor);
|
||||
m_printer_view->load_url(url);
|
||||
});
|
||||
|
||||
m_auxiliary = new AuxiliaryPanel(m_tabpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
|
||||
m_tabpanel->AddPage(m_auxiliary, _L("Project"), std::string("tab_auxiliary_avtice"), std::string("tab_auxiliary_avtice"));
|
||||
|
||||
|
|
@ -951,6 +959,33 @@ void MainFrame::init_tabpanel()
|
|||
}
|
||||
}
|
||||
|
||||
// SoftFever
|
||||
void MainFrame::show_device(bool bBBLPrinter) {
|
||||
if (m_tabpanel->GetPage(3) != m_monitor &&
|
||||
m_tabpanel->GetPage(3) != m_printer_view) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to find device tab";
|
||||
return;
|
||||
}
|
||||
if (bBBLPrinter) {
|
||||
if (m_tabpanel->GetPage(3) != m_monitor) {
|
||||
m_tabpanel->RemovePage(3);
|
||||
m_tabpanel->InsertPage(3, m_monitor, _L("Device"),
|
||||
std::string("tab_monitor_active"),
|
||||
std::string("tab_monitor_active"));
|
||||
}
|
||||
} else {
|
||||
if (m_tabpanel->GetPage(3) != m_printer_view) {
|
||||
m_tabpanel->RemovePage(3);
|
||||
m_tabpanel->InsertPage(3, m_printer_view, _L("Device"),
|
||||
std::string("tab_monitor_active"),
|
||||
std::string("tab_monitor_active"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
void MainFrame::register_win32_callbacks()
|
||||
{
|
||||
|
|
@ -2859,6 +2894,13 @@ void MainFrame::load_url(wxString url)
|
|||
wxQueueEvent(this, evt);
|
||||
}
|
||||
|
||||
void MainFrame::load_printer_url(wxString url)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << "load_printer_url:" << url;
|
||||
auto evt = new wxCommandEvent(EVT_LOAD_PRINTER_URL, this->GetId());
|
||||
evt->SetString(url);
|
||||
wxQueueEvent(this, evt);
|
||||
}
|
||||
void MainFrame::refresh_plugin_tips()
|
||||
{
|
||||
if (m_webview != nullptr)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "BBLTopbar.hpp"
|
||||
|
||||
|
||||
#include "PrinterWebView.hpp"
|
||||
|
||||
#define ENABEL_PRINT_ALL 0
|
||||
|
||||
class Notebook;
|
||||
|
|
@ -307,9 +309,13 @@ public:
|
|||
|
||||
//BBS
|
||||
void load_url(wxString url);
|
||||
void load_printer_url(wxString url);
|
||||
void refresh_plugin_tips();
|
||||
void RunScript(wxString js);
|
||||
|
||||
//SoftFever
|
||||
void show_device(bool bBBLPrinter);
|
||||
|
||||
// BBS. Replace title bar and menu bar with top bar.
|
||||
BBLTopbar* m_topbar{ nullptr };
|
||||
PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; }
|
||||
|
|
@ -318,6 +324,7 @@ public:
|
|||
MonitorPanel* m_monitor{ nullptr };
|
||||
AuxiliaryPanel* m_auxiliary{ nullptr };
|
||||
WebViewPanel* m_webview { nullptr };
|
||||
PrinterWebView* m_printer_view{nullptr};
|
||||
wxLogWindow* m_log_window { nullptr };
|
||||
// BBS
|
||||
//wxBookCtrlBase* m_tabpanel { nullptr };
|
||||
|
|
|
|||
|
|
@ -114,9 +114,13 @@ Button* MsgDialog::add_button(wxWindowID btn_id, bool set_focus /*= false*/, con
|
|||
else if (label.length() >= 5 && label.length() < 8) {
|
||||
type = ButtonSizeMiddle;
|
||||
btn->SetMinSize(MSG_DIALOG_MIDDLE_BUTTON_SIZE);
|
||||
}
|
||||
else if (label.length() >= 8 && label.length() < 12) {
|
||||
type = ButtonSizeMiddle;
|
||||
btn->SetMinSize(MSG_DIALOG_LONG_BUTTON_SIZE);
|
||||
} else {
|
||||
type = ButtonSizeLong;
|
||||
btn->SetMinSize(MSG_DIALOG_LONG_BUTTON_SIZE);
|
||||
btn->SetMinSize(MSG_DIALOG_LONGER_BUTTON_SIZE);
|
||||
}
|
||||
|
||||
btn->SetCornerRadius(FromDIP(12));
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ enum ButtonSizeType{
|
|||
#define MSG_DIALOG_BUTTON_SIZE wxSize(FromDIP(58), FromDIP(24))
|
||||
#define MSG_DIALOG_MIDDLE_BUTTON_SIZE wxSize(FromDIP(76), FromDIP(24))
|
||||
#define MSG_DIALOG_LONG_BUTTON_SIZE wxSize(FromDIP(90), FromDIP(24))
|
||||
#define MSG_DIALOG_LONGER_BUTTON_SIZE wxSize(FromDIP(120), FromDIP(24))
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
|
|
|||
|
|
@ -670,7 +670,7 @@ void ConfigOptionsGroup::back_to_config_value(const DynamicPrintConfig& config,
|
|||
else if (m_opt_map.find(opt_key) == m_opt_map.end() ||
|
||||
// This option don't have corresponded field
|
||||
opt_key == "printable_area" ||
|
||||
opt_key == "compatible_printers" || opt_key == "compatible_prints" ) {
|
||||
opt_key == "compatible_printers" || opt_key == "compatible_prints" || opt_key == "thumbnails" ) {
|
||||
value = get_config_value(config, opt_key);
|
||||
this->change_opt_value(opt_key, value);
|
||||
return;
|
||||
|
|
@ -950,6 +950,14 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
|||
case coInts:
|
||||
ret = config.option<ConfigOptionIntsNullable>(opt_key)->get_at(idx);
|
||||
break;
|
||||
case coPoints:
|
||||
if (opt_key == "bed_shape")
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->values;
|
||||
else if (opt_key == "thumbnails")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1026,6 +1034,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
|||
if (opt_key == "printable_area")
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->values;
|
||||
else if (opt_key == "bed_exclude_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "thumbnails")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
|
|
@ -1137,6 +1147,8 @@ boost::any ConfigOptionsGroup::get_config_value2(const DynamicPrintConfig& confi
|
|||
ret = config.option<ConfigOptionPoints>(opt_key)->values;
|
||||
else if (opt_key == "bed_exclude_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "thumbnails")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
#include "format.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
//#include "PrintHostDialogs.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
#include "../Utils/ASCIIFolding.hpp"
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
#include "../Utils/FixModelByWin10.hpp"
|
||||
|
|
@ -189,7 +189,6 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
|||
Option option = m_optgroup->get_option("print_host");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line host_line = m_optgroup->create_single_option_line(option);
|
||||
//do not support now
|
||||
host_line.append_widget(printhost_browse);
|
||||
host_line.append_widget(print_host_test);
|
||||
m_optgroup->append_line(host_line);
|
||||
|
|
@ -228,36 +227,36 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
|||
};
|
||||
|
||||
cafile_line.append_widget(printhost_cafile_browse);
|
||||
//m_optgroup->append_line(cafile_line);
|
||||
m_optgroup->append_line(cafile_line);
|
||||
|
||||
/*Line cafile_hint{ "", "" };
|
||||
Line cafile_hint{ "", "" };
|
||||
cafile_hint.full_width = 1;
|
||||
cafile_hint.widget = [ca_file_hint](wxWindow* parent) {
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint);
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt);
|
||||
return sizer;
|
||||
};*/
|
||||
//m_optgroup->append_line(cafile_hint);
|
||||
};
|
||||
m_optgroup->append_line(cafile_hint);
|
||||
}
|
||||
else {
|
||||
|
||||
//Line line{ "", "" };
|
||||
//line.full_width = 1;
|
||||
Line line{ "", "" };
|
||||
line.full_width = 1;
|
||||
|
||||
//line.widget = [ca_file_hint](wxWindow* parent) {
|
||||
// std::string info = _u8L("HTTPS CA File") + ":\n\t" +
|
||||
// (boost::format(_u8L("On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.")) % SLIC3R_APP_NAME).str() +
|
||||
// "\n\t" + _u8L("To use a custom CA file, please import your CA file into Certificate Store / Keychain.");
|
||||
line.widget = [ca_file_hint](wxWindow* parent) {
|
||||
std::string info = _u8L("HTTPS CA File") + ":\n\t" +
|
||||
(boost::format(_u8L("On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.")) % SLIC3R_APP_NAME).str() +
|
||||
"\n\t" + _u8L("To use a custom CA file, please import your CA file into Certificate Store / Keychain.");
|
||||
|
||||
// //auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\n\t%2%") % info % ca_file_hint).str()));
|
||||
// auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\t%2%") % info % ca_file_hint).str()));
|
||||
// txt->SetFont(wxGetApp().normal_font());
|
||||
// auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
// sizer->Add(txt, 1, wxEXPAND);
|
||||
// return sizer;
|
||||
//};
|
||||
//m_optgroup->append_line(line);
|
||||
//auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\n\t%2%") % info % ca_file_hint).str()));
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\t%2%") % info % ca_file_hint).str()));
|
||||
txt->SetFont(wxGetApp().normal_font());
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt, 1, wxEXPAND);
|
||||
return sizer;
|
||||
};
|
||||
m_optgroup->append_line(line);
|
||||
}
|
||||
|
||||
for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" }) {
|
||||
|
|
@ -267,13 +266,10 @@ void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgr
|
|||
}
|
||||
|
||||
#ifdef WIN32
|
||||
/*
|
||||
option = m_optgroup->get_option("printhost_ssl_ignore_revoke");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
m_optgroup->append_single_option_line(option);
|
||||
*/
|
||||
#endif
|
||||
|
||||
|
||||
m_optgroup->activate();
|
||||
|
||||
|
|
@ -422,6 +418,7 @@ void PhysicalPrinterDialog::update(bool printer_change)
|
|||
m_optgroup->hide_field(opt_key);
|
||||
supports_multiple_printers = opt && opt->value == htRepetier;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false);
|
||||
|
|
|
|||
|
|
@ -911,17 +911,22 @@ void Sidebar::update_all_preset_comboboxes()
|
|||
|
||||
bool is_bbl_preset = preset_bundle.printers.get_edited_preset().is_bbl_vendor_preset(&preset_bundle);
|
||||
|
||||
auto p_mainframe = wxGetApp().mainframe;
|
||||
|
||||
p_mainframe->show_device(is_bbl_preset);
|
||||
if (is_bbl_preset) {
|
||||
//only show connection button for not-BBL printer
|
||||
connection_btn->Hide();
|
||||
//only show sync-ams button for BBL printer
|
||||
ams_btn->Show();
|
||||
//update print button default value for bbl or third-party printer
|
||||
wxGetApp().mainframe->set_print_button_to_default(MainFrame::PrintSelectType::ePrintPlate);
|
||||
p_mainframe->set_print_button_to_default(MainFrame::PrintSelectType::ePrintPlate);
|
||||
|
||||
} else {
|
||||
connection_btn->Show();
|
||||
ams_btn->Hide();
|
||||
wxGetApp().mainframe->set_print_button_to_default(MainFrame::PrintSelectType::eSendGcode);
|
||||
p_mainframe->set_print_button_to_default(MainFrame::PrintSelectType::eSendGcode);
|
||||
p_mainframe->load_printer_url(wxString::Format("http://%s",preset_bundle.printers.get_edited_preset().config.opt_string("print_host")));
|
||||
}
|
||||
|
||||
// Update the print choosers to only contain the compatible presets, update the dirty flags.
|
||||
|
|
@ -9080,7 +9085,7 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool up
|
|||
upload_job.printhost->get_groups(groups);
|
||||
}
|
||||
|
||||
PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, upload_only);
|
||||
PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups);
|
||||
if (dlg.ShowModal() == wxID_OK) {
|
||||
upload_job.upload_data.upload_path = dlg.filename();
|
||||
upload_job.upload_data.post_action = dlg.post_action();
|
||||
|
|
@ -10646,4 +10651,4 @@ SuppressBackgroundProcessingUpdate::~SuppressBackgroundProcessingUpdate()
|
|||
wxGetApp().plater()->schedule_background_process(m_was_scheduled);
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
||||
}} // namespace Slic3r::GUI
|
||||
|
|
@ -687,4 +687,4 @@ private:
|
|||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -36,8 +36,8 @@ namespace GUI {
|
|||
static const char *CONFIG_KEY_PATH = "printhost_path";
|
||||
static const char *CONFIG_KEY_GROUP = "printhost_group";
|
||||
|
||||
PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups, bool upload_only)
|
||||
: MsgDialog(static_cast<wxWindow*>(wxGetApp().mainframe), _L("Upload and Print"), _L("Upload to Printer Host with the following filename:"),0)
|
||||
PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups)
|
||||
: MsgDialog(static_cast<wxWindow*>(wxGetApp().mainframe), _L("Send to print"), _L("Upload to Printer Host with the following filename:"),0)
|
||||
, txt_filename(new wxTextCtrl(this, wxID_ANY))
|
||||
, combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr)
|
||||
, post_upload_action(PrintHostPostUploadAction::None)
|
||||
|
|
@ -88,19 +88,7 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
|
|||
return true;
|
||||
};
|
||||
|
||||
auto* btn_confirm = add_button(wxID_YES, false, _L("Confirm"));
|
||||
btn_confirm->Bind(wxEVT_BUTTON, [this, upload_only, validate_path](wxCommandEvent&) {
|
||||
if (validate_path(txt_filename->GetValue())) {
|
||||
if (upload_only) {
|
||||
post_upload_action = PrintHostPostUploadAction::None;
|
||||
} else {
|
||||
post_upload_action = PrintHostPostUploadAction::StartPrint;
|
||||
}
|
||||
EndDialog(wxID_OK);
|
||||
}
|
||||
});
|
||||
|
||||
/*auto* btn_upload = add_button(wxID_YES, false, _L("Upload"));
|
||||
auto* btn_upload = add_button(wxID_YES, false, _L("Upload"));
|
||||
btn_upload->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) {
|
||||
if (validate_path(txt_filename->GetValue())) {
|
||||
post_upload_action = PrintHostPostUploadAction::None;
|
||||
|
|
@ -108,7 +96,7 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
|
|||
}
|
||||
});
|
||||
|
||||
if (post_actions.has(PrintHostPostUploadAction::StartPrint) && !upload_only) {
|
||||
if (post_actions.has(PrintHostPostUploadAction::StartPrint)) {
|
||||
auto* btn_print = add_button(wxID_YES, false, _L("Upload and Print"));
|
||||
btn_print->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) {
|
||||
if (validate_path(txt_filename->GetValue())) {
|
||||
|
|
@ -128,9 +116,8 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
|
|||
}
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
add_button(wxID_CANCEL, false, "Cancel");
|
||||
add_button(wxID_CANCEL,false,"Cancel");
|
||||
finalize();
|
||||
|
||||
#ifdef __linux__
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace GUI {
|
|||
class PrintHostSendDialog : public GUI::MsgDialog
|
||||
{
|
||||
public:
|
||||
PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups, bool upload_only);
|
||||
PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups);
|
||||
boost::filesystem::path filename() const;
|
||||
PrintHostPostUploadAction post_action() const;
|
||||
std::string group() const;
|
||||
|
|
|
|||
125
src/slic3r/GUI/PrinterWebView.cpp
Normal file
125
src/slic3r/GUI/PrinterWebView.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#include "PrinterWebView.hpp"
|
||||
|
||||
#include "I18N.hpp"
|
||||
#include "slic3r/GUI/wxExtensions.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/MainFrame.hpp"
|
||||
#include "libslic3r_version.h"
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/toolbar.h>
|
||||
#include <wx/textdlg.h>
|
||||
|
||||
#include <slic3r/GUI/Widgets/WebView.hpp>
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
PrinterWebView::PrinterWebView(wxWindow *parent)
|
||||
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize)
|
||||
{
|
||||
|
||||
wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// Create the button
|
||||
bSizer_toolbar = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
//m_button_reload = new wxButton(this, wxID_ANY, wxT("Reload"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
//bSizer_toolbar->Add(m_button_reload, 0, wxALL, 5);
|
||||
|
||||
m_url = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
||||
bSizer_toolbar->Add(m_url, 1, wxALL | wxEXPAND, 5);
|
||||
|
||||
|
||||
// Create the webview
|
||||
m_browser = WebView::CreateWebView(this, "");
|
||||
if (m_browser == nullptr) {
|
||||
wxLogError("Could not init m_browser");
|
||||
return;
|
||||
}
|
||||
|
||||
SetSizer(topsizer);
|
||||
|
||||
topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1));
|
||||
|
||||
// Log backend information
|
||||
if (wxGetApp().get_mode() == comDevelop) {
|
||||
wxLogMessage(wxWebView::GetBackendVersionInfo().ToString());
|
||||
wxLogMessage("Backend: %s Version: %s", m_browser->GetClassInfo()->GetClassName(),
|
||||
wxWebView::GetBackendVersionInfo().ToString());
|
||||
wxLogMessage("User Agent: %s", m_browser->GetUserAgent());
|
||||
}
|
||||
|
||||
//Zoom
|
||||
m_zoomFactor = 100;
|
||||
|
||||
// Connect the button events
|
||||
//Bind(wxEVT_BUTTON, &PrinterWebView::OnReload, this, m_button_reload->GetId());
|
||||
Bind(wxEVT_TEXT_ENTER, &PrinterWebView::OnUrl, this, m_url->GetId());
|
||||
//Connect the idle events
|
||||
Bind(wxEVT_CLOSE_WINDOW, &PrinterWebView::OnClose, this);
|
||||
|
||||
}
|
||||
|
||||
PrinterWebView::~PrinterWebView()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " Start";
|
||||
SetEvtHandlerEnabled(false);
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " End";
|
||||
}
|
||||
|
||||
|
||||
void PrinterWebView::load_url(wxString& url)
|
||||
{
|
||||
//this->Show();
|
||||
//this->Raise();
|
||||
m_url->SetLabelText(url);
|
||||
|
||||
if (wxGetApp().get_mode() == comDevelop)
|
||||
wxLogMessage(m_url->GetValue());
|
||||
m_browser->LoadURL(url);
|
||||
//m_browser->SetFocus();
|
||||
UpdateState();
|
||||
}
|
||||
/**
|
||||
* Method that retrieves the current state from the web control and updates the
|
||||
* GUI the reflect this current state.
|
||||
*/
|
||||
void PrinterWebView::UpdateState() {
|
||||
// SetTitle(m_browser->GetCurrentTitle());
|
||||
m_url->SetValue(m_browser->GetCurrentURL());
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when user entered an URL and pressed enter
|
||||
*/
|
||||
void PrinterWebView::OnUrl(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
if (wxGetApp().get_mode() == comDevelop)
|
||||
wxLogMessage(m_url->GetValue());
|
||||
m_browser->LoadURL(m_url->GetValue());
|
||||
m_browser->SetFocus();
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback invoked when user pressed the "reload" button
|
||||
*/
|
||||
void PrinterWebView::OnReload(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_browser->Reload();
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
void PrinterWebView::OnClose(wxCloseEvent& evt)
|
||||
{
|
||||
this->Hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
64
src/slic3r/GUI/PrinterWebView.hpp
Normal file
64
src/slic3r/GUI/PrinterWebView.hpp
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#ifndef slic3r_PrinterWebView_hpp_
|
||||
#define slic3r_PrinterWebView_hpp_
|
||||
|
||||
|
||||
#include "wx/artprov.h"
|
||||
#include "wx/cmdline.h"
|
||||
#include "wx/notifmsg.h"
|
||||
#include "wx/settings.h"
|
||||
#include "wx/webview.h"
|
||||
|
||||
#if wxUSE_WEBVIEW_EDGE
|
||||
#include "wx/msw/webview_edge.h"
|
||||
#endif
|
||||
|
||||
#include "wx/webviewarchivehandler.h"
|
||||
#include "wx/webviewfshandler.h"
|
||||
#include "wx/numdlg.h"
|
||||
#include "wx/infobar.h"
|
||||
#include "wx/filesys.h"
|
||||
#include "wx/fs_arc.h"
|
||||
#include "wx/fs_mem.h"
|
||||
#include "wx/stdpaths.h"
|
||||
#include <wx/panel.h>
|
||||
#include <wx/tbarbase.h>
|
||||
#include "wx/textctrl.h"
|
||||
#include <wx/timer.h>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
|
||||
class PrinterWebView : public wxPanel {
|
||||
public:
|
||||
PrinterWebView(wxWindow *parent);
|
||||
virtual ~PrinterWebView();
|
||||
|
||||
void load_url(wxString& url);
|
||||
|
||||
void UpdateState();
|
||||
void OnUrl(wxCommandEvent& evt);
|
||||
void OnReload(wxCommandEvent& evt);
|
||||
void OnClose(wxCloseEvent& evt);
|
||||
|
||||
private:
|
||||
|
||||
wxWebView* m_browser;
|
||||
wxBoxSizer *bSizer_toolbar;
|
||||
wxButton * m_button_reload;
|
||||
wxTextCtrl *m_url;
|
||||
|
||||
long m_zoomFactor;
|
||||
|
||||
// Last executed JavaScript snippet, for convenience.
|
||||
// wxString m_javascript;
|
||||
// wxString m_response_js;
|
||||
|
||||
// DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
||||
#endif /* slic3r_Tab_hpp_ */
|
||||
|
|
@ -43,6 +43,8 @@
|
|||
#include "MarkdownTip.hpp"
|
||||
#include "Search.hpp"
|
||||
|
||||
#include "BedShapeDialog.hpp"
|
||||
// #include "BonjourDialog.hpp"
|
||||
#ifdef WIN32
|
||||
#include <commctrl.h>
|
||||
#endif // WIN32
|
||||
|
|
@ -853,7 +855,7 @@ void TabPrinter::init_options_list()
|
|||
|
||||
for (const std::string& opt_key : m_config->keys())
|
||||
{
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area") {
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" | opt_key == "thumbnails") {
|
||||
m_options_list.emplace(opt_key, m_opt_status_value);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1779,8 +1781,11 @@ void TabPrint::build()
|
|||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("wall_infill_order");
|
||||
optgroup->append_single_option_line("bridge_flow");
|
||||
optgroup->append_single_option_line("top_solid_infill_flow_ratio");
|
||||
optgroup->append_single_option_line("bottom_solid_infill_flow_ratio");
|
||||
optgroup->append_single_option_line("thick_bridges");
|
||||
optgroup->append_single_option_line("only_one_wall_top");
|
||||
optgroup->append_single_option_line("only_one_wall_first_layer");
|
||||
optgroup->append_single_option_line("detect_overhang_wall");
|
||||
optgroup->append_single_option_line("reduce_crossing_wall");
|
||||
optgroup->append_single_option_line("max_travel_detour_distance");
|
||||
|
|
@ -1805,6 +1810,7 @@ void TabPrint::build()
|
|||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("infill_wall_overlap");
|
||||
optgroup->append_single_option_line("infill_direction");
|
||||
optgroup->append_single_option_line("bridge_angle");
|
||||
optgroup->append_single_option_line("minimum_sparse_infill_area");
|
||||
optgroup->append_single_option_line("infill_combination");
|
||||
optgroup->append_single_option_line("detect_narrow_internal_solid_infill");
|
||||
|
|
@ -1837,9 +1843,20 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("travel_speed");
|
||||
|
||||
optgroup = page->new_optgroup(L("Acceleration"), L"param_acceleration", 15);
|
||||
optgroup->append_single_option_line("default_acceleration");
|
||||
optgroup->append_single_option_line("outer_wall_acceleration");
|
||||
optgroup->append_single_option_line("inner_wall_acceleration");
|
||||
optgroup->append_single_option_line("initial_layer_acceleration");
|
||||
optgroup->append_single_option_line("top_surface_acceleration");
|
||||
optgroup->append_single_option_line("default_acceleration");
|
||||
optgroup->append_single_option_line("travel_acceleration");
|
||||
|
||||
optgroup = page->new_optgroup(L("Jerk(XY)"));
|
||||
optgroup->append_single_option_line("default_jerk");
|
||||
optgroup->append_single_option_line("outer_wall_jerk");
|
||||
optgroup->append_single_option_line("inner_wall_jerk");
|
||||
optgroup->append_single_option_line("top_surface_jerk");
|
||||
optgroup->append_single_option_line("initial_layer_jerk");
|
||||
optgroup->append_single_option_line("travel_jerk");
|
||||
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
optgroup->append_single_option_line("max_volumetric_extrusion_rate_slope_positive");
|
||||
|
|
@ -1922,7 +1939,10 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("reduce_infill_retraction");
|
||||
optgroup->append_single_option_line("gcode_add_line_number");
|
||||
Option option = optgroup->get_option("filename_format");
|
||||
option.opt.full_width = true;
|
||||
// option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.multiline = true;
|
||||
// option.opt.height = 5;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
#if 0
|
||||
|
|
@ -2424,6 +2444,10 @@ void TabFilament::build()
|
|||
//optgroup->append_single_option_line("filament_colour");
|
||||
optgroup->append_single_option_line("filament_diameter");
|
||||
optgroup->append_single_option_line("filament_flow_ratio");
|
||||
|
||||
optgroup->append_single_option_line("enable_pressure_advance");
|
||||
optgroup->append_single_option_line("pressure_advance");
|
||||
|
||||
optgroup->append_single_option_line("filament_density");
|
||||
optgroup->append_single_option_line("filament_cost");
|
||||
//BBS
|
||||
|
|
@ -2439,6 +2463,10 @@ void TabFilament::build()
|
|||
optgroup = page->new_optgroup(L("Print temperature"), L"param_temperature");
|
||||
optgroup->split_multi_line = true;
|
||||
optgroup->option_label_at_right = true;
|
||||
line = { L("Chamber temperature"), L("Chamber temperature") };
|
||||
line.append_option(optgroup->get_option("chamber_temperature"));
|
||||
optgroup->append_line(line);
|
||||
|
||||
line = { L("Nozzle"), L("Nozzle temperature when printing") };
|
||||
line.append_option(optgroup->get_option("nozzle_temperature_initial_layer"));
|
||||
line.append_option(optgroup->get_option("nozzle_temperature"));
|
||||
|
|
@ -2637,7 +2665,11 @@ void TabFilament::toggle_options()
|
|||
for (auto el : { "overhang_fan_speed", "overhang_fan_threshold" })
|
||||
toggle_option(el, has_enable_overhang_bridge_fan);
|
||||
}
|
||||
|
||||
if (m_active_page->title() == "Filament")
|
||||
{
|
||||
bool pa = m_config->opt_bool("enable_pressure_advance");
|
||||
toggle_option("pressure_advance", pa);
|
||||
}
|
||||
if (m_active_page->title() == "Setting Overrides")
|
||||
update_filament_overrides_page();
|
||||
}
|
||||
|
|
@ -2729,12 +2761,13 @@ void TabPrinter::build_fff()
|
|||
auto page = add_options_page(L("Basic information"), "printer");
|
||||
auto optgroup = page->new_optgroup(L("Printable space")/*, L"param_printable_space"*/);
|
||||
|
||||
//create_line_with_widget(optgroup.get(), "printable_area", "custom-svg-and-png-bed-textures_124612", [this](wxWindow* parent) {
|
||||
// return create_bed_shape_widget(parent);
|
||||
//});
|
||||
create_line_with_widget(optgroup.get(), "printable_area", "custom-svg-and-png-bed-textures_124612", [this](wxWindow* parent) {
|
||||
return create_bed_shape_widget(parent);
|
||||
});
|
||||
Option option = optgroup->get_option("bed_exclude_area");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option);
|
||||
// optgroup->append_single_option_line("printable_area");
|
||||
optgroup->append_single_option_line("printable_height");
|
||||
optgroup->append_single_option_line("nozzle_volume");
|
||||
// BBS
|
||||
|
|
@ -2835,6 +2868,9 @@ void TabPrinter::build_fff()
|
|||
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
optgroup->append_single_option_line("gcode_flavor");
|
||||
option = optgroup->get_option("thumbnails");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option);
|
||||
optgroup->append_single_option_line("scan_first_layer");
|
||||
// optgroup->append_single_option_line("spaghetti_detector");
|
||||
optgroup->append_single_option_line("machine_load_filament_time");
|
||||
|
|
@ -2870,8 +2906,8 @@ void TabPrinter::build_fff()
|
|||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option);
|
||||
#if 0
|
||||
optgroup = page->new_optgroup(L("Before layer change G-code"), 0);
|
||||
|
||||
optgroup = page->new_optgroup(L("Before layer change G-code"),"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup, opt_key, value);
|
||||
};
|
||||
|
|
@ -2880,7 +2916,6 @@ void TabPrinter::build_fff()
|
|||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option);
|
||||
#endif
|
||||
|
||||
optgroup = page->new_optgroup(L("Layer change G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
|
|
@ -2926,7 +2961,6 @@ void TabPrinter::build_fff()
|
|||
|
||||
// build_preset_description_line(optgroup.get());
|
||||
#endif
|
||||
|
||||
build_unregular_pages(true);
|
||||
}
|
||||
|
||||
|
|
@ -3100,7 +3134,7 @@ void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/)
|
|||
{
|
||||
size_t n_before_extruders = 2; // Count of pages before Extruder pages
|
||||
auto flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
|
||||
bool is_marlin_flavor = (flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware);
|
||||
bool is_marlin_flavor = (flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfKlipper);
|
||||
|
||||
/* ! Freeze/Thaw in this function is needed to avoid call OnPaint() for erased pages
|
||||
* and be cause of application crash, when try to change Preset in moment,
|
||||
|
|
@ -3231,6 +3265,7 @@ void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/)
|
|||
optgroup = page->new_optgroup(L("Retraction"), L"param_retraction");
|
||||
optgroup->append_single_option_line("retraction_length", "", extruder_idx);
|
||||
optgroup->append_single_option_line("z_hop", "", extruder_idx);
|
||||
optgroup->append_single_option_line("z_lift_type", "", extruder_idx);
|
||||
optgroup->append_single_option_line("retraction_speed", "", extruder_idx);
|
||||
optgroup->append_single_option_line("deretraction_speed", "", extruder_idx);
|
||||
//optgroup->append_single_option_line("retract_restart_extra", "", extruder_idx);
|
||||
|
|
@ -3447,9 +3482,9 @@ void TabPrinter::toggle_options()
|
|||
toggle_option("retract_restart_extra_toolchange", have_multiple_extruders && toolchange_retraction, i);
|
||||
}
|
||||
|
||||
if (m_active_page->title() == "Motion ability") {
|
||||
assert(m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlinLegacy
|
||||
|| m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlinFirmware);
|
||||
auto gcf = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
|
||||
if (m_active_page->title() == "Motion ability") {
|
||||
assert(gcf == gcfMarlinLegacy || gcf == gcfMarlinFirmware || gcf == gcfKlipper);
|
||||
bool silent_mode = m_config->opt_bool("silent_mode");
|
||||
int max_field = silent_mode ? 2 : 1;
|
||||
//BBS: limits of BBL printer can't be edited.
|
||||
|
|
@ -3481,7 +3516,9 @@ void TabPrinter::update_fff()
|
|||
m_use_silent_mode = m_config->opt_bool("silent_mode");
|
||||
}
|
||||
|
||||
bool supports_travel_acceleration = (m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlinFirmware);
|
||||
auto gcf_ =
|
||||
m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
|
||||
bool supports_travel_acceleration = (gcf_ == gcfMarlinFirmware || gcf_ == gcfMarlinLegacy || gcf_ == gcfKlipper);
|
||||
if (m_supports_travel_acceleration != supports_travel_acceleration) {
|
||||
m_rebuild_kinematics_page = true;
|
||||
m_supports_travel_acceleration = supports_travel_acceleration;
|
||||
|
|
@ -4609,7 +4646,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
|
|||
}
|
||||
|
||||
// Return a callback to create a TabPrinter widget to edit bed shape
|
||||
/*wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent)
|
||||
wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent)
|
||||
{
|
||||
ScalableButton* btn = new ScalableButton(parent, wxID_ANY, "printer", " " + _(L("Set")) + " " + dots,
|
||||
wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT, true);
|
||||
|
|
@ -4639,7 +4676,7 @@ wxSizer* Tab::compatible_widget_create(wxWindow* parent, PresetDependencies &dep
|
|||
}
|
||||
|
||||
return sizer;
|
||||
}*/
|
||||
}
|
||||
|
||||
void TabPrinter::cache_extruder_cnt()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -547,6 +547,7 @@ private:
|
|||
std::vector<PageShp> m_pages_fff;
|
||||
std::vector<PageShp> m_pages_sla;
|
||||
|
||||
wxBoxSizer* m_presets_sizer {nullptr};
|
||||
public:
|
||||
ScalableButton* m_reset_to_filament_color = nullptr;
|
||||
|
||||
|
|
@ -582,9 +583,10 @@ public:
|
|||
void msw_rescale() override;
|
||||
bool supports_printer_technology(const PrinterTechnology /* tech */) const override { return true; }
|
||||
|
||||
//wxSizer* create_bed_shape_widget(wxWindow* parent);
|
||||
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
||||
void cache_extruder_cnt();
|
||||
bool apply_extruder_cnt_from_cache();
|
||||
|
||||
};
|
||||
|
||||
class TabSLAMaterial : public Tab
|
||||
|
|
|
|||
|
|
@ -1315,7 +1315,7 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
|
|||
}
|
||||
case coPoints: {
|
||||
//BBS: add bed_exclude_area
|
||||
if (opt_key == "printable_area") {
|
||||
if (opt_key == "printable_area" || opt_key == "thumbnails") {
|
||||
ConfigOptionPoints points = *config.option<ConfigOptionPoints>(opt_key);
|
||||
//BuildVolume build_volume = {points.values, 0.};
|
||||
return get_thumbnails_string(points.values);
|
||||
|
|
|
|||
173
src/slic3r/Utils/AstroBox.cpp
Normal file
173
src/slic3r/Utils/AstroBox.cpp
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
#include "AstroBox.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <wx/progdlg.h>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "Http.hpp"
|
||||
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
AstroBox::AstroBox(DynamicPrintConfig *config) :
|
||||
host(config->opt_string("print_host")),
|
||||
apikey(config->opt_string("printhost_apikey")),
|
||||
cafile(config->opt_string("printhost_cafile"))
|
||||
{}
|
||||
|
||||
const char* AstroBox::get_name() const { return "AstroBox"; }
|
||||
|
||||
bool AstroBox::test(wxString &msg) const
|
||||
{
|
||||
// Since the request is performed synchronously here,
|
||||
// it is ok to refer to `msg` from within the closure
|
||||
|
||||
const char *name = get_name();
|
||||
|
||||
bool res = true;
|
||||
auto url = make_url("api/version");
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get version at: %2%") % name % url;
|
||||
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
res = false;
|
||||
msg = format_error(body, error, status);
|
||||
})
|
||||
.on_complete([&, this](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body;
|
||||
|
||||
try {
|
||||
std::stringstream ss(body);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
|
||||
if (! ptree.get_optional<std::string>("api")) {
|
||||
res = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto text = ptree.get_optional<std::string>("text");
|
||||
res = validate_version_text(text);
|
||||
if (! res) {
|
||||
msg = GUI::from_u8((boost::format(_utf8(L("Mismatched type of print host: %s"))) % (text ? *text : "AstroBox")).str());
|
||||
}
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
res = false;
|
||||
msg = "Could not parse server response";
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
wxString AstroBox::get_test_ok_msg () const
|
||||
{
|
||||
return _(L("Connection to AstroBox works correctly."));
|
||||
}
|
||||
|
||||
wxString AstroBox::get_test_failed_msg (wxString &msg) const
|
||||
{
|
||||
return GUI::from_u8((boost::format("%s: %s\n\n%s")
|
||||
% _utf8(L("Could not connect to AstroBox"))
|
||||
% std::string(msg.ToUTF8())
|
||||
% _utf8(L("Note: AstroBox version at least 1.1.0 is required."))).str());
|
||||
}
|
||||
|
||||
bool AstroBox::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
|
||||
{
|
||||
const char *name = get_name();
|
||||
|
||||
const auto upload_filename = upload_data.upload_path.filename();
|
||||
const auto upload_parent_path = upload_data.upload_path.parent_path();
|
||||
|
||||
wxString test_msg;
|
||||
if (! test(test_msg)) {
|
||||
error_fn(std::move(test_msg));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = true;
|
||||
|
||||
auto url = make_url("api/files/local");
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%")
|
||||
% name
|
||||
% upload_data.source_path
|
||||
% url
|
||||
% upload_filename.string()
|
||||
% upload_parent_path.string()
|
||||
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false");
|
||||
|
||||
auto http = Http::post(std::move(url));
|
||||
set_auth(http);
|
||||
http.form_add("print", upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
||||
.form_add("path", upload_parent_path.string()) // XXX: slashes on windows ???
|
||||
.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
||||
.on_complete([&](std::string body, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
||||
})
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
error_fn(format_error(body, error, status));
|
||||
res = false;
|
||||
})
|
||||
.on_progress([&](Http::Progress progress, bool &cancel) {
|
||||
prorgess_fn(std::move(progress), cancel);
|
||||
if (cancel) {
|
||||
// Upload was canceled
|
||||
BOOST_LOG_TRIVIAL(info) << "AstroBox: Upload canceled";
|
||||
res = false;
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool AstroBox::validate_version_text(const boost::optional<std::string> &version_text) const
|
||||
{
|
||||
return version_text ? boost::starts_with(*version_text, "AstroBox") : true;
|
||||
}
|
||||
|
||||
void AstroBox::set_auth(Http &http) const
|
||||
{
|
||||
http.header("X-Api-Key", apikey);
|
||||
|
||||
if (! cafile.empty()) {
|
||||
http.ca_file(cafile);
|
||||
}
|
||||
}
|
||||
|
||||
std::string AstroBox::make_url(const std::string &path) const
|
||||
{
|
||||
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||
if (host.back() == '/') {
|
||||
return (boost::format("%1%%2%") % host % path).str();
|
||||
} else {
|
||||
return (boost::format("%1%/%2%") % host % path).str();
|
||||
}
|
||||
} else {
|
||||
return (boost::format("http://%1%/%2%") % host % path).str();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
46
src/slic3r/Utils/AstroBox.hpp
Normal file
46
src/slic3r/Utils/AstroBox.hpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef slic3r_AstroBox_hpp_
|
||||
#define slic3r_AstroBox_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "PrintHost.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
class Http;
|
||||
|
||||
class AstroBox : public PrintHost
|
||||
{
|
||||
public:
|
||||
AstroBox(DynamicPrintConfig *config);
|
||||
~AstroBox() override = default;
|
||||
|
||||
const char* get_name() const override;
|
||||
|
||||
bool test(wxString &curl_msg) const override;
|
||||
wxString get_test_ok_msg () const override;
|
||||
wxString get_test_failed_msg (wxString &msg) const override;
|
||||
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override;
|
||||
bool has_auto_discovery() const override { return true; }
|
||||
bool can_test() const override { return true; }
|
||||
PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; }
|
||||
std::string get_host() const override { return host; }
|
||||
|
||||
protected:
|
||||
bool validate_version_text(const boost::optional<std::string> &version_text) const;
|
||||
|
||||
private:
|
||||
std::string host;
|
||||
std::string apikey;
|
||||
std::string cafile;
|
||||
|
||||
void set_auth(Http &http) const;
|
||||
std::string make_url(const std::string &path) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
286
src/slic3r/Utils/Duet.cpp
Normal file
286
src/slic3r/Utils/Duet.cpp
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
#include "Duet.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
|
||||
#include <wx/frame.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
#include "Http.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
Duet::Duet(DynamicPrintConfig *config) :
|
||||
host(config->opt_string("print_host")),
|
||||
password(config->opt_string("printhost_apikey"))
|
||||
{}
|
||||
|
||||
const char* Duet::get_name() const { return "Duet"; }
|
||||
|
||||
bool Duet::test(wxString &msg) const
|
||||
{
|
||||
auto connectionType = connect(msg);
|
||||
disconnect(connectionType);
|
||||
|
||||
return connectionType != ConnectionType::error;
|
||||
}
|
||||
|
||||
wxString Duet::get_test_ok_msg () const
|
||||
{
|
||||
return _(L("Connection to Duet works correctly."));
|
||||
}
|
||||
|
||||
wxString Duet::get_test_failed_msg (wxString &msg) const
|
||||
{
|
||||
return GUI::from_u8((boost::format("%s: %s")
|
||||
% _utf8(L("Could not connect to Duet"))
|
||||
% std::string(msg.ToUTF8())).str());
|
||||
}
|
||||
|
||||
bool Duet::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
|
||||
{
|
||||
wxString connect_msg;
|
||||
auto connectionType = connect(connect_msg);
|
||||
if (connectionType == ConnectionType::error) {
|
||||
error_fn(std::move(connect_msg));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = true;
|
||||
bool dsf = (connectionType == ConnectionType::dsf);
|
||||
|
||||
auto upload_cmd = get_upload_url(upload_data.upload_path.string(), connectionType);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("Duet: Uploading file %1%, filepath: %2%, post_action: %3%, command: %4%")
|
||||
% upload_data.source_path
|
||||
% upload_data.upload_path
|
||||
% int(upload_data.post_action)
|
||||
% upload_cmd;
|
||||
|
||||
auto http = (dsf ? Http::put(std::move(upload_cmd)) : Http::post(std::move(upload_cmd)));
|
||||
if (dsf) {
|
||||
http.set_put_body(upload_data.source_path);
|
||||
} else {
|
||||
http.set_post_body(upload_data.source_path);
|
||||
}
|
||||
http.on_complete([&](std::string body, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Duet: File uploaded: HTTP %1%: %2%") % status % body;
|
||||
|
||||
int err_code = dsf ? (status == 201 ? 0 : 1) : get_err_code_from_body(body);
|
||||
if (err_code != 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Request completed but error code was received: %1%") % err_code;
|
||||
error_fn(format_error(body, L("Unknown error occured"), 0));
|
||||
res = false;
|
||||
} else if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
|
||||
wxString errormsg;
|
||||
res = start_print(errormsg, upload_data.upload_path.string(), connectionType, false);
|
||||
if (! res) {
|
||||
error_fn(std::move(errormsg));
|
||||
}
|
||||
} else if (upload_data.post_action == PrintHostPostUploadAction::StartSimulation) {
|
||||
wxString errormsg;
|
||||
res = start_print(errormsg, upload_data.upload_path.string(), connectionType, true);
|
||||
if (! res) {
|
||||
error_fn(std::move(errormsg));
|
||||
}
|
||||
}
|
||||
})
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body;
|
||||
error_fn(format_error(body, error, status));
|
||||
res = false;
|
||||
})
|
||||
.on_progress([&](Http::Progress progress, bool &cancel) {
|
||||
prorgess_fn(std::move(progress), cancel);
|
||||
if (cancel) {
|
||||
// Upload was canceled
|
||||
BOOST_LOG_TRIVIAL(info) << "Duet: Upload canceled";
|
||||
res = false;
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
disconnect(connectionType);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Duet::ConnectionType Duet::connect(wxString &msg) const
|
||||
{
|
||||
auto res = ConnectionType::error;
|
||||
auto url = get_connect_url(false);
|
||||
|
||||
auto http = Http::get(std::move(url));
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
auto dsfUrl = get_connect_url(true);
|
||||
auto dsfHttp = Http::get(std::move(dsfUrl));
|
||||
dsfHttp.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error connecting: %1%, HTTP %2%, body: `%3%`") % error % status % body;
|
||||
msg = format_error(body, error, status);
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned) {
|
||||
res = ConnectionType::dsf;
|
||||
})
|
||||
.perform_sync();
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Duet: Got: %1%") % body;
|
||||
|
||||
int err_code = get_err_code_from_body(body);
|
||||
switch (err_code) {
|
||||
case 0:
|
||||
res = ConnectionType::rrf;
|
||||
break;
|
||||
case 1:
|
||||
msg = format_error(body, L("Wrong password"), 0);
|
||||
break;
|
||||
case 2:
|
||||
msg = format_error(body, L("Could not get resources to create a new connection"), 0);
|
||||
break;
|
||||
default:
|
||||
msg = format_error(body, L("Unknown error occured"), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Duet::disconnect(ConnectionType connectionType) const
|
||||
{
|
||||
// we don't need to disconnect from DSF or if it failed anyway
|
||||
if (connectionType != ConnectionType::rrf) {
|
||||
return;
|
||||
}
|
||||
auto url = (boost::format("%1%rr_disconnect")
|
||||
% get_base_url()).str();
|
||||
|
||||
auto http = Http::get(std::move(url));
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
// we don't care about it, if disconnect is not working Duet will disconnect automatically after some time
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error disconnecting: %1%, HTTP %2%, body: `%3%`") % error % status % body;
|
||||
})
|
||||
.perform_sync();
|
||||
}
|
||||
|
||||
std::string Duet::get_upload_url(const std::string &filename, ConnectionType connectionType) const
|
||||
{
|
||||
assert(connectionType != ConnectionType::error);
|
||||
|
||||
if (connectionType == ConnectionType::dsf) {
|
||||
return (boost::format("%1%machine/file/gcodes/%2%")
|
||||
% get_base_url()
|
||||
% Http::url_encode(filename)).str();
|
||||
} else {
|
||||
return (boost::format("%1%rr_upload?name=0:/gcodes/%2%&%3%")
|
||||
% get_base_url()
|
||||
% Http::url_encode(filename)
|
||||
% timestamp_str()).str();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Duet::get_connect_url(const bool dsfUrl) const
|
||||
{
|
||||
if (dsfUrl) {
|
||||
return (boost::format("%1%machine/status")
|
||||
% get_base_url()).str();
|
||||
} else {
|
||||
return (boost::format("%1%rr_connect?password=%2%&%3%")
|
||||
% get_base_url()
|
||||
% (password.empty() ? "reprap" : password)
|
||||
% timestamp_str()).str();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Duet::get_base_url() const
|
||||
{
|
||||
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||
if (host.back() == '/') {
|
||||
return host;
|
||||
} else {
|
||||
return (boost::format("%1%/") % host).str();
|
||||
}
|
||||
} else {
|
||||
return (boost::format("http://%1%/") % host).str();
|
||||
}
|
||||
}
|
||||
|
||||
std::string Duet::timestamp_str() const
|
||||
{
|
||||
enum { BUFFER_SIZE = 32 };
|
||||
|
||||
auto t = std::time(nullptr);
|
||||
auto tm = *std::localtime(&t);
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
std::strftime(buffer, BUFFER_SIZE, "time=%Y-%m-%dT%H:%M:%S", &tm);
|
||||
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
bool Duet::start_print(wxString &msg, const std::string &filename, ConnectionType connectionType, bool simulationMode) const
|
||||
{
|
||||
assert(connectionType != ConnectionType::error);
|
||||
|
||||
bool res = false;
|
||||
bool dsf = (connectionType == ConnectionType::dsf);
|
||||
|
||||
auto url = dsf
|
||||
? (boost::format("%1%machine/code")
|
||||
% get_base_url()).str()
|
||||
: (boost::format(simulationMode
|
||||
? "%1%rr_gcode?gcode=M37%%20P\"0:/gcodes/%2%\""
|
||||
: "%1%rr_gcode?gcode=M32%%20\"0:/gcodes/%2%\"")
|
||||
% get_base_url()
|
||||
% Http::url_encode(filename)).str();
|
||||
|
||||
auto http = (dsf ? Http::post(std::move(url)) : Http::get(std::move(url)));
|
||||
if (dsf) {
|
||||
http.set_post_body(
|
||||
(boost::format(simulationMode
|
||||
? "M37 P\"0:/gcodes/%1%\""
|
||||
: "M32 \"0:/gcodes/%1%\"")
|
||||
% filename).str()
|
||||
);
|
||||
}
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Duet: Error starting print: %1%, HTTP %2%, body: `%3%`") % error % status % body;
|
||||
msg = format_error(body, error, status);
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("Duet: Got: %1%") % body;
|
||||
res = true;
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int Duet::get_err_code_from_body(const std::string &body) const
|
||||
{
|
||||
pt::ptree root;
|
||||
std::istringstream iss (body); // wrap returned json to istringstream
|
||||
pt::read_json(iss, root);
|
||||
|
||||
return root.get<int>("err", 0);
|
||||
}
|
||||
|
||||
}
|
||||
48
src/slic3r/Utils/Duet.hpp
Normal file
48
src/slic3r/Utils/Duet.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef slic3r_Duet_hpp_
|
||||
#define slic3r_Duet_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "PrintHost.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
class Http;
|
||||
|
||||
class Duet : public PrintHost
|
||||
{
|
||||
public:
|
||||
explicit Duet(DynamicPrintConfig *config);
|
||||
~Duet() override = default;
|
||||
|
||||
const char* get_name() const override;
|
||||
|
||||
bool test(wxString &curl_msg) const override;
|
||||
wxString get_test_ok_msg() const override;
|
||||
wxString get_test_failed_msg(wxString &msg) const override;
|
||||
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override;
|
||||
bool has_auto_discovery() const override { return false; }
|
||||
bool can_test() const override { return true; }
|
||||
PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint | PrintHostPostUploadAction::StartSimulation; }
|
||||
std::string get_host() const override { return host; }
|
||||
|
||||
private:
|
||||
enum class ConnectionType { rrf, dsf, error };
|
||||
std::string host;
|
||||
std::string password;
|
||||
|
||||
std::string get_upload_url(const std::string &filename, ConnectionType connectionType) const;
|
||||
std::string get_connect_url(const bool dsfUrl) const;
|
||||
std::string get_base_url() const;
|
||||
std::string timestamp_str() const;
|
||||
ConnectionType connect(wxString &msg) const;
|
||||
void disconnect(ConnectionType connectionType) const;
|
||||
bool start_print(wxString &msg, const std::string &filename, ConnectionType connectionType, bool simulationMode) const;
|
||||
int get_err_code_from_body(const std::string &body) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
229
src/slic3r/Utils/FlashAir.cpp
Normal file
229
src/slic3r/Utils/FlashAir.cpp
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
#include "FlashAir.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <wx/frame.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
#include "Http.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
FlashAir::FlashAir(DynamicPrintConfig *config) :
|
||||
host(config->opt_string("print_host"))
|
||||
{}
|
||||
|
||||
const char* FlashAir::get_name() const { return "FlashAir"; }
|
||||
|
||||
bool FlashAir::test(wxString &msg) const
|
||||
{
|
||||
// Since the request is performed synchronously here,
|
||||
// it is ok to refer to `msg` from within the closure
|
||||
|
||||
const char *name = get_name();
|
||||
|
||||
bool res = false;
|
||||
auto url = make_url("command.cgi", "op", "118");
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get upload enabled at: %2%") % name % url;
|
||||
|
||||
auto http = Http::get(std::move(url));
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting upload enabled: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
res = false;
|
||||
msg = format_error(body, error, status);
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got upload enabled: %2%") % name % body;
|
||||
|
||||
res = boost::starts_with(body, "1");
|
||||
if (! res) {
|
||||
msg = _(L("Upload not enabled on FlashAir card."));
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
wxString FlashAir::get_test_ok_msg () const
|
||||
{
|
||||
return _(L("Connection to FlashAir works correctly and upload is enabled."));
|
||||
}
|
||||
|
||||
wxString FlashAir::get_test_failed_msg (wxString &msg) const
|
||||
{
|
||||
return GUI::from_u8((boost::format("%s: %s\n%s")
|
||||
% _utf8(L("Could not connect to FlashAir"))
|
||||
% std::string(msg.ToUTF8())
|
||||
% _utf8(L("Note: FlashAir with firmware 2.00.02 or newer and activated upload function is required."))).str());
|
||||
}
|
||||
|
||||
bool FlashAir::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
|
||||
{
|
||||
const char *name = get_name();
|
||||
|
||||
const auto upload_filename = upload_data.upload_path.filename();
|
||||
const auto upload_parent_path = upload_data.upload_path.parent_path();
|
||||
wxString test_msg;
|
||||
if (! test(test_msg)) {
|
||||
error_fn(std::move(test_msg));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = false;
|
||||
|
||||
std::string strDest = upload_parent_path.string();
|
||||
if (strDest.front()!='/') // Needs a leading / else root uploads fail.
|
||||
{
|
||||
strDest.insert(0,"/");
|
||||
}
|
||||
|
||||
auto urlPrepare = make_url("upload.cgi", "WRITEPROTECT=ON&FTIME", timestamp_str());
|
||||
auto urlSetDir = make_url("upload.cgi","UPDIR",strDest);
|
||||
auto urlUpload = make_url("upload.cgi");
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3% / %4%, filename: %5%")
|
||||
% name
|
||||
% upload_data.source_path
|
||||
% urlPrepare
|
||||
% urlUpload
|
||||
% upload_filename.string();
|
||||
|
||||
// set filetime for upload and make card writeprotect to prevent filesystem damage
|
||||
auto httpPrepare = Http::get(std::move(urlPrepare));
|
||||
httpPrepare.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error preparing upload: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
error_fn(format_error(body, error, status));
|
||||
res = false;
|
||||
})
|
||||
.on_complete([&, this](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got prepare result: %2%") % name % body;
|
||||
res = boost::icontains(body, "SUCCESS");
|
||||
if (! res) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name;
|
||||
error_fn(format_error(body, L("Unknown error occured"), 0));
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
if(! res ) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// start file upload
|
||||
auto httpDir = Http::get(std::move(urlSetDir));
|
||||
httpDir.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error setting upload dir: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
error_fn(format_error(body, error, status));
|
||||
res = false;
|
||||
})
|
||||
.on_complete([&, this](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got dir select result: %2%") % name % body;
|
||||
res = boost::icontains(body, "SUCCESS");
|
||||
if (! res) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name;
|
||||
error_fn(format_error(body, L("Unknown error occured"), 0));
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
if(! res ) {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto http = Http::post(std::move(urlUpload));
|
||||
http.form_add_file("file", upload_data.source_path.string(), upload_filename.string())
|
||||
.on_complete([&](std::string body, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
||||
res = boost::icontains(body, "SUCCESS");
|
||||
if (! res) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Request completed but no SUCCESS message was received.") % name;
|
||||
error_fn(format_error(body, L("Unknown error occured"), 0));
|
||||
}
|
||||
})
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
error_fn(format_error(body, error, status));
|
||||
res = false;
|
||||
})
|
||||
.on_progress([&](Http::Progress progress, bool &cancel) {
|
||||
prorgess_fn(std::move(progress), cancel);
|
||||
if (cancel) {
|
||||
// Upload was canceled
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Upload canceled") % name;
|
||||
res = false;
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string FlashAir::timestamp_str() const
|
||||
{
|
||||
auto t = std::time(nullptr);
|
||||
auto tm = *std::localtime(&t);
|
||||
|
||||
unsigned long fattime = ((tm.tm_year - 80) << 25) |
|
||||
((tm.tm_mon + 1) << 21) |
|
||||
(tm.tm_mday << 16) |
|
||||
(tm.tm_hour << 11) |
|
||||
(tm.tm_min << 5) |
|
||||
(tm.tm_sec >> 1);
|
||||
|
||||
return (boost::format("%1$#x") % fattime).str();
|
||||
}
|
||||
|
||||
std::string FlashAir::make_url(const std::string &path) const
|
||||
{
|
||||
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||
if (host.back() == '/') {
|
||||
return (boost::format("%1%%2%") % host % path).str();
|
||||
} else {
|
||||
return (boost::format("%1%/%2%") % host % path).str();
|
||||
}
|
||||
} else {
|
||||
if (host.back() == '/') {
|
||||
return (boost::format("http://%1%%2%") % host % path).str();
|
||||
} else {
|
||||
return (boost::format("http://%1%/%2%") % host % path).str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string FlashAir::make_url(const std::string &path, const std::string &arg, const std::string &val) const
|
||||
{
|
||||
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||
if (host.back() == '/') {
|
||||
return (boost::format("%1%%2%?%3%=%4%") % host % path % arg % val).str();
|
||||
} else {
|
||||
return (boost::format("%1%/%2%?%3%=%4%") % host % path % arg % val).str();
|
||||
}
|
||||
} else {
|
||||
if (host.back() == '/') {
|
||||
return (boost::format("http://%1%%2%?%3%=%4%") % host % path % arg % val).str();
|
||||
} else {
|
||||
return (boost::format("http://%1%/%2%?%3%=%4%") % host % path % arg % val).str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
42
src/slic3r/Utils/FlashAir.hpp
Normal file
42
src/slic3r/Utils/FlashAir.hpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef slic3r_FlashAir_hpp_
|
||||
#define slic3r_FlashAir_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "PrintHost.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
class Http;
|
||||
|
||||
class FlashAir : public PrintHost
|
||||
{
|
||||
public:
|
||||
FlashAir(DynamicPrintConfig *config);
|
||||
~FlashAir() override = default;
|
||||
|
||||
const char* get_name() const override;
|
||||
|
||||
bool test(wxString &curl_msg) const override;
|
||||
wxString get_test_ok_msg() const override;
|
||||
wxString get_test_failed_msg(wxString &msg) const override;
|
||||
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override;
|
||||
bool has_auto_discovery() const override { return false; }
|
||||
bool can_test() const override { return true; }
|
||||
PrintHostPostUploadActions get_post_upload_actions() const override { return {}; }
|
||||
std::string get_host() const override { return host; }
|
||||
|
||||
private:
|
||||
std::string host;
|
||||
|
||||
std::string timestamp_str() const;
|
||||
std::string make_url(const std::string &path) const;
|
||||
std::string make_url(const std::string &path, const std::string &arg, const std::string &val) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
150
src/slic3r/Utils/MKS.cpp
Normal file
150
src/slic3r/Utils/MKS.cpp
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
#include "MKS.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <wx/frame.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
#include "Http.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
MKS::MKS(DynamicPrintConfig* config) :
|
||||
m_host(config->opt_string("print_host")), m_console_port("8080")
|
||||
{}
|
||||
|
||||
const char* MKS::get_name() const { return "MKS"; }
|
||||
|
||||
bool MKS::test(wxString& msg) const
|
||||
{
|
||||
Utils::TCPConsole console(m_host, m_console_port);
|
||||
|
||||
console.enqueue_cmd("M105");
|
||||
bool ret = console.run_queue();
|
||||
|
||||
if (!ret)
|
||||
msg = wxString::FromUTF8(console.error_message().c_str());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxString MKS::get_test_ok_msg() const
|
||||
{
|
||||
return _(L("Connection to MKS works correctly."));
|
||||
}
|
||||
|
||||
wxString MKS::get_test_failed_msg(wxString& msg) const
|
||||
{
|
||||
return GUI::from_u8((boost::format("%s: %s")
|
||||
% _utf8(L("Could not connect to MKS"))
|
||||
% std::string(msg.ToUTF8())).str());
|
||||
}
|
||||
|
||||
bool MKS::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
|
||||
{
|
||||
bool res = true;
|
||||
|
||||
auto upload_cmd = get_upload_url(upload_data.upload_path.string());
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("MKS: Uploading file %1%, filepath: %2%, print: %3%, command: %4%")
|
||||
% upload_data.source_path
|
||||
% upload_data.upload_path
|
||||
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint)
|
||||
% upload_cmd;
|
||||
|
||||
auto http = Http::post(std::move(upload_cmd));
|
||||
http.set_post_body(upload_data.source_path);
|
||||
|
||||
http.on_complete([&](std::string body, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("MKS: File uploaded: HTTP %1%: %2%") % status % body;
|
||||
|
||||
int err_code = get_err_code_from_body(body);
|
||||
if (err_code != 0) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("MKS: Request completed but error code was received: %1%") % err_code;
|
||||
error_fn(format_error(body, L("Unknown error occured"), 0));
|
||||
res = false;
|
||||
}
|
||||
else if (upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
|
||||
wxString errormsg;
|
||||
res = start_print(errormsg, upload_data.upload_path.string());
|
||||
if (!res) {
|
||||
error_fn(std::move(errormsg));
|
||||
}
|
||||
}
|
||||
})
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("MKS: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body;
|
||||
error_fn(format_error(body, error, status));
|
||||
res = false;
|
||||
})
|
||||
.on_progress([&](Http::Progress progress, bool& cancel) {
|
||||
prorgess_fn(std::move(progress), cancel);
|
||||
if (cancel) {
|
||||
// Upload was canceled
|
||||
BOOST_LOG_TRIVIAL(info) << "MKS: Upload canceled";
|
||||
res = false;
|
||||
}
|
||||
}).perform_sync();
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string MKS::get_upload_url(const std::string& filename) const
|
||||
{
|
||||
return (boost::format("http://%1%/upload?X-Filename=%2%")
|
||||
% m_host
|
||||
% Http::url_encode(filename)).str();
|
||||
}
|
||||
|
||||
bool MKS::start_print(wxString& msg, const std::string& filename) const
|
||||
{
|
||||
// For some reason printer firmware does not want to respond on gcode commands immediately after file upload.
|
||||
// So we just introduce artificial delay to workaround it.
|
||||
// TODO: Inspect reasons
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
|
||||
|
||||
Utils::TCPConsole console(m_host, m_console_port);
|
||||
|
||||
console.enqueue_cmd(std::string("M23 ") + filename);
|
||||
console.enqueue_cmd("M24");
|
||||
|
||||
bool ret = console.run_queue();
|
||||
|
||||
if (!ret)
|
||||
msg = wxString::FromUTF8(console.error_message().c_str());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int MKS::get_err_code_from_body(const std::string& body) const
|
||||
{
|
||||
pt::ptree root;
|
||||
std::istringstream iss(body); // wrap returned json to istringstream
|
||||
pt::read_json(iss, root);
|
||||
|
||||
return root.get<int>("err", 0);
|
||||
}
|
||||
|
||||
} // Slic3r
|
||||
42
src/slic3r/Utils/MKS.hpp
Normal file
42
src/slic3r/Utils/MKS.hpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef slic3r_MKS_hpp_
|
||||
#define slic3r_MKS_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
|
||||
#include "PrintHost.hpp"
|
||||
#include "TCPConsole.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
class DynamicPrintConfig;
|
||||
class Http;
|
||||
|
||||
class MKS : public PrintHost
|
||||
{
|
||||
public:
|
||||
explicit MKS(DynamicPrintConfig* config);
|
||||
~MKS() override = default;
|
||||
|
||||
const char* get_name() const override;
|
||||
|
||||
bool test(wxString& curl_msg) const override;
|
||||
wxString get_test_ok_msg() const override;
|
||||
wxString get_test_failed_msg(wxString& msg) const override;
|
||||
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override;
|
||||
bool has_auto_discovery() const override { return false; }
|
||||
bool can_test() const override { return true; }
|
||||
PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; }
|
||||
std::string get_host() const override { return m_host; }
|
||||
|
||||
private:
|
||||
std::string m_host;
|
||||
std::string m_console_port;
|
||||
|
||||
std::string get_upload_url(const std::string& filename) const;
|
||||
bool start_print(wxString& msg, const std::string& filename) const;
|
||||
int get_err_code_from_body(const std::string& body) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -14,11 +14,11 @@
|
|||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/Channel.hpp"
|
||||
#include "OctoPrint.hpp"
|
||||
//#include "Duet.hpp"
|
||||
//#include "FlashAir.hpp"
|
||||
//#include "AstroBox.hpp"
|
||||
//#include "Repetier.hpp"
|
||||
//#include "MKS.hpp"
|
||||
#include "Duet.hpp"
|
||||
#include "FlashAir.hpp"
|
||||
#include "AstroBox.hpp"
|
||||
#include "Repetier.hpp"
|
||||
#include "MKS.hpp"
|
||||
#include "../GUI/PrintHostDialogs.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
|
@ -47,12 +47,12 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config)
|
|||
|
||||
switch (host_type) {
|
||||
case htOctoPrint: return new OctoPrint(config);
|
||||
//case htDuet: return new Duet(config);
|
||||
//case htFlashAir: return new FlashAir(config);
|
||||
//case htAstroBox: return new AstroBox(config);
|
||||
//case htRepetier: return new Repetier(config);
|
||||
case htDuet: return new Duet(config);
|
||||
case htFlashAir: return new FlashAir(config);
|
||||
case htAstroBox: return new AstroBox(config);
|
||||
case htRepetier: return new Repetier(config);
|
||||
case htPrusaLink: return new PrusaLink(config);
|
||||
//case htMKS: return new MKS(config);
|
||||
case htMKS: return new MKS(config);
|
||||
default: return nullptr;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
274
src/slic3r/Utils/Repetier.cpp
Normal file
274
src/slic3r/Utils/Repetier.cpp
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
#include "Repetier.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include <wx/progdlg.h>
|
||||
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/format.hpp"
|
||||
#include "Http.hpp"
|
||||
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace pt = boost::property_tree;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
Repetier::Repetier(DynamicPrintConfig *config) :
|
||||
host(config->opt_string("print_host")),
|
||||
apikey(config->opt_string("printhost_apikey")),
|
||||
cafile(config->opt_string("printhost_cafile")),
|
||||
port(config->opt_string("printhost_port"))
|
||||
{}
|
||||
|
||||
const char* Repetier::get_name() const { return "Repetier"; }
|
||||
|
||||
bool Repetier::test(wxString &msg) const
|
||||
{
|
||||
// Since the request is performed synchronously here,
|
||||
// it is ok to refer to `msg` from within the closure
|
||||
|
||||
const char *name = get_name();
|
||||
|
||||
bool res = true;
|
||||
auto url = make_url("printer/info");
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: List version at: %2%") % name % url;
|
||||
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
res = false;
|
||||
msg = format_error(body, error, status);
|
||||
})
|
||||
.on_complete([&, this](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got version: %2%") % name % body;
|
||||
|
||||
try {
|
||||
std::stringstream ss(body);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
|
||||
const auto text = ptree.get_optional<std::string>("name");
|
||||
res = validate_version_text(text);
|
||||
if (! res) {
|
||||
msg = GUI::from_u8((boost::format(_utf8(L("Mismatched type of print host: %s"))) % (text ? *text : "Repetier")).str());
|
||||
}
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
res = false;
|
||||
msg = "Could not parse server response";
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
wxString Repetier::get_test_ok_msg () const
|
||||
{
|
||||
return _(L("Connection to Repetier works correctly."));
|
||||
}
|
||||
|
||||
wxString Repetier::get_test_failed_msg (wxString &msg) const
|
||||
{
|
||||
return GUI::from_u8((boost::format("%s: %s\n\n%s")
|
||||
% _utf8(L("Could not connect to Repetier"))
|
||||
% std::string(msg.ToUTF8())
|
||||
% _utf8(L("Note: Repetier version at least 0.90.0 is required."))).str());
|
||||
}
|
||||
|
||||
bool Repetier::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
|
||||
{
|
||||
const char *name = get_name();
|
||||
|
||||
const auto upload_filename = upload_data.upload_path.filename();
|
||||
const auto upload_parent_path = upload_data.upload_path.parent_path();
|
||||
|
||||
wxString test_msg;
|
||||
if (! test(test_msg)) {
|
||||
error_fn(std::move(test_msg));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool res = true;
|
||||
|
||||
auto url = upload_data.post_action == PrintHostPostUploadAction::StartPrint
|
||||
? make_url((boost::format("printer/job/%1%") % port).str())
|
||||
: make_url((boost::format("printer/model/%1%") % port).str());
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Uploading file %2% at %3%, filename: %4%, path: %5%, print: %6%, group: %7%")
|
||||
% name
|
||||
% upload_data.source_path
|
||||
% url
|
||||
% upload_filename.string()
|
||||
% upload_parent_path.string()
|
||||
% (upload_data.post_action == PrintHostPostUploadAction::StartPrint ? "true" : "false")
|
||||
% upload_data.group;
|
||||
|
||||
auto http = Http::post(std::move(url));
|
||||
set_auth(http);
|
||||
|
||||
if (! upload_data.group.empty() && upload_data.group != _utf8(L("Default"))) {
|
||||
http.form_add("group", upload_data.group);
|
||||
}
|
||||
|
||||
if(upload_data.post_action == PrintHostPostUploadAction::StartPrint) {
|
||||
http.form_add("name", upload_filename.string());
|
||||
}
|
||||
|
||||
http.form_add("a", "upload")
|
||||
.form_add_file("filename", upload_data.source_path.string(), upload_filename.string())
|
||||
.on_complete([&](std::string body, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: File uploaded: HTTP %2%: %3%") % name % status % body;
|
||||
})
|
||||
.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error uploading file: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
error_fn(format_error(body, error, status));
|
||||
res = false;
|
||||
})
|
||||
.on_progress([&](Http::Progress progress, bool &cancel) {
|
||||
prorgess_fn(std::move(progress), cancel);
|
||||
if (cancel) {
|
||||
// Upload was canceled
|
||||
BOOST_LOG_TRIVIAL(info) << "Repetier: Upload canceled";
|
||||
res = false;
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Repetier::validate_version_text(const boost::optional<std::string> &version_text) const
|
||||
{
|
||||
return version_text ? boost::starts_with(*version_text, "Repetier") : true;
|
||||
}
|
||||
|
||||
void Repetier::set_auth(Http &http) const
|
||||
{
|
||||
http.header("X-Api-Key", apikey);
|
||||
|
||||
if (! cafile.empty()) {
|
||||
http.ca_file(cafile);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Repetier::make_url(const std::string &path) const
|
||||
{
|
||||
if (host.find("http://") == 0 || host.find("https://") == 0) {
|
||||
if (host.back() == '/') {
|
||||
return (boost::format("%1%%2%") % host % path).str();
|
||||
} else {
|
||||
return (boost::format("%1%/%2%") % host % path).str();
|
||||
}
|
||||
} else {
|
||||
return (boost::format("http://%1%/%2%") % host % path).str();
|
||||
}
|
||||
}
|
||||
|
||||
bool Repetier::get_groups(wxArrayString& groups) const
|
||||
{
|
||||
bool res = true;
|
||||
|
||||
const char *name = get_name();
|
||||
auto url = make_url((boost::format("printer/api/%1%") % port).str());
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get groups at: %2%") % name % url;
|
||||
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
http.form_add("a", "listModelGroups");
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting version: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got groups: %2%") % name % body;
|
||||
|
||||
try {
|
||||
std::stringstream ss(body);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
|
||||
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, ptree.get_child("groupNames.")) {
|
||||
if (v.second.data() == "#") {
|
||||
groups.push_back(_utf8(L("Default")));
|
||||
} else {
|
||||
// Is it safe to assume that the data are utf-8 encoded?
|
||||
groups.push_back(GUI::from_u8(v.second.data()));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception &) {
|
||||
//msg = "Could not parse server response";
|
||||
res = false;
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool Repetier::get_printers(wxArrayString& printers) const
|
||||
{
|
||||
const char *name = get_name();
|
||||
|
||||
bool res = true;
|
||||
auto url = make_url("printer/list");
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("%1%: List printers at: %2%") % name % url;
|
||||
|
||||
auto http = Http::get(std::move(url));
|
||||
set_auth(http);
|
||||
|
||||
http.on_error([&](std::string body, std::string error, unsigned status) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error listing printers: %2%, HTTP %3%, body: `%4%`") % name % error % status % body;
|
||||
res = false;
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned http_status) {
|
||||
BOOST_LOG_TRIVIAL(debug) << boost::format("%1%: Got printers: %2%, HTTP status: %3%") % name % body % http_status;
|
||||
|
||||
if (http_status != 200)
|
||||
throw HostNetworkError(GUI::format(_L("HTTP status: %1%\nMessage body: \"%2%\""), http_status, body));
|
||||
|
||||
std::stringstream ss(body);
|
||||
pt::ptree ptree;
|
||||
try {
|
||||
pt::read_json(ss, ptree);
|
||||
} catch (const pt::ptree_error &err) {
|
||||
throw HostNetworkError(GUI::format(_L("Parsing of host response failed.\nMessage body: \"%1%\"\nError: \"%2%\""), body, err.what()));
|
||||
}
|
||||
|
||||
const auto error = ptree.get_optional<std::string>("error");
|
||||
if (error)
|
||||
throw HostNetworkError(*error);
|
||||
|
||||
try {
|
||||
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, ptree.get_child("data.")) {
|
||||
const auto port = v.second.get<std::string>("slug");
|
||||
printers.push_back(Slic3r::GUI::from_u8(port));
|
||||
}
|
||||
} catch (const std::exception &err) {
|
||||
throw HostNetworkError(GUI::format(_L("Enumeration of host printers failed.\nMessage body: \"%1%\"\nError: \"%2%\""), body, err.what()));
|
||||
}
|
||||
})
|
||||
.perform_sync();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
51
src/slic3r/Utils/Repetier.hpp
Normal file
51
src/slic3r/Utils/Repetier.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef slic3r_Repetier_hpp_
|
||||
#define slic3r_Repetier_hpp_
|
||||
|
||||
#include <string>
|
||||
#include <wx/string.h>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "PrintHost.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class DynamicPrintConfig;
|
||||
class Http;
|
||||
|
||||
class Repetier : public PrintHost
|
||||
{
|
||||
public:
|
||||
Repetier(DynamicPrintConfig *config);
|
||||
~Repetier() override = default;
|
||||
|
||||
const char* get_name() const override;
|
||||
|
||||
bool test(wxString &curl_msg) const override;
|
||||
wxString get_test_ok_msg () const override;
|
||||
wxString get_test_failed_msg (wxString &msg) const override;
|
||||
bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const override;
|
||||
bool has_auto_discovery() const override { return false; }
|
||||
bool can_test() const override { return true; }
|
||||
PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; }
|
||||
bool supports_multiple_printers() const override { return true; }
|
||||
std::string get_host() const override { return host; }
|
||||
|
||||
bool get_groups(wxArrayString &groups) const override;
|
||||
bool get_printers(wxArrayString &printers) const override;
|
||||
|
||||
protected:
|
||||
virtual bool validate_version_text(const boost::optional<std::string> &version_text) const;
|
||||
|
||||
private:
|
||||
std::string host;
|
||||
std::string apikey;
|
||||
std::string cafile;
|
||||
std::string port;
|
||||
|
||||
void set_auth(Http &http) const;
|
||||
std::string make_url(const std::string &path) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
504
src/slic3r/Utils/Serial.cpp
Normal file
504
src/slic3r/Utils/Serial.cpp
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
#include "Serial.hpp"
|
||||
|
||||
#include "libslic3r/Exception.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#if _WIN32
|
||||
#include <Windows.h>
|
||||
#include <Setupapi.h>
|
||||
#include <initguid.h>
|
||||
#include <devguid.h>
|
||||
#include <regex>
|
||||
// Undefine min/max macros incompatible with the standard library
|
||||
// For example, std::numeric_limits<std::streamsize>::max()
|
||||
// produces some weird errors
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#include "boost/nowide/convert.hpp"
|
||||
#pragma comment(lib, "user32.lib")
|
||||
#elif __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreFoundation/CFString.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/serial/IOSerialKeys.h>
|
||||
#include <IOKit/serial/ioss.h>
|
||||
#include <sys/syslimits.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#include <termios.h>
|
||||
#elif defined __linux__
|
||||
#include <fcntl.h>
|
||||
#include <asm-generic/ioctls.h>
|
||||
#endif
|
||||
|
||||
using boost::optional;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
static bool looks_like_printer(const std::string &friendly_name)
|
||||
{
|
||||
return friendly_name.find("Original Prusa") != std::string::npos;
|
||||
}
|
||||
|
||||
#if _WIN32
|
||||
void parse_hardware_id(const std::string &hardware_id, SerialPortInfo &spi)
|
||||
{
|
||||
unsigned vid, pid;
|
||||
std::regex pattern("USB\\\\.*VID_([[:xdigit:]]+)&PID_([[:xdigit:]]+).*");
|
||||
std::smatch matches;
|
||||
if (std::regex_match(hardware_id, matches, pattern)) {
|
||||
vid = std::stoul(matches[1].str(), 0, 16);
|
||||
pid = std::stoul(matches[2].str(), 0, 16);
|
||||
spi.id_vendor = vid;
|
||||
spi.id_product = pid;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
optional<std::string> sysfs_tty_prop(const std::string &tty_dev, const std::string &name)
|
||||
{
|
||||
const auto prop_path = (boost::format("/sys/class/tty/%1%/device/../%2%") % tty_dev % name).str();
|
||||
std::ifstream file(prop_path);
|
||||
std::string res;
|
||||
|
||||
std::getline(file, res);
|
||||
if (file.good()) { return res; }
|
||||
else { return boost::none; }
|
||||
}
|
||||
|
||||
optional<unsigned long> sysfs_tty_prop_hex(const std::string &tty_dev, const std::string &name)
|
||||
{
|
||||
auto prop = sysfs_tty_prop(tty_dev, name);
|
||||
if (!prop) { return boost::none; }
|
||||
|
||||
try { return std::stoul(*prop, 0, 16); }
|
||||
catch (const std::exception&) { return boost::none; }
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<SerialPortInfo> scan_serial_ports_extended()
|
||||
{
|
||||
std::vector<SerialPortInfo> output;
|
||||
|
||||
#ifdef _WIN32
|
||||
SP_DEVINFO_DATA devInfoData = { 0 };
|
||||
devInfoData.cbSize = sizeof(devInfoData);
|
||||
// Get the tree containing the info for the ports.
|
||||
HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, nullptr, DIGCF_PRESENT);
|
||||
if (hDeviceInfo != INVALID_HANDLE_VALUE) {
|
||||
// Iterate over all the devices in the tree.
|
||||
for (int nDevice = 0; SetupDiEnumDeviceInfo(hDeviceInfo, nDevice, &devInfoData); ++ nDevice) {
|
||||
SerialPortInfo port_info;
|
||||
// Get the registry key which stores the ports settings.
|
||||
HKEY hDeviceKey = SetupDiOpenDevRegKey(hDeviceInfo, &devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
|
||||
if (hDeviceKey) {
|
||||
// Read in the name of the port.
|
||||
wchar_t pszPortName[4096];
|
||||
DWORD dwSize = sizeof(pszPortName);
|
||||
DWORD dwType = 0;
|
||||
if (RegQueryValueEx(hDeviceKey, L"PortName", NULL, &dwType, (LPBYTE)pszPortName, &dwSize) == ERROR_SUCCESS)
|
||||
port_info.port = boost::nowide::narrow(pszPortName);
|
||||
RegCloseKey(hDeviceKey);
|
||||
if (port_info.port.empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the size required to hold the device info.
|
||||
DWORD regDataType;
|
||||
DWORD reqSize = 0;
|
||||
SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, nullptr, nullptr, 0, &reqSize);
|
||||
std::vector<wchar_t> hardware_id(reqSize > 1 ? reqSize : 1);
|
||||
// Now store it in a buffer.
|
||||
if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, (BYTE*)hardware_id.data(), reqSize, nullptr))
|
||||
continue;
|
||||
parse_hardware_id(boost::nowide::narrow(hardware_id.data()), port_info);
|
||||
|
||||
// Find the size required to hold the friendly name.
|
||||
reqSize = 0;
|
||||
SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize);
|
||||
std::vector<wchar_t> friendly_name;
|
||||
friendly_name.reserve(reqSize > 1 ? reqSize : 1);
|
||||
// Now store it in a buffer.
|
||||
if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, (BYTE*)friendly_name.data(), reqSize, nullptr)) {
|
||||
port_info.friendly_name = port_info.port;
|
||||
} else {
|
||||
port_info.friendly_name = boost::nowide::narrow(friendly_name.data());
|
||||
port_info.is_printer = looks_like_printer(port_info.friendly_name);
|
||||
}
|
||||
output.emplace_back(std::move(port_info));
|
||||
}
|
||||
}
|
||||
#elif __APPLE__
|
||||
// inspired by https://sigrok.org/wiki/Libserialport
|
||||
CFMutableDictionaryRef classes = IOServiceMatching(kIOSerialBSDServiceValue);
|
||||
if (classes != 0) {
|
||||
io_iterator_t iter;
|
||||
if (IOServiceGetMatchingServices(kIOMasterPortDefault, classes, &iter) == KERN_SUCCESS) {
|
||||
io_object_t port;
|
||||
while ((port = IOIteratorNext(iter)) != 0) {
|
||||
CFTypeRef cf_property = IORegistryEntryCreateCFProperty(port, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
|
||||
if (cf_property) {
|
||||
char path[PATH_MAX];
|
||||
Boolean result = CFStringGetCString((CFStringRef)cf_property, path, sizeof(path), kCFStringEncodingUTF8);
|
||||
CFRelease(cf_property);
|
||||
if (result) {
|
||||
SerialPortInfo port_info;
|
||||
port_info.port = path;
|
||||
|
||||
// Attempt to read out the device friendly name
|
||||
if ((cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
|
||||
CFSTR("USB Interface Name"), kCFAllocatorDefault,
|
||||
kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
|
||||
(cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
|
||||
CFSTR("USB Product Name"), kCFAllocatorDefault,
|
||||
kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
|
||||
(cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
|
||||
CFSTR("Product Name"), kCFAllocatorDefault,
|
||||
kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
|
||||
(cf_property = IORegistryEntryCreateCFProperty(port,
|
||||
CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0))) {
|
||||
// Description limited to 127 char, anything longer would not be user friendly anyway.
|
||||
char description[128];
|
||||
if (CFStringGetCString((CFStringRef)cf_property, description, sizeof(description), kCFStringEncodingUTF8)) {
|
||||
port_info.friendly_name = std::string(description) + " (" + port_info.port + ")";
|
||||
port_info.is_printer = looks_like_printer(port_info.friendly_name);
|
||||
}
|
||||
CFRelease(cf_property);
|
||||
}
|
||||
if (port_info.friendly_name.empty())
|
||||
port_info.friendly_name = port_info.port;
|
||||
|
||||
// Attempt to read out the VID & PID
|
||||
int vid, pid;
|
||||
auto cf_vendor = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idVendor"),
|
||||
kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
|
||||
auto cf_product = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idProduct"),
|
||||
kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
|
||||
if (cf_vendor && cf_product) {
|
||||
if (CFNumberGetValue((CFNumberRef)cf_vendor, kCFNumberIntType, &vid) &&
|
||||
CFNumberGetValue((CFNumberRef)cf_product, kCFNumberIntType, &pid)) {
|
||||
port_info.id_vendor = vid;
|
||||
port_info.id_product = pid;
|
||||
}
|
||||
}
|
||||
if (cf_vendor) { CFRelease(cf_vendor); }
|
||||
if (cf_product) { CFRelease(cf_product); }
|
||||
|
||||
output.emplace_back(std::move(port_info));
|
||||
}
|
||||
}
|
||||
IOObjectRelease(port);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
// UNIX / Linux
|
||||
std::initializer_list<const char*> prefixes { "ttyUSB" , "ttyACM", "tty.", "cu.", "rfcomm" };
|
||||
for (auto &dir_entry : boost::filesystem::directory_iterator(boost::filesystem::path("/dev"))) {
|
||||
std::string name = dir_entry.path().filename().string();
|
||||
for (const char *prefix : prefixes) {
|
||||
if (boost::starts_with(name, prefix)) {
|
||||
const auto path = dir_entry.path().string();
|
||||
SerialPortInfo spi;
|
||||
spi.port = path;
|
||||
#ifdef __linux__
|
||||
auto friendly_name = sysfs_tty_prop(name, "product");
|
||||
if (friendly_name) {
|
||||
spi.is_printer = looks_like_printer(*friendly_name);
|
||||
spi.friendly_name = (boost::format("%1% (%2%)") % *friendly_name % path).str();
|
||||
} else {
|
||||
spi.friendly_name = path;
|
||||
}
|
||||
auto vid = sysfs_tty_prop_hex(name, "idVendor");
|
||||
auto pid = sysfs_tty_prop_hex(name, "idProduct");
|
||||
if (vid && pid) {
|
||||
spi.id_vendor = *vid;
|
||||
spi.id_product = *pid;
|
||||
}
|
||||
#else
|
||||
spi.friendly_name = path;
|
||||
#endif
|
||||
output.emplace_back(std::move(spi));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
output.erase(std::remove_if(output.begin(), output.end(),
|
||||
[](const SerialPortInfo &info) {
|
||||
return boost::starts_with(info.port, "Bluetooth") || boost::starts_with(info.port, "FireFly");
|
||||
}),
|
||||
output.end());
|
||||
return output;
|
||||
}
|
||||
|
||||
std::vector<std::string> scan_serial_ports()
|
||||
{
|
||||
std::vector<SerialPortInfo> ports = scan_serial_ports_extended();
|
||||
std::vector<std::string> output;
|
||||
output.reserve(ports.size());
|
||||
for (const SerialPortInfo &spi : ports)
|
||||
output.emplace_back(std::move(spi.port));
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Class Serial
|
||||
|
||||
namespace asio = boost::asio;
|
||||
using boost::system::error_code;
|
||||
|
||||
Serial::Serial(asio::io_service& io_service) :
|
||||
asio::serial_port(io_service)
|
||||
{}
|
||||
|
||||
Serial::Serial(asio::io_service& io_service, const std::string &name, unsigned baud_rate) :
|
||||
asio::serial_port(io_service, name)
|
||||
{
|
||||
set_baud_rate(baud_rate);
|
||||
}
|
||||
|
||||
Serial::~Serial() {}
|
||||
|
||||
void Serial::set_baud_rate(unsigned baud_rate)
|
||||
{
|
||||
try {
|
||||
// This does not support speeds > 115200
|
||||
set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
|
||||
} catch (boost::system::system_error &) {
|
||||
auto handle = native_handle();
|
||||
|
||||
auto handle_errno = [](int retval) {
|
||||
if (retval != 0) {
|
||||
throw Slic3r::RuntimeError(
|
||||
(boost::format("Could not set baud rate: %1%") % strerror(errno)).str()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
#if __APPLE__
|
||||
termios ios;
|
||||
handle_errno(::tcgetattr(handle, &ios));
|
||||
handle_errno(::cfsetspeed(&ios, baud_rate));
|
||||
speed_t newSpeed = baud_rate;
|
||||
handle_errno(::ioctl(handle, IOSSIOSPEED, &newSpeed));
|
||||
handle_errno(::tcsetattr(handle, TCSANOW, &ios));
|
||||
#elif __linux__
|
||||
|
||||
/* The following definitions are kindly borrowed from:
|
||||
/usr/include/asm-generic/termbits.h
|
||||
Unfortunately we cannot just include that one because
|
||||
it would redefine the "struct termios" already defined
|
||||
the <termios.h> already included by Boost.ASIO. */
|
||||
#define K_NCCS 19
|
||||
struct termios2 {
|
||||
tcflag_t c_iflag;
|
||||
tcflag_t c_oflag;
|
||||
tcflag_t c_cflag;
|
||||
tcflag_t c_lflag;
|
||||
cc_t c_line;
|
||||
cc_t c_cc[K_NCCS];
|
||||
speed_t c_ispeed;
|
||||
speed_t c_ospeed;
|
||||
};
|
||||
#define BOTHER CBAUDEX
|
||||
|
||||
termios2 ios;
|
||||
handle_errno(::ioctl(handle, TCGETS2, &ios));
|
||||
ios.c_ispeed = ios.c_ospeed = baud_rate;
|
||||
ios.c_cflag &= ~CBAUD;
|
||||
ios.c_cflag |= BOTHER | CLOCAL | CREAD;
|
||||
ios.c_cc[VMIN] = 1; // Minimum of characters to read, prevents eof errors when 0 bytes are read
|
||||
ios.c_cc[VTIME] = 1;
|
||||
handle_errno(::ioctl(handle, TCSETS2, &ios));
|
||||
|
||||
#elif __OpenBSD__
|
||||
struct termios ios;
|
||||
handle_errno(::tcgetattr(handle, &ios));
|
||||
handle_errno(::cfsetspeed(&ios, baud_rate));
|
||||
handle_errno(::tcsetattr(handle, TCSAFLUSH, &ios));
|
||||
#else
|
||||
throw Slic3r::RuntimeError("Custom baud rates are not currently supported on this OS");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void Serial::set_DTR(bool on)
|
||||
{
|
||||
auto handle = native_handle();
|
||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
||||
if (! EscapeCommFunction(handle, on ? SETDTR : CLRDTR)) {
|
||||
throw Slic3r::RuntimeError("Could not set serial port DTR");
|
||||
}
|
||||
#else
|
||||
int status;
|
||||
if (::ioctl(handle, TIOCMGET, &status) == 0) {
|
||||
on ? status |= TIOCM_DTR : status &= ~TIOCM_DTR;
|
||||
if (::ioctl(handle, TIOCMSET, &status) == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw Slic3r::RuntimeError(
|
||||
(boost::format("Could not set serial port DTR: %1%") % strerror(errno)).str()
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Serial::reset_line_num()
|
||||
{
|
||||
// See https://github.com/MarlinFirmware/Marlin/wiki/M110
|
||||
write_string("M110 N0\n");
|
||||
m_line_num = 0;
|
||||
}
|
||||
|
||||
bool Serial::read_line(unsigned timeout, std::string &line, error_code &ec)
|
||||
{
|
||||
auto& io_service =
|
||||
#if BOOST_VERSION >= 107000
|
||||
//FIXME this is most certainly wrong!
|
||||
(boost::asio::io_context&)this->get_executor().context();
|
||||
#else
|
||||
this->get_io_service();
|
||||
#endif
|
||||
asio::deadline_timer timer(io_service);
|
||||
char c = 0;
|
||||
bool fail = false;
|
||||
|
||||
while (true) {
|
||||
io_service.reset();
|
||||
|
||||
asio::async_read(*this, boost::asio::buffer(&c, 1), [&](const error_code &read_ec, size_t size) {
|
||||
if (ec || size == 0) {
|
||||
fail = true;
|
||||
ec = read_ec; // FIXME: only if operation not aborted
|
||||
}
|
||||
timer.cancel(); // FIXME: ditto
|
||||
});
|
||||
|
||||
if (timeout > 0) {
|
||||
timer.expires_from_now(boost::posix_time::milliseconds(timeout));
|
||||
timer.async_wait([&](const error_code &ec) {
|
||||
// Ignore timer aborts
|
||||
if (!ec) {
|
||||
fail = true;
|
||||
this->cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
io_service.run();
|
||||
|
||||
if (fail) {
|
||||
return false;
|
||||
} else if (c != '\n') {
|
||||
line += c;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Serial::printer_setup()
|
||||
{
|
||||
printer_reset();
|
||||
write_string("\r\r\r\r\r\r\r\r\r\r"); // Gets rid of line noise, if any
|
||||
}
|
||||
|
||||
size_t Serial::write_string(const std::string &str)
|
||||
{
|
||||
// TODO: might be wise to timeout here as well
|
||||
return asio::write(*this, asio::buffer(str));
|
||||
}
|
||||
|
||||
bool Serial::printer_ready_wait(unsigned retries, unsigned timeout)
|
||||
{
|
||||
std::string line;
|
||||
error_code ec;
|
||||
|
||||
for (; retries > 0; retries--) {
|
||||
reset_line_num();
|
||||
|
||||
while (read_line(timeout, line, ec)) {
|
||||
if (line == "ok") {
|
||||
return true;
|
||||
}
|
||||
line.clear();
|
||||
}
|
||||
|
||||
line.clear();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t Serial::printer_write_line(const std::string &line, unsigned line_num)
|
||||
{
|
||||
const auto formatted_line = Utils::Serial::printer_format_line(line, line_num);
|
||||
return write_string(formatted_line);
|
||||
}
|
||||
|
||||
size_t Serial::printer_write_line(const std::string &line)
|
||||
{
|
||||
m_line_num++;
|
||||
return printer_write_line(line, m_line_num);
|
||||
}
|
||||
|
||||
void Serial::printer_reset()
|
||||
{
|
||||
this->set_DTR(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
this->set_DTR(true);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
this->set_DTR(false);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
|
||||
std::string Serial::printer_format_line(const std::string &line, unsigned line_num)
|
||||
{
|
||||
const auto line_num_str = std::to_string(line_num);
|
||||
|
||||
unsigned checksum = 'N';
|
||||
for (auto c : line_num_str) { checksum ^= c; }
|
||||
checksum ^= ' ';
|
||||
for (auto c : line) { checksum ^= c; }
|
||||
|
||||
return (boost::format("N%1% %2%*%3%\n") % line_num_str % line % checksum).str();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
} // namespace Utils
|
||||
} // namespace Slic3r
|
||||
97
src/slic3r/Utils/Serial.hpp
Normal file
97
src/slic3r/Utils/Serial.hpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#ifndef slic3r_GUI_Utils_Serial_hpp_
|
||||
#define slic3r_GUI_Utils_Serial_hpp_
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace Utils {
|
||||
|
||||
struct SerialPortInfo {
|
||||
std::string port;
|
||||
unsigned id_vendor = -1;
|
||||
unsigned id_product = -1;
|
||||
std::string friendly_name;
|
||||
bool is_printer = false;
|
||||
|
||||
SerialPortInfo() {}
|
||||
SerialPortInfo(std::string port) : port(port), friendly_name(std::move(port)) {}
|
||||
|
||||
bool id_match(unsigned id_vendor, unsigned id_product) const { return id_vendor == this->id_vendor && id_product == this->id_product; }
|
||||
};
|
||||
|
||||
inline bool operator==(const SerialPortInfo &sp1, const SerialPortInfo &sp2)
|
||||
{
|
||||
return
|
||||
sp1.port == sp2.port &&
|
||||
sp1.id_vendor == sp2.id_vendor &&
|
||||
sp1.id_product == sp2.id_product &&
|
||||
sp1.is_printer == sp2.is_printer;
|
||||
}
|
||||
|
||||
extern std::vector<std::string> scan_serial_ports();
|
||||
extern std::vector<SerialPortInfo> scan_serial_ports_extended();
|
||||
|
||||
|
||||
class Serial : public boost::asio::serial_port
|
||||
{
|
||||
public:
|
||||
Serial(boost::asio::io_service &io_service);
|
||||
Serial(boost::asio::io_service &io_service, const std::string &name, unsigned baud_rate);
|
||||
Serial(const Serial &) = delete;
|
||||
Serial &operator=(const Serial &) = delete;
|
||||
~Serial();
|
||||
|
||||
void set_baud_rate(unsigned baud_rate);
|
||||
|
||||
// The Serial implementation is currently in disarray and therefore commented out.
|
||||
// The boost implementation seems to have several problems, such as lack of support
|
||||
// for custom baud rates, few weird implementation bugs and a history of API breakages.
|
||||
// It's questionable whether it solves more problems than causes. Probably not.
|
||||
// TODO: Custom implementation not based on asio.
|
||||
//
|
||||
// As of now, this class is only kept for the purpose of rebooting AVR109,
|
||||
// see FirmwareDialog::priv::avr109_reboot()
|
||||
|
||||
/*
|
||||
void set_DTR(bool on);
|
||||
|
||||
// Resets the line number both internally as well as with the firmware using M110
|
||||
void reset_line_num();
|
||||
|
||||
// Reads a line or times out, the timeout is in milliseconds
|
||||
bool read_line(unsigned timeout, std::string &line, boost::system::error_code &ec);
|
||||
|
||||
// Perform an initial setup for communicating with a printer
|
||||
void printer_setup();
|
||||
|
||||
// Write data from a string
|
||||
size_t write_string(const std::string &str);
|
||||
|
||||
// Attempts to reset the line numer and waits until the printer says "ok"
|
||||
bool printer_ready_wait(unsigned retries, unsigned timeout);
|
||||
|
||||
// Write Marlin-formatted line, with a line number and a checksum
|
||||
size_t printer_write_line(const std::string &line, unsigned line_num);
|
||||
|
||||
// Same as above, but with internally-managed line number
|
||||
size_t printer_write_line(const std::string &line);
|
||||
|
||||
// Toggles DTR to reset the printer
|
||||
void printer_reset();
|
||||
|
||||
// Formats a line Marlin-style, ie. with a sequential number and a checksum
|
||||
static std::string printer_format_line(const std::string &line, unsigned line_num);
|
||||
private:
|
||||
unsigned m_line_num = 0;
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
} // Utils
|
||||
} // Slic3r
|
||||
|
||||
#endif /* slic3r_GUI_Utils_Serial_hpp_ */
|
||||
Loading…
Add table
Add a link
Reference in a new issue