Merge branch 'master' into wipe_tower_improvements

This commit is contained in:
Lukas Matena 2018-04-04 13:06:46 +02:00
commit eb9917536c
27 changed files with 457 additions and 170 deletions

View file

@ -1443,10 +1443,10 @@ namespace Slic3r {
IdToObjectDataMap m_objects_data;
public:
bool save_model_to_file(const std::string& filename, Model& model, const Print& print);
bool save_model_to_file(const std::string& filename, Model& model, const Print& print, bool export_print_config);
private:
bool _save_model_to_file(const std::string& filename, Model& model, const Print& print);
bool _save_model_to_file(const std::string& filename, Model& model, const Print& print, bool export_print_config);
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
bool _add_relationships_file_to_archive(mz_zip_archive& archive);
bool _add_model_file_to_archive(mz_zip_archive& archive, Model& model);
@ -1457,13 +1457,13 @@ namespace Slic3r {
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model);
};
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const Print& print)
bool _3MF_Exporter::save_model_to_file(const std::string& filename, Model& model, const Print& print, bool export_print_config)
{
clear_errors();
return _save_model_to_file(filename, model, print);
return _save_model_to_file(filename, model, print, export_print_config);
}
bool _3MF_Exporter::_save_model_to_file(const std::string& filename, Model& model, const Print& print)
bool _3MF_Exporter::_save_model_to_file(const std::string& filename, Model& model, const Print& print, bool export_print_config)
{
mz_zip_archive archive;
mz_zip_zero_struct(&archive);
@ -1502,11 +1502,14 @@ namespace Slic3r {
}
// adds slic3r print config file
if (!_add_print_config_file_to_archive(archive, print))
if (export_print_config)
{
mz_zip_writer_end(&archive);
boost::filesystem::remove(filename);
return false;
if (!_add_print_config_file_to_archive(archive, print))
{
mz_zip_writer_end(&archive);
boost::filesystem::remove(filename);
return false;
}
}
// adds slic3r model config file
@ -1863,13 +1866,13 @@ namespace Slic3r {
return res;
}
bool store_3mf(const char* path, Model* model, Print* print)
bool store_3mf(const char* path, Model* model, Print* print, bool export_print_config)
{
if ((path == nullptr) || (model == nullptr) || (print == nullptr))
return false;
_3MF_Exporter exporter;
bool res = exporter.save_model_to_file(path, *model, *print);
bool res = exporter.save_model_to_file(path, *model, *print, export_print_config);
if (!res)
exporter.log_errors();

View file

@ -12,7 +12,7 @@ namespace Slic3r {
// Save the given model and the config data contained in the given Print into a 3mf file.
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
extern bool store_3mf(const char* path, Model* model, Print* print);
extern bool store_3mf(const char* path, Model* model, Print* print, bool export_print_config);
}; // namespace Slic3r

View file

@ -576,8 +576,7 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model)
return false;
}
std::string internal_amf_filename = boost::ireplace_last_copy(boost::filesystem::path(path).filename().string(), ".zip.amf", ".amf");
if (internal_amf_filename != stat.m_filename)
if (!boost::iends_with(stat.m_filename, ".amf"))
{
printf("Found invalid internal filename\n");
mz_zip_reader_end(&archive);
@ -644,15 +643,20 @@ bool load_amf(const char *path, PresetBundle* bundle, Model *model)
return false;
}
bool store_amf(const char *path, Model *model, Print* print)
bool store_amf(const char *path, Model *model, Print* print, bool export_print_config)
{
if ((path == nullptr) || (model == nullptr) || (print == nullptr))
return false;
// forces ".zip.amf" extension
std::string export_path = path;
if (!boost::iends_with(export_path, ".zip.amf"))
export_path = boost::filesystem::path(export_path).replace_extension(".zip.amf").string();
mz_zip_archive archive;
mz_zip_zero_struct(&archive);
mz_bool res = mz_zip_writer_init_file(&archive, path, 0);
mz_bool res = mz_zip_writer_init_file(&archive, export_path.c_str(), 0);
if (res == 0)
return false;
@ -661,9 +665,12 @@ bool store_amf(const char *path, Model *model, Print* print)
stream << "<amf unit=\"millimeter\">\n";
stream << "<metadata type=\"cad\">Slic3r " << SLIC3R_VERSION << "</metadata>\n";
std::string config = "\n";
GCode::append_full_config(*print, config);
stream << "<metadata type=\"" << SLIC3R_CONFIG_TYPE << "\">" << config << "</metadata>\n";
if (export_print_config)
{
std::string config = "\n";
GCode::append_full_config(*print, config);
stream << "<metadata type=\"" << SLIC3R_CONFIG_TYPE << "\">" << config << "</metadata>\n";
}
for (const auto &material : model->materials) {
if (material.first.empty())
@ -767,20 +774,20 @@ bool store_amf(const char *path, Model *model, Print* print)
}
stream << "</amf>\n";
std::string internal_amf_filename = boost::ireplace_last_copy(boost::filesystem::path(path).filename().string(), ".zip.amf", ".amf");
std::string internal_amf_filename = boost::ireplace_last_copy(boost::filesystem::path(export_path).filename().string(), ".zip.amf", ".amf");
std::string out = stream.str();
if (!mz_zip_writer_add_mem(&archive, internal_amf_filename.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
{
mz_zip_writer_end(&archive);
boost::filesystem::remove(path);
boost::filesystem::remove(export_path);
return false;
}
if (!mz_zip_writer_finalize_archive(&archive))
{
mz_zip_writer_end(&archive);
boost::filesystem::remove(path);
boost::filesystem::remove(export_path);
return false;
}

View file

@ -12,7 +12,7 @@ extern bool load_amf(const char *path, PresetBundle* bundle, Model *model);
// Save the given model and the config data contained in the given Print into an amf file.
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
extern bool store_amf(const char *path, Model *model, Print* print);
extern bool store_amf(const char *path, Model *model, Print* print, bool export_print_config);
}; // namespace Slic3r

View file

@ -97,8 +97,8 @@ GCodeAnalyzer::GCodeAnalyzer()
void GCodeAnalyzer::reset()
{
_set_units(Millimeters);
_set_positioning_xyz_type(Absolute);
_set_positioning_e_type(Relative);
_set_global_positioning_type(Absolute);
_set_e_local_positioning_type(Absolute);
_set_extrusion_role(erNone);
_set_extruder_id(DEFAULT_EXTRUDER_ID);
_set_mm3_per_mm(Default_mm3_per_mm);
@ -177,6 +177,16 @@ void GCodeAnalyzer::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLi
_processG1(line);
break;
}
case 10: // Retract
{
_processG10(line);
break;
}
case 11: // Unretract
{
_processG11(line);
break;
}
case 22: // Firmware controlled Retract
{
_processG22(line);
@ -237,13 +247,13 @@ void GCodeAnalyzer::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLi
}
// Returns the new absolute position on the given axis in dependence of the given parameters
float axis_absolute_position_from_G1_line(GCodeAnalyzer::EAxis axis, const GCodeReader::GCodeLine& lineG1, GCodeAnalyzer::EUnits units, GCodeAnalyzer::EPositioningType type, float current_absolute_position)
float axis_absolute_position_from_G1_line(GCodeAnalyzer::EAxis axis, const GCodeReader::GCodeLine& lineG1, GCodeAnalyzer::EUnits units, bool is_relative, float current_absolute_position)
{
float lengthsScaleFactor = (units == GCodeAnalyzer::Inches) ? INCHES_TO_MM : 1.0f;
if (lineG1.has(Slic3r::Axis(axis)))
{
float ret = lineG1.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
return (type == GCodeAnalyzer::Absolute) ? ret : current_absolute_position + ret;
return is_relative ? current_absolute_position + ret : ret;
}
else
return current_absolute_position;
@ -256,7 +266,11 @@ void GCodeAnalyzer::_processG1(const GCodeReader::GCodeLine& line)
float new_pos[Num_Axis];
for (unsigned char a = X; a < Num_Axis; ++a)
{
new_pos[a] = axis_absolute_position_from_G1_line((EAxis)a, line, units, (a == E) ? _get_positioning_e_type() : _get_positioning_xyz_type(), _get_axis_position((EAxis)a));
bool is_relative = (_get_global_positioning_type() == Relative);
if (a == E)
is_relative |= (_get_e_local_positioning_type() == Relative);
new_pos[a] = axis_absolute_position_from_G1_line((EAxis)a, line, units, is_relative, _get_axis_position((EAxis)a));
}
// updates feedrate from line, if present
@ -305,6 +319,18 @@ void GCodeAnalyzer::_processG1(const GCodeReader::GCodeLine& line)
_store_move(type);
}
void GCodeAnalyzer::_processG10(const GCodeReader::GCodeLine& line)
{
// stores retract move
_store_move(GCodeMove::Retract);
}
void GCodeAnalyzer::_processG11(const GCodeReader::GCodeLine& line)
{
// stores unretract move
_store_move(GCodeMove::Unretract);
}
void GCodeAnalyzer::_processG22(const GCodeReader::GCodeLine& line)
{
// stores retract move
@ -319,12 +345,12 @@ void GCodeAnalyzer::_processG23(const GCodeReader::GCodeLine& line)
void GCodeAnalyzer::_processG90(const GCodeReader::GCodeLine& line)
{
_set_positioning_xyz_type(Absolute);
_set_global_positioning_type(Absolute);
}
void GCodeAnalyzer::_processG91(const GCodeReader::GCodeLine& line)
{
_set_positioning_xyz_type(Relative);
_set_global_positioning_type(Relative);
}
void GCodeAnalyzer::_processG92(const GCodeReader::GCodeLine& line)
@ -367,12 +393,12 @@ void GCodeAnalyzer::_processG92(const GCodeReader::GCodeLine& line)
void GCodeAnalyzer::_processM82(const GCodeReader::GCodeLine& line)
{
_set_positioning_e_type(Absolute);
_set_e_local_positioning_type(Absolute);
}
void GCodeAnalyzer::_processM83(const GCodeReader::GCodeLine& line)
{
_set_positioning_e_type(Relative);
_set_e_local_positioning_type(Relative);
}
void GCodeAnalyzer::_processT(const GCodeReader::GCodeLine& line)
@ -466,24 +492,24 @@ GCodeAnalyzer::EUnits GCodeAnalyzer::_get_units() const
return m_state.units;
}
void GCodeAnalyzer::_set_positioning_xyz_type(GCodeAnalyzer::EPositioningType type)
void GCodeAnalyzer::_set_global_positioning_type(GCodeAnalyzer::EPositioningType type)
{
m_state.positioning_xyz_type = type;
m_state.global_positioning_type = type;
}
GCodeAnalyzer::EPositioningType GCodeAnalyzer::_get_positioning_xyz_type() const
GCodeAnalyzer::EPositioningType GCodeAnalyzer::_get_global_positioning_type() const
{
return m_state.positioning_xyz_type;
return m_state.global_positioning_type;
}
void GCodeAnalyzer::_set_positioning_e_type(GCodeAnalyzer::EPositioningType type)
void GCodeAnalyzer::_set_e_local_positioning_type(GCodeAnalyzer::EPositioningType type)
{
m_state.positioning_e_type = type;
m_state.e_local_positioning_type = type;
}
GCodeAnalyzer::EPositioningType GCodeAnalyzer::_get_positioning_e_type() const
GCodeAnalyzer::EPositioningType GCodeAnalyzer::_get_e_local_positioning_type() const
{
return m_state.positioning_e_type;
return m_state.e_local_positioning_type;
}
void GCodeAnalyzer::_set_extrusion_role(ExtrusionRole extrusion_role)
@ -648,14 +674,16 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
float z = FLT_MAX;
Polyline polyline;
Pointf3 position(FLT_MAX, FLT_MAX, FLT_MAX);
float volumetric_rate = FLT_MAX;
GCodePreviewData::Range height_range;
GCodePreviewData::Range width_range;
GCodePreviewData::Range feedrate_range;
GCodePreviewData::Range volumetric_rate_range;
// constructs the polylines while traversing the moves
for (const GCodeMove& move : extrude_moves->second)
{
if ((data != move.data) || (data.feedrate != move.data.feedrate) || (z != move.start_position.z) || (position != move.start_position))
if ((data != move.data) || (z != move.start_position.z) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * (float)move.data.mm3_per_mm))
{
// store current polyline
polyline.remove_duplicate_points();
@ -671,9 +699,11 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
// update current values
data = move.data;
z = move.start_position.z;
volumetric_rate = move.data.feedrate * (float)move.data.mm3_per_mm;
height_range.update_from(move.data.height);
width_range.update_from(move.data.width);
feedrate_range.update_from(move.data.feedrate);
volumetric_rate_range.update_from(volumetric_rate);
}
else
// append end vertex of the move to current polyline
@ -688,9 +718,10 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
Helper::store_polyline(polyline, data, z, preview_data);
// updates preview ranges data
preview_data.extrusion.ranges.height.set_from(height_range);
preview_data.extrusion.ranges.width.set_from(width_range);
preview_data.extrusion.ranges.feedrate.set_from(feedrate_range);
preview_data.ranges.height.set_from(height_range);
preview_data.ranges.width.set_from(width_range);
preview_data.ranges.feedrate.set_from(feedrate_range);
preview_data.ranges.volumetric_rate.set_from(volumetric_rate_range);
}
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
@ -717,6 +748,10 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
float feedrate = FLT_MAX;
unsigned int extruder_id = -1;
GCodePreviewData::Range height_range;
GCodePreviewData::Range width_range;
GCodePreviewData::Range feedrate_range;
// constructs the polylines while traversing the moves
for (const GCodeMove& move : travel_moves->second)
{
@ -745,11 +780,19 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
type = move_type;
feedrate = move.data.feedrate;
extruder_id = move.data.extruder_id;
height_range.update_from(move.data.height);
width_range.update_from(move.data.width);
feedrate_range.update_from(move.data.feedrate);
}
// store last polyline
polyline.remove_duplicate_points();
Helper::store_polyline(polyline, type, direction, feedrate, extruder_id, preview_data);
// updates preview ranges data
preview_data.ranges.height.set_from(height_range);
preview_data.ranges.width.set_from(width_range);
preview_data.ranges.feedrate.set_from(feedrate_range);
}
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data)

View file

@ -90,8 +90,8 @@ private:
struct State
{
EUnits units;
EPositioningType positioning_xyz_type;
EPositioningType positioning_e_type;
EPositioningType global_positioning_type;
EPositioningType e_local_positioning_type;
Metadata data;
Pointf3 start_position;
float start_extrusion;
@ -127,6 +127,12 @@ private:
// Move
void _processG1(const GCodeReader::GCodeLine& line);
// Retract
void _processG10(const GCodeReader::GCodeLine& line);
// Unretract
void _processG11(const GCodeReader::GCodeLine& line);
// Firmware controlled Retract
void _processG22(const GCodeReader::GCodeLine& line);
@ -170,11 +176,11 @@ private:
void _set_units(EUnits units);
EUnits _get_units() const;
void _set_positioning_xyz_type(EPositioningType type);
EPositioningType _get_positioning_xyz_type() const;
void _set_global_positioning_type(EPositioningType type);
EPositioningType _get_global_positioning_type() const;
void _set_positioning_e_type(EPositioningType type);
EPositioningType _get_positioning_e_type() const;
void _set_e_local_positioning_type(EPositioningType type);
EPositioningType _get_e_local_positioning_type() const;
void _set_extrusion_role(ExtrusionRole extrusion_role);
ExtrusionRole _get_extrusion_role() const;

View file

@ -85,6 +85,12 @@ void GCodePreviewData::Range::update_from(float value)
max = std::max(max, value);
}
void GCodePreviewData::Range::update_from(const Range& other)
{
min = std::min(min, other.min);
max = std::max(max, other.max);
}
void GCodePreviewData::Range::set_from(const Range& other)
{
min = other.min;
@ -158,9 +164,6 @@ void GCodePreviewData::Extrusion::set_default()
view_type = Default_View_Type;
::memcpy((void*)role_colors, (const void*)Default_Extrusion_Role_Colors, Num_Extrusion_Roles * sizeof(Color));
::memcpy((void*)ranges.height.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
::memcpy((void*)ranges.width.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
::memcpy((void*)ranges.feedrate.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i)
{
@ -198,6 +201,7 @@ void GCodePreviewData::Travel::set_default()
width = Default_Width;
height = Default_Height;
::memcpy((void*)type_colors, (const void*)Default_Type_Colors, Num_Types * sizeof(Color));
is_visible = false;
}
@ -228,6 +232,11 @@ GCodePreviewData::GCodePreviewData()
void GCodePreviewData::set_default()
{
::memcpy((void*)ranges.height.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
::memcpy((void*)ranges.width.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
::memcpy((void*)ranges.feedrate.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
::memcpy((void*)ranges.volumetric_rate.colors, (const void*)Range::Default_Colors, Range::Colors_Count * sizeof(Color));
extrusion.set_default();
travel.set_default();
retraction.set_default();
@ -237,6 +246,10 @@ void GCodePreviewData::set_default()
void GCodePreviewData::reset()
{
ranges.width.reset();
ranges.height.reset();
ranges.feedrate.reset();
ranges.volumetric_rate.reset();
extrusion.layers.clear();
travel.polylines.clear();
retraction.positions.clear();
@ -253,19 +266,24 @@ const GCodePreviewData::Color& GCodePreviewData::get_extrusion_role_color(Extrus
return extrusion.role_colors[role];
}
const GCodePreviewData::Color& GCodePreviewData::get_extrusion_height_color(float height) const
const GCodePreviewData::Color& GCodePreviewData::get_height_color(float height) const
{
return extrusion.ranges.height.get_color_at(height);
return ranges.height.get_color_at(height);
}
const GCodePreviewData::Color& GCodePreviewData::get_extrusion_width_color(float width) const
const GCodePreviewData::Color& GCodePreviewData::get_width_color(float width) const
{
return extrusion.ranges.width.get_color_at(width);
return ranges.width.get_color_at(width);
}
const GCodePreviewData::Color& GCodePreviewData::get_extrusion_feedrate_color(float feedrate) const
const GCodePreviewData::Color& GCodePreviewData::get_feedrate_color(float feedrate) const
{
return extrusion.ranges.feedrate.get_color_at(feedrate);
return ranges.feedrate.get_color_at(feedrate);
}
const GCodePreviewData::Color& GCodePreviewData::get_volumetric_rate_color(float rate) const
{
return ranges.volumetric_rate.get_color_at(rate);
}
void GCodePreviewData::set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha)
@ -334,6 +352,8 @@ std::string GCodePreviewData::get_legend_title() const
return L("Width (mm)");
case Extrusion::Feedrate:
return L("Speed (mm/s)");
case Extrusion::VolumetricRate:
return L("Volumetric flow rate (mm3/s)");
case Extrusion::Tool:
return L("Tool");
}
@ -348,10 +368,11 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
static void FillListFromRange(LegendItemsList& list, const Range& range, unsigned int decimals, float scale_factor)
{
list.reserve(Range::Colors_Count);
float step = range.step_size();
for (unsigned int i = 0; i < Range::Colors_Count; ++i)
{
char buf[32];
char buf[1024];
sprintf(buf, "%.*f/%.*f", decimals, scale_factor * (range.min + (float)i * step), decimals, scale_factor * (range.min + (float)(i + 1) * step));
list.emplace_back(buf, range.colors[i]);
}
@ -377,17 +398,22 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
}
case Extrusion::Height:
{
Helper::FillListFromRange(items, extrusion.ranges.height, 3, 1.0f);
Helper::FillListFromRange(items, ranges.height, 3, 1.0f);
break;
}
case Extrusion::Width:
{
Helper::FillListFromRange(items, extrusion.ranges.width, 3, 1.0f);
Helper::FillListFromRange(items, ranges.width, 3, 1.0f);
break;
}
case Extrusion::Feedrate:
{
Helper::FillListFromRange(items, extrusion.ranges.feedrate, 0, 1.0f);
Helper::FillListFromRange(items, ranges.feedrate, 0, 1.0f);
break;
}
case Extrusion::VolumetricRate:
{
Helper::FillListFromRange(items, ranges.volumetric_rate, 3, 1.0f);
break;
}
case Extrusion::Tool:

View file

@ -37,6 +37,7 @@ public:
void reset();
bool empty() const;
void update_from(float value);
void update_from(const Range& other);
void set_from(const Range& other);
float step_size() const;
@ -44,6 +45,14 @@ public:
const Color& get_color_at_max() const;
};
struct Ranges
{
Range height;
Range width;
Range feedrate;
Range volumetric_rate;
};
struct LegendItem
{
std::string text;
@ -62,6 +71,7 @@ public:
Height,
Width,
Feedrate,
VolumetricRate,
Tool,
Num_View_Types
};
@ -71,13 +81,6 @@ public:
static const std::string Default_Extrusion_Role_Names[Num_Extrusion_Roles];
static const EViewType Default_View_Type;
struct Ranges
{
Range height;
Range width;
Range feedrate;
};
struct Layer
{
float z;
@ -91,7 +94,6 @@ public:
EViewType view_type;
Color role_colors[Num_Extrusion_Roles];
std::string role_names[Num_Extrusion_Roles];
Ranges ranges;
LayersList layers;
unsigned int role_flags;
@ -178,6 +180,7 @@ public:
Retraction retraction;
Retraction unretraction;
Shell shell;
Ranges ranges;
GCodePreviewData();
@ -186,9 +189,10 @@ public:
bool empty() const;
const Color& get_extrusion_role_color(ExtrusionRole role) const;
const Color& get_extrusion_height_color(float height) const;
const Color& get_extrusion_width_color(float width) const;
const Color& get_extrusion_feedrate_color(float feedrate) const;
const Color& get_height_color(float height) const;
const Color& get_width_color(float width) const;
const Color& get_feedrate_color(float feedrate) const;
const Color& get_volumetric_rate_color(float rate) const;
void set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha);
void set_extrusion_paths_colors(const std::vector<std::string>& colors);

View file

@ -369,24 +369,24 @@ namespace Slic3r {
return _state.units;
}
void GCodeTimeEstimator::set_positioning_xyz_type(GCodeTimeEstimator::EPositioningType type)
void GCodeTimeEstimator::set_global_positioning_type(GCodeTimeEstimator::EPositioningType type)
{
_state.positioning_xyz_type = type;
_state.global_positioning_type = type;
}
GCodeTimeEstimator::EPositioningType GCodeTimeEstimator::get_positioning_xyz_type() const
GCodeTimeEstimator::EPositioningType GCodeTimeEstimator::get_global_positioning_type() const
{
return _state.positioning_xyz_type;
return _state.global_positioning_type;
}
void GCodeTimeEstimator::set_positioning_e_type(GCodeTimeEstimator::EPositioningType type)
void GCodeTimeEstimator::set_e_local_positioning_type(GCodeTimeEstimator::EPositioningType type)
{
_state.positioning_e_type = type;
_state.e_local_positioning_type = type;
}
GCodeTimeEstimator::EPositioningType GCodeTimeEstimator::get_positioning_e_type() const
GCodeTimeEstimator::EPositioningType GCodeTimeEstimator::get_e_local_positioning_type() const
{
return _state.positioning_e_type;
return _state.e_local_positioning_type;
}
void GCodeTimeEstimator::add_additional_time(float timeSec)
@ -408,8 +408,8 @@ namespace Slic3r {
{
set_units(Millimeters);
set_dialect(gcfRepRap);
set_positioning_xyz_type(Absolute);
set_positioning_e_type(Relative);
set_global_positioning_type(Absolute);
set_e_local_positioning_type(Absolute);
set_feedrate(DEFAULT_FEEDRATE);
set_acceleration(DEFAULT_ACCELERATION);
@ -628,13 +628,13 @@ namespace Slic3r {
}
// Returns the new absolute position on the given axis in dependence of the given parameters
float axis_absolute_position_from_G1_line(GCodeTimeEstimator::EAxis axis, const GCodeReader::GCodeLine& lineG1, GCodeTimeEstimator::EUnits units, GCodeTimeEstimator::EPositioningType type, float current_absolute_position)
float axis_absolute_position_from_G1_line(GCodeTimeEstimator::EAxis axis, const GCodeReader::GCodeLine& lineG1, GCodeTimeEstimator::EUnits units, bool is_relative, float current_absolute_position)
{
float lengthsScaleFactor = (units == GCodeTimeEstimator::Inches) ? INCHES_TO_MM : 1.0f;
if (lineG1.has(Slic3r::Axis(axis)))
{
float ret = lineG1.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
return (type == GCodeTimeEstimator::Absolute) ? ret : current_absolute_position + ret;
return is_relative ? current_absolute_position + ret : ret;
}
else
return current_absolute_position;
@ -647,7 +647,11 @@ namespace Slic3r {
float new_pos[Num_Axis];
for (unsigned char a = X; a < Num_Axis; ++a)
{
new_pos[a] = axis_absolute_position_from_G1_line((EAxis)a, line, units, (a == E) ? get_positioning_e_type() : get_positioning_xyz_type(), get_axis_position((EAxis)a));
bool is_relative = (get_global_positioning_type() == Relative);
if (a == E)
is_relative |= (get_e_local_positioning_type() == Relative);
new_pos[a] = axis_absolute_position_from_G1_line((EAxis)a, line, units, is_relative, get_axis_position((EAxis)a));
}
// updates feedrate from line, if present
@ -865,14 +869,12 @@ namespace Slic3r {
void GCodeTimeEstimator::_processG90(const GCodeReader::GCodeLine& line)
{
set_positioning_xyz_type(Absolute);
set_global_positioning_type(Absolute);
}
void GCodeTimeEstimator::_processG91(const GCodeReader::GCodeLine& line)
{
// TODO: THERE ARE DIALECT VARIANTS
set_positioning_xyz_type(Relative);
set_global_positioning_type(Relative);
}
void GCodeTimeEstimator::_processG92(const GCodeReader::GCodeLine& line)
@ -922,12 +924,12 @@ namespace Slic3r {
void GCodeTimeEstimator::_processM82(const GCodeReader::GCodeLine& line)
{
set_positioning_e_type(Absolute);
set_e_local_positioning_type(Absolute);
}
void GCodeTimeEstimator::_processM83(const GCodeReader::GCodeLine& line)
{
set_positioning_e_type(Relative);
set_e_local_positioning_type(Relative);
}
void GCodeTimeEstimator::_processM109(const GCodeReader::GCodeLine& line)

View file

@ -61,8 +61,8 @@ namespace Slic3r {
{
GCodeFlavor dialect;
EUnits units;
EPositioningType positioning_xyz_type;
EPositioningType positioning_e_type;
EPositioningType global_positioning_type;
EPositioningType e_local_positioning_type;
Axis axis[Num_Axis];
float feedrate; // mm/s
float acceleration; // mm/s^2
@ -257,11 +257,11 @@ namespace Slic3r {
void set_units(EUnits units);
EUnits get_units() const;
void set_positioning_xyz_type(EPositioningType type);
EPositioningType get_positioning_xyz_type() const;
void set_global_positioning_type(EPositioningType type);
EPositioningType get_global_positioning_type() const;
void set_positioning_e_type(EPositioningType type);
EPositioningType get_positioning_e_type() const;
void set_e_local_positioning_type(EPositioningType type);
EPositioningType get_e_local_positioning_type() const;
void add_additional_time(float timeSec);
void set_additional_time(float timeSec);

View file

@ -450,6 +450,8 @@ bool Model::fits_print_volume(const DynamicPrintConfig* config) const
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config->opt_float("max_print_height")));
// Allow the objects to protrude below the print bed
print_volume.min.z = -1e10;
return print_volume.contains(transformed_bounding_box());
}
@ -459,6 +461,8 @@ bool Model::fits_print_volume(const FullPrintConfig &config) const
return true;
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values));
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height));
// Allow the objects to protrude below the print bed
print_volume.min.z = -1e10;
return print_volume.contains(transformed_bounding_box());
}

View file

@ -194,8 +194,8 @@ void GLIndexedVertexArray::render(
const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
const float GLVolume::HOVER_COLOR[4] = { 0.4f, 0.9f, 0.1f, 1.0f };
const float GLVolume::OUTSIDE_COLOR[4] = { 0.75f, 0.0f, 0.75f, 1.0f };
const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 1.0f, 0.0f, 1.0f, 1.0f };
const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f };
const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
void GLVolume::set_render_color(float r, float g, float b, float a)
{
@ -632,6 +632,8 @@ void GLVolumeCollection::update_outside_state(const DynamicPrintConfig* config,
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config->opt_float("max_print_height")));
// Allow the objects to protrude below the print bed
print_volume.min.z = -1e10;
for (GLVolume* volume : this->volumes)
{
@ -647,20 +649,25 @@ void GLVolumeCollection::update_outside_state(const DynamicPrintConfig* config,
std::vector<double> GLVolumeCollection::get_current_print_zs() const
{
// Collect layer top positions of all volumes.
std::vector<double> print_zs;
for (GLVolume *vol : this->volumes)
{
for (coordf_t z : vol->print_zs)
{
double round_z = (double)round(z * 100000.0f) / 100000.0f;
if (std::find(print_zs.begin(), print_zs.end(), round_z) == print_zs.end())
print_zs.push_back(round_z);
}
}
append(print_zs, vol->print_zs);
std::sort(print_zs.begin(), print_zs.end());
// Replace intervals of layers with similar top positions with their average value.
int n = int(print_zs.size());
int k = 0;
for (int i = 0; i < n;) {
int j = i + 1;
coordf_t zmax = print_zs[i] + EPSILON;
for (; j < n && print_zs[j] <= zmax; ++ j) ;
print_zs[k ++] = (j > i + 1) ? (0.5 * (print_zs[i] + print_zs[j - 1])) : print_zs[i];
i = j;
}
if (k < n)
print_zs.erase(print_zs.begin() + k, print_zs.end());
return print_zs;
}
@ -2044,6 +2051,8 @@ void _3DScene::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data,
return path.width;
case GCodePreviewData::Extrusion::Feedrate:
return path.feedrate;
case GCodePreviewData::Extrusion::VolumetricRate:
return path.feedrate * (float)path.mm3_per_mm;
case GCodePreviewData::Extrusion::Tool:
return (float)path.extruder_id;
}
@ -2058,11 +2067,13 @@ void _3DScene::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data,
case GCodePreviewData::Extrusion::FeatureType:
return data.get_extrusion_role_color((ExtrusionRole)(int)value);
case GCodePreviewData::Extrusion::Height:
return data.get_extrusion_height_color(value);
return data.get_height_color(value);
case GCodePreviewData::Extrusion::Width:
return data.get_extrusion_width_color(value);
return data.get_width_color(value);
case GCodePreviewData::Extrusion::Feedrate:
return data.get_extrusion_feedrate_color(value);
return data.get_feedrate_color(value);
case GCodePreviewData::Extrusion::VolumetricRate:
return data.get_volumetric_rate_color(value);
case GCodePreviewData::Extrusion::Tool:
{
static GCodePreviewData::Color color;
@ -2342,7 +2353,7 @@ bool _3DScene::_travel_paths_by_feedrate(const GCodePreviewData& preview_data, G
// creates a new volume for each feedrate
for (Feedrate& feedrate : feedrates)
{
GLVolume* volume = new GLVolume(preview_data.get_extrusion_feedrate_color(feedrate.value).rgba);
GLVolume* volume = new GLVolume(preview_data.get_feedrate_color(feedrate.value).rgba);
if (volume == nullptr)
return false;
else

View file

@ -715,8 +715,53 @@ ConfigOptionsGroup* get_optgroup()
return m_optgroup.get();
}
wxButton* get_wiping_dialog_button(){
return g_wiping_dialog_button;
wxWindow* export_option_creator(wxWindow* parent)
{
wxPanel* panel = new wxPanel(parent, -1);
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
wxCheckBox* cbox = new wxCheckBox(panel, wxID_HIGHEST + 1, L("Export print config"));
sizer->AddSpacer(5);
sizer->Add(cbox, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5);
panel->SetSizer(sizer);
sizer->SetSizeHints(panel);
return panel;
}
void add_export_option(wxFileDialog* dlg, const std::string& format)
{
if ((dlg != nullptr) && (format == "AMF") || (format == "3MF"))
{
if (dlg->SupportsExtraControl())
dlg->SetExtraControlCreator(export_option_creator);
}
}
int get_export_option(wxFileDialog* dlg)
{
if (dlg != nullptr)
{
wxWindow* wnd = dlg->GetExtraControl();
if (wnd != nullptr)
{
wxPanel* panel = dynamic_cast<wxPanel*>(wnd);
if (panel != nullptr)
{
wxWindow* child = panel->FindWindow(wxID_HIGHEST + 1);
if (child != nullptr)
{
wxCheckBox* cbox = dynamic_cast<wxCheckBox*>(child);
if (cbox != nullptr)
return cbox->IsChecked() ? 1 : 0;
}
}
}
}
return 0;
}
} }

View file

@ -19,6 +19,7 @@ class wxColour;
class wxBoxSizer;
class wxFlexGridSizer;
class wxButton;
class wxFileDialog;
namespace Slic3r {
@ -132,6 +133,8 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
ConfigOptionsGroup* get_optgroup();
wxButton* get_wiping_dialog_button();
void add_export_option(wxFileDialog* dlg, const std::string& format);
int get_export_option(wxFileDialog* dlg);
}
}

View file

@ -36,16 +36,20 @@ struct Http::priv
::curl_slist *headerlist;
std::string buffer;
size_t limit;
bool cancel;
std::thread io_thread;
Http::CompleteFn completefn;
Http::ErrorFn errorfn;
Http::ProgressFn progressfn;
priv(const std::string &url);
~priv();
static bool ca_file_supported(::CURL *curl);
static size_t writecb(void *data, size_t size, size_t nmemb, void *userp);
static int xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
std::string curl_error(CURLcode curlcode);
std::string body_size_error();
void http_perform();
@ -55,7 +59,8 @@ Http::priv::priv(const std::string &url) :
curl(::curl_easy_init()),
form(nullptr),
form_end(nullptr),
headerlist(nullptr)
headerlist(nullptr),
cancel(false)
{
if (curl == nullptr) {
throw std::runtime_error(std::string("Could not construct Curl object"));
@ -112,6 +117,24 @@ size_t Http::priv::writecb(void *data, size_t size, size_t nmemb, void *userp)
return realsize;
}
int Http::priv::xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
{
auto self = static_cast<priv*>(userp);
bool cb_cancel = false;
if (self->progressfn) {
Progress progress(dltotal, dlnow, ultotal, ulnow);
self->progressfn(progress, cb_cancel);
}
return self->cancel || cb_cancel;
}
int Http::priv::xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow)
{
return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
}
std::string Http::priv::curl_error(CURLcode curlcode)
{
return (boost::format("%1% (%2%)")
@ -132,6 +155,16 @@ void Http::priv::http_perform()
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
::curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xfercb);
::curl_easy_setopt(curl, CURLOPT_XFERINFODATA, static_cast<void*>(this));
(void)xfercb_legacy; // prevent unused function warning
#else
::curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, xfercb);
::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, static_cast<void*>(this));
#endif
#ifndef NDEBUG
::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
#endif
@ -149,16 +182,16 @@ void Http::priv::http_perform()
::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
if (res != CURLE_OK) {
std::string error;
if (res == CURLE_WRITE_ERROR) {
error = std::move(body_size_error());
} else {
error = std::move(curl_error(res));
};
if (errorfn) {
errorfn(std::move(buffer), std::move(error), http_status);
if (res == CURLE_ABORTED_BY_CALLBACK) {
Progress dummyprogress(0, 0, 0, 0);
bool cancel = true;
if (progressfn) { progressfn(dummyprogress, cancel); }
}
else if (res == CURLE_WRITE_ERROR) {
if (errorfn) { errorfn(std::move(buffer), std::move(body_size_error()), http_status); }
} else {
if (errorfn) { errorfn(std::move(buffer), std::move(curl_error(res)), http_status); }
};
} else {
if (completefn) {
completefn(std::move(buffer), http_status);
@ -258,6 +291,12 @@ Http& Http::on_error(ErrorFn fn)
return *this;
}
Http& Http::on_progress(ProgressFn fn)
{
if (p) { p->progressfn = std::move(fn); }
return *this;
}
Http::Ptr Http::perform()
{
auto self = std::make_shared<Http>(std::move(*this));
@ -277,6 +316,11 @@ void Http::perform_sync()
if (p) { p->http_perform(); }
}
void Http::cancel()
{
if (p) { p->cancel = true; }
}
Http Http::get(std::string url)
{
return std::move(Http{std::move(url)});
@ -297,5 +341,16 @@ bool Http::ca_file_supported()
return res;
}
std::ostream& operator<<(std::ostream &os, const Http::Progress &progress)
{
os << "Http::Progress("
<< "dltotal = " << progress.dltotal
<< ", dlnow = " << progress.dlnow
<< ", ultotal = " << progress.ultotal
<< ", ulnow = " << progress.ulnow
<< ")";
return os;
}
}

View file

@ -14,9 +14,22 @@ class Http : public std::enable_shared_from_this<Http> {
private:
struct priv;
public:
struct Progress
{
size_t dltotal;
size_t dlnow;
size_t ultotal;
size_t ulnow;
Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) :
dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
{}
};
typedef std::shared_ptr<Http> Ptr;
typedef std::function<void(std::string /* body */, unsigned /* http_status */)> CompleteFn;
typedef std::function<void(std::string /* body */, std::string /* error */, unsigned /* http_status */)> ErrorFn;
typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn;
Http(Http &&other);
@ -37,9 +50,11 @@ public:
Http& on_complete(CompleteFn fn);
Http& on_error(ErrorFn fn);
Http& on_progress(ProgressFn fn);
Ptr perform();
void perform_sync();
void cancel();
static bool ca_file_supported();
private:
@ -48,6 +63,8 @@ private:
std::unique_ptr<priv> p;
};
std::ostream& operator<<(std::ostream &, const Http::Progress &);
}

View file

@ -1,10 +1,11 @@
#include "OctoPrint.hpp"
#include <iostream>
#include <algorithm>
#include <boost/format.hpp>
#include <wx/frame.h>
#include <wx/event.h>
#include <wx/progdlg.h>
#include "libslic3r/PrintConfig.hpp"
#include "slic3r/GUI/GUI.hpp"
@ -39,36 +40,53 @@ bool OctoPrint::test(wxString &msg) const
return res;
}
void OctoPrint::send_gcode(int windowId, int completeEvt, int errorEvt, const std::string &filename, bool print) const
bool OctoPrint::send_gcode(const std::string &filename, bool print) const
{
enum { PROGRESS_RANGE = 1000 };
const auto errortitle = _(L("Error while uploading to the OctoPrint server"));
wxProgressDialog progress_dialog(
_(L("OctoPrint upload")),
_(L("Sending G-code file to the OctoPrint server...")),
PROGRESS_RANGE, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
progress_dialog.Pulse();
wxString test_msg;
if (!test(test_msg)) {
auto errormsg = wxString::Format("%s: %s", errortitle, test_msg);
GUI::show_error(&progress_dialog, std::move(errormsg));
return false;
}
bool res = true;
auto http = Http::post(std::move(make_url("api/files/local")));
set_auth(http);
http.form_add("print", print ? "true" : "false")
.form_add_file("file", filename)
.on_complete([=](std::string body, unsigned status) {
wxWindow *window = wxWindow::FindWindowById(windowId);
if (window == nullptr) { return; }
wxCommandEvent* evt = new wxCommandEvent(completeEvt);
evt->SetString(_(L("G-code file successfully uploaded to the OctoPrint server")));
evt->SetInt(100);
wxQueueEvent(window, evt);
.on_complete([&](std::string body, unsigned status) {
progress_dialog.Update(PROGRESS_RANGE);
})
.on_error([=](std::string body, std::string error, unsigned status) {
wxWindow *window = wxWindow::FindWindowById(windowId);
if (window == nullptr) { return; }
wxCommandEvent* evt_complete = new wxCommandEvent(completeEvt);
evt_complete->SetInt(100);
wxQueueEvent(window, evt_complete);
wxCommandEvent* evt_error = new wxCommandEvent(errorEvt);
evt_error->SetString(wxString::Format("%s: %s",
_(L("Error while uploading to the OctoPrint server")),
format_error(error, status)));
wxQueueEvent(window, evt_error);
.on_error([&](std::string body, std::string error, unsigned status) {
auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
GUI::show_error(&progress_dialog, std::move(errormsg));
res = false;
})
.perform();
.on_progress([&](Http::Progress progress, bool &cancel) {
if (cancel) {
// Upload was canceled
res = false;
} else if (progress.ultotal > 0) {
int value = PROGRESS_RANGE * progress.ulnow / progress.ultotal;
cancel = !progress_dialog.Update(std::min(value, PROGRESS_RANGE - 1)); // Cap the value to prevent premature dialog closing
} else {
cancel = !progress_dialog.Pulse();
}
})
.perform_sync();
return res;
}
void OctoPrint::set_auth(Http &http) const

View file

@ -17,7 +17,7 @@ public:
OctoPrint(DynamicPrintConfig *config);
bool test(wxString &curl_msg) const;
void send_gcode(int windowId, int completeEvt, int errorEvt, const std::string &filename, bool print = false) const;
bool send_gcode(const std::string &filename, bool print = false) const;
private:
std::string host;
std::string apikey;

View file

@ -67,3 +67,10 @@ void add_frequently_changed_parameters(SV *ui_parent, SV *ui_sizer, SV *ui_p_siz
std::string fold_utf8_to_ascii(const char *src)
%code%{ RETVAL = Slic3r::fold_utf8_to_ascii(src); %};
void add_export_option(SV *ui, std::string format)
%code%{ Slic3r::GUI::add_export_option((wxFileDialog*)wxPli_sv_2_object(aTHX_ ui, "Wx::FileDialog"), format); %};
int get_export_option(SV *ui)
%code%{ RETVAL = Slic3r::GUI::get_export_option((wxFileDialog*)wxPli_sv_2_object(aTHX_ ui, "Wx::FileDialog")); %};

View file

@ -104,10 +104,10 @@
bool store_stl(char *path, bool binary)
%code%{ TriangleMesh mesh = THIS->mesh(); RETVAL = Slic3r::store_stl(path, &mesh, binary); %};
bool store_amf(char *path, Print* print)
%code%{ RETVAL = Slic3r::store_amf(path, THIS, print); %};
bool store_3mf(char *path, Print* print)
%code%{ RETVAL = Slic3r::store_3mf(path, THIS, print); %};
bool store_amf(char *path, Print* print, bool export_print_config)
%code%{ RETVAL = Slic3r::store_amf(path, THIS, print, export_print_config); %};
bool store_3mf(char *path, Print* print, bool export_print_config)
%code%{ RETVAL = Slic3r::store_3mf(path, THIS, print, export_print_config); %};
%{

View file

@ -9,5 +9,5 @@
OctoPrint(DynamicPrintConfig *config);
~OctoPrint();
void send_gcode(int windowId, int completeEvt, int errorEvt, std::string filename, bool print = false) const;
bool send_gcode(std::string filename, bool print = false) const;
};