mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-22 16:21:24 -06:00
Merge branch 'master' of https://github.com/prusa3d/Slic3r into scene_manipulators
This commit is contained in:
commit
81636abaa9
105 changed files with 8069 additions and 1964 deletions
|
@ -206,6 +206,44 @@ t_config_option_keys ConfigBase::diff(const ConfigBase &other) const
|
|||
return diff;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void add_correct_opts_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 < 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));
|
||||
}
|
||||
}
|
||||
|
||||
t_config_option_keys ConfigBase::deep_diff(const ConfigBase &other) const
|
||||
{
|
||||
t_config_option_keys diff;
|
||||
for (const t_config_option_key &opt_key : this->keys()) {
|
||||
const ConfigOption *this_opt = this->option(opt_key);
|
||||
const ConfigOption *other_opt = other.option(opt_key);
|
||||
if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
|
||||
{
|
||||
if (opt_key == "bed_shape"){ diff.emplace_back(opt_key); continue; }
|
||||
switch (other_opt->type())
|
||||
{
|
||||
case coInts: add_correct_opts_to_diff<ConfigOptionInts >(opt_key, diff, other, this); break;
|
||||
case coBools: add_correct_opts_to_diff<ConfigOptionBools >(opt_key, diff, other, this); break;
|
||||
case coFloats: add_correct_opts_to_diff<ConfigOptionFloats >(opt_key, diff, other, this); break;
|
||||
case coStrings: add_correct_opts_to_diff<ConfigOptionStrings >(opt_key, diff, other, this); break;
|
||||
case coPercents:add_correct_opts_to_diff<ConfigOptionPercents >(opt_key, diff, other, this); break;
|
||||
case coPoints: add_correct_opts_to_diff<ConfigOptionPoints >(opt_key, diff, other, this); break;
|
||||
default: diff.emplace_back(opt_key); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
t_config_option_keys ConfigBase::equal(const ConfigBase &other) const
|
||||
{
|
||||
t_config_option_keys equal;
|
||||
|
|
|
@ -659,6 +659,7 @@ public:
|
|||
ConfigOptionPoints() : ConfigOptionVector<Pointf>() {}
|
||||
explicit ConfigOptionPoints(size_t n, const Pointf &value) : ConfigOptionVector<Pointf>(n, value) {}
|
||||
explicit ConfigOptionPoints(std::initializer_list<Pointf> il) : ConfigOptionVector<Pointf>(std::move(il)) {}
|
||||
explicit ConfigOptionPoints(const std::vector<Pointf> &values) : ConfigOptionVector<Pointf>(values) {}
|
||||
|
||||
static ConfigOptionType static_type() { return coPoints; }
|
||||
ConfigOptionType type() const override { return static_type(); }
|
||||
|
@ -1046,6 +1047,9 @@ public:
|
|||
void apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false);
|
||||
bool equals(const ConfigBase &other) const { return this->diff(other).empty(); }
|
||||
t_config_option_keys diff(const ConfigBase &other) const;
|
||||
// Use deep_diff to correct return of changed options,
|
||||
// considering individual options for each extruder
|
||||
t_config_option_keys deep_diff(const ConfigBase &other) const;
|
||||
t_config_option_keys equal(const ConfigBase &other) const;
|
||||
std::string serialize(const t_config_option_key &opt_key) const;
|
||||
// Set a configuration value from a string, it will call an overridable handle_legacy()
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "libslic3r.h"
|
||||
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Slic3r {
|
||||
|
@ -15,6 +16,9 @@ public:
|
|||
file_parser_error(const std::string &msg, const std::string &file, unsigned long line = 0) :
|
||||
std::runtime_error(format_what(msg, file, line)),
|
||||
m_message(msg), m_filename(file), m_line(line) {}
|
||||
file_parser_error(const std::string &msg, const boost::filesystem::path &file, unsigned long line = 0) :
|
||||
std::runtime_error(format_what(msg, file.string(), line)),
|
||||
m_message(msg), m_filename(file.string()), m_line(line) {}
|
||||
// gcc 3.4.2 complains about lack of throw specifier on compiler
|
||||
// generated dtor
|
||||
~file_parser_error() throw() {}
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
#include <Eigen/Dense>
|
||||
#include <miniz/miniz_zip.h>
|
||||
|
||||
// VERSION NUMBERS
|
||||
// 0 : .3mf, files saved by older slic3r or other applications. No version definition in them.
|
||||
// 1 : Introduction of 3mf versioning. No other change in data saved into 3mf files.
|
||||
const unsigned int VERSION_3MF = 1;
|
||||
const char* SLIC3RPE_3MF_VERSION = "slic3rpe:Version3mf"; // definition of the metadata name saved into .model file
|
||||
|
||||
const std::string MODEL_FOLDER = "3D/";
|
||||
const std::string MODEL_EXTENSION = ".model";
|
||||
const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format of the string which works with CURA
|
||||
|
@ -23,6 +29,7 @@ const std::string CONTENT_TYPES_FILE = "[Content_Types].xml";
|
|||
const std::string RELATIONSHIPS_FILE = "_rels/.rels";
|
||||
const std::string PRINT_CONFIG_FILE = "Metadata/Slic3r_PE.config";
|
||||
const std::string MODEL_CONFIG_FILE = "Metadata/Slic3r_PE_model.config";
|
||||
const std::string LAYER_HEIGHTS_PROFILE_FILE = "Metadata/Slic3r_PE_layer_heights_profile.txt";
|
||||
|
||||
const char* MODEL_TAG = "model";
|
||||
const char* RESOURCES_TAG = "resources";
|
||||
|
@ -36,9 +43,9 @@ const char* COMPONENTS_TAG = "components";
|
|||
const char* COMPONENT_TAG = "component";
|
||||
const char* BUILD_TAG = "build";
|
||||
const char* ITEM_TAG = "item";
|
||||
const char* METADATA_TAG = "metadata";
|
||||
|
||||
const char* CONFIG_TAG = "config";
|
||||
const char* METADATA_TAG = "metadata";
|
||||
const char* VOLUME_TAG = "volume";
|
||||
|
||||
const char* UNIT_ATTR = "unit";
|
||||
|
@ -315,6 +322,10 @@ namespace Slic3r {
|
|||
typedef std::vector<Instance> InstancesList;
|
||||
typedef std::map<int, ObjectMetadata> IdToMetadataMap;
|
||||
typedef std::map<int, Geometry> IdToGeometryMap;
|
||||
typedef std::map<int, std::vector<coordf_t>> IdToLayerHeightsProfileMap;
|
||||
|
||||
// Version of the 3mf file
|
||||
unsigned int m_version;
|
||||
|
||||
XML_Parser m_xml_parser;
|
||||
Model* m_model;
|
||||
|
@ -326,6 +337,9 @@ namespace Slic3r {
|
|||
IdToGeometryMap m_geometries;
|
||||
CurrentConfig m_curr_config;
|
||||
IdToMetadataMap m_objects_metadata;
|
||||
IdToLayerHeightsProfileMap m_layer_heights_profiles;
|
||||
std::string m_curr_metadata_name;
|
||||
std::string m_curr_characters;
|
||||
|
||||
public:
|
||||
_3MF_Importer();
|
||||
|
@ -339,12 +353,14 @@ namespace Slic3r {
|
|||
|
||||
bool _load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle);
|
||||
bool _extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
bool _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename);
|
||||
void _extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename);
|
||||
bool _extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model);
|
||||
|
||||
// handlers to parse the .model file
|
||||
void _handle_start_model_xml_element(const char* name, const char** attributes);
|
||||
void _handle_end_model_xml_element(const char* name);
|
||||
void _handle_model_xml_characters(const XML_Char* s, int len);
|
||||
|
||||
// handlers to parse the MODEL_CONFIG_FILE file
|
||||
void _handle_start_config_xml_element(const char* name, const char** attributes);
|
||||
|
@ -386,6 +402,9 @@ namespace Slic3r {
|
|||
bool _handle_start_item(const char** attributes, unsigned int num_attributes);
|
||||
bool _handle_end_item();
|
||||
|
||||
bool _handle_start_metadata(const char** attributes, unsigned int num_attributes);
|
||||
bool _handle_end_metadata();
|
||||
|
||||
bool _create_object_instance(int object_id, const Matrix4x4& matrix, unsigned int recur_counter);
|
||||
|
||||
void _apply_transform(ModelInstance& instance, const Matrix4x4& matrix);
|
||||
|
@ -407,6 +426,7 @@ namespace Slic3r {
|
|||
// callbacks to parse the .model file
|
||||
static void XMLCALL _handle_start_model_xml_element(void* userData, const char* name, const char** attributes);
|
||||
static void XMLCALL _handle_end_model_xml_element(void* userData, const char* name);
|
||||
static void XMLCALL _handle_model_xml_characters(void* userData, const XML_Char* s, int len);
|
||||
|
||||
// callbacks to parse the MODEL_CONFIG_FILE file
|
||||
static void XMLCALL _handle_start_config_xml_element(void* userData, const char* name, const char** attributes);
|
||||
|
@ -414,9 +434,12 @@ namespace Slic3r {
|
|||
};
|
||||
|
||||
_3MF_Importer::_3MF_Importer()
|
||||
: m_xml_parser(nullptr)
|
||||
: m_version(0)
|
||||
, m_xml_parser(nullptr)
|
||||
, m_model(nullptr)
|
||||
, m_unit_factor(1.0f)
|
||||
, m_curr_metadata_name("")
|
||||
, m_curr_characters("")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -427,6 +450,7 @@ namespace Slic3r {
|
|||
|
||||
bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, PresetBundle& bundle)
|
||||
{
|
||||
m_version = 0;
|
||||
m_model = &model;
|
||||
m_unit_factor = 1.0f;
|
||||
m_curr_object.reset();
|
||||
|
@ -437,6 +461,9 @@ namespace Slic3r {
|
|||
m_curr_config.object_id = -1;
|
||||
m_curr_config.volume_id = -1;
|
||||
m_objects_metadata.clear();
|
||||
m_layer_heights_profiles.clear();
|
||||
m_curr_metadata_name.clear();
|
||||
m_curr_characters.clear();
|
||||
clear_errors();
|
||||
|
||||
return _load_model_from_file(filename, model, bundle);
|
||||
|
@ -472,6 +499,8 @@ namespace Slic3r {
|
|||
mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
|
||||
|
||||
mz_zip_archive_file_stat stat;
|
||||
|
||||
// we first loop the entries to read from the archive the .model file only, in order to extract the version from it
|
||||
for (mz_uint i = 0; i < num_entries; ++i)
|
||||
{
|
||||
if (mz_zip_reader_file_stat(&archive, i, &stat))
|
||||
|
@ -489,15 +518,26 @@ namespace Slic3r {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we then loop again the entries to read other files stored in the archive
|
||||
for (mz_uint i = 0; i < num_entries; ++i)
|
||||
{
|
||||
if (mz_zip_reader_file_stat(&archive, i, &stat))
|
||||
{
|
||||
std::string name(stat.m_filename);
|
||||
std::replace(name.begin(), name.end(), '\\', '/');
|
||||
|
||||
if (boost::algorithm::iequals(name, LAYER_HEIGHTS_PROFILE_FILE))
|
||||
{
|
||||
// extract slic3r lazer heights profile file
|
||||
_extract_layer_heights_profile_config_from_archive(archive, stat);
|
||||
}
|
||||
else if (boost::algorithm::iequals(name, PRINT_CONFIG_FILE))
|
||||
{
|
||||
// extract slic3r print config file
|
||||
if (!_extract_print_config_from_archive(archive, stat, bundle, filename))
|
||||
{
|
||||
mz_zip_reader_end(&archive);
|
||||
add_error("Archive does not contain a valid print config");
|
||||
return false;
|
||||
}
|
||||
_extract_print_config_from_archive(archive, stat, bundle, filename);
|
||||
}
|
||||
else if (boost::algorithm::iequals(name, MODEL_CONFIG_FILE))
|
||||
{
|
||||
|
@ -526,6 +566,13 @@ namespace Slic3r {
|
|||
return false;
|
||||
}
|
||||
|
||||
IdToLayerHeightsProfileMap::iterator obj_layer_heights_profile = m_layer_heights_profiles.find(object.first);
|
||||
if (obj_layer_heights_profile != m_layer_heights_profiles.end())
|
||||
{
|
||||
object.second->layer_height_profile = obj_layer_heights_profile->second;
|
||||
object.second->layer_height_profile_valid = true;
|
||||
}
|
||||
|
||||
IdToMetadataMap::iterator obj_metadata = m_objects_metadata.find(object.first);
|
||||
if (obj_metadata != m_objects_metadata.end())
|
||||
{
|
||||
|
@ -583,6 +630,7 @@ namespace Slic3r {
|
|||
|
||||
XML_SetUserData(m_xml_parser, (void*)this);
|
||||
XML_SetElementHandler(m_xml_parser, _3MF_Importer::_handle_start_model_xml_element, _3MF_Importer::_handle_end_model_xml_element);
|
||||
XML_SetCharacterDataHandler(m_xml_parser, _3MF_Importer::_handle_model_xml_characters);
|
||||
|
||||
void* parser_buffer = XML_GetBuffer(m_xml_parser, (int)stat.m_uncomp_size);
|
||||
if (parser_buffer == nullptr)
|
||||
|
@ -609,23 +657,90 @@ namespace Slic3r {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename)
|
||||
void _3MF_Importer::_extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, PresetBundle& bundle, const std::string& archive_filename)
|
||||
{
|
||||
if (stat.m_uncomp_size > 0)
|
||||
{
|
||||
std::vector<char> buffer((size_t)stat.m_uncomp_size + 1, 0);
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0)
|
||||
{
|
||||
add_error("Error while reading config data to buffer");
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.back() = '\0';
|
||||
bundle.load_config_string(buffer.data(), archive_filename.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
void _3MF_Importer::_extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat)
|
||||
{
|
||||
if (stat.m_uncomp_size > 0)
|
||||
{
|
||||
std::string buffer((size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (void*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0)
|
||||
{
|
||||
add_error("Error while reading layer heights profile data to buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer.back() == '\n')
|
||||
buffer.pop_back();
|
||||
|
||||
std::vector<std::string> objects;
|
||||
boost::split(objects, buffer, boost::is_any_of("\n"), boost::token_compress_off);
|
||||
|
||||
for (const std::string& object : objects)
|
||||
{
|
||||
std::vector<std::string> object_data;
|
||||
boost::split(object_data, object, boost::is_any_of("|"), boost::token_compress_off);
|
||||
if (object_data.size() != 2)
|
||||
{
|
||||
add_error("Error while reading object data");
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> object_data_id;
|
||||
boost::split(object_data_id, object_data[0], boost::is_any_of("="), boost::token_compress_off);
|
||||
if (object_data_id.size() != 2)
|
||||
{
|
||||
add_error("Error while reading object id");
|
||||
continue;
|
||||
}
|
||||
|
||||
int object_id = std::atoi(object_data_id[1].c_str());
|
||||
if (object_id == 0)
|
||||
{
|
||||
add_error("Found invalid object id");
|
||||
continue;
|
||||
}
|
||||
|
||||
IdToLayerHeightsProfileMap::iterator object_item = m_layer_heights_profiles.find(object_id);
|
||||
if (object_item != m_layer_heights_profiles.end())
|
||||
{
|
||||
add_error("Found duplicated layer heights profile");
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> object_data_profile;
|
||||
boost::split(object_data_profile, object_data[1], boost::is_any_of(";"), boost::token_compress_off);
|
||||
if ((object_data_profile.size() <= 4) || (object_data_profile.size() % 2 != 0))
|
||||
{
|
||||
add_error("Found invalid layer heights profile");
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<coordf_t> profile;
|
||||
profile.reserve(object_data_profile.size());
|
||||
|
||||
for (const std::string& value : object_data_profile)
|
||||
{
|
||||
profile.push_back((coordf_t)std::atof(value.c_str()));
|
||||
}
|
||||
|
||||
m_layer_heights_profiles.insert(IdToLayerHeightsProfileMap::value_type(object_id, profile));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_extract_model_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model)
|
||||
|
@ -705,6 +820,8 @@ namespace Slic3r {
|
|||
res = _handle_start_build(attributes, num_attributes);
|
||||
else if (::strcmp(ITEM_TAG, name) == 0)
|
||||
res = _handle_start_item(attributes, num_attributes);
|
||||
else if (::strcmp(METADATA_TAG, name) == 0)
|
||||
res = _handle_start_metadata(attributes, num_attributes);
|
||||
|
||||
if (!res)
|
||||
_stop_xml_parser();
|
||||
|
@ -741,11 +858,18 @@ namespace Slic3r {
|
|||
res = _handle_end_build();
|
||||
else if (::strcmp(ITEM_TAG, name) == 0)
|
||||
res = _handle_end_item();
|
||||
else if (::strcmp(METADATA_TAG, name) == 0)
|
||||
res = _handle_end_metadata();
|
||||
|
||||
if (!res)
|
||||
_stop_xml_parser();
|
||||
}
|
||||
|
||||
void _3MF_Importer::_handle_model_xml_characters(const XML_Char* s, int len)
|
||||
{
|
||||
m_curr_characters.append(s, len);
|
||||
}
|
||||
|
||||
void _3MF_Importer::_handle_start_config_xml_element(const char* name, const char** attributes)
|
||||
{
|
||||
if (m_xml_parser == nullptr)
|
||||
|
@ -1052,6 +1176,25 @@ namespace Slic3r {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_handle_start_metadata(const char** attributes, unsigned int num_attributes)
|
||||
{
|
||||
m_curr_characters.clear();
|
||||
|
||||
std::string name = get_attribute_value_string(attributes, num_attributes, NAME_ATTR);
|
||||
if (!name.empty())
|
||||
m_curr_metadata_name = name;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_handle_end_metadata()
|
||||
{
|
||||
if (m_curr_metadata_name == SLIC3RPE_3MF_VERSION)
|
||||
m_version = (unsigned int)atoi(m_curr_characters.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Importer::_create_object_instance(int object_id, const Matrix4x4& matrix, unsigned int recur_counter)
|
||||
{
|
||||
static const unsigned int MAX_RECURSIONS = 10;
|
||||
|
@ -1358,6 +1501,13 @@ namespace Slic3r {
|
|||
importer->_handle_end_model_xml_element(name);
|
||||
}
|
||||
|
||||
void XMLCALL _3MF_Importer::_handle_model_xml_characters(void* userData, const XML_Char* s, int len)
|
||||
{
|
||||
_3MF_Importer* importer = (_3MF_Importer*)userData;
|
||||
if (importer != nullptr)
|
||||
importer->_handle_model_xml_characters(s, len);
|
||||
}
|
||||
|
||||
void XMLCALL _3MF_Importer::_handle_start_config_xml_element(void* userData, const char* name, const char** attributes)
|
||||
{
|
||||
_3MF_Importer* importer = (_3MF_Importer*)userData;
|
||||
|
@ -1429,6 +1579,7 @@ namespace Slic3r {
|
|||
bool _add_object_to_model_stream(std::stringstream& stream, unsigned int& object_id, ModelObject& object, BuildItemsList& build_items, VolumeToOffsetsMap& volumes_offsets);
|
||||
bool _add_mesh_to_object_stream(std::stringstream& stream, ModelObject& object, VolumeToOffsetsMap& volumes_offsets);
|
||||
bool _add_build_to_model_stream(std::stringstream& stream, const BuildItemsList& build_items);
|
||||
bool _add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model);
|
||||
bool _add_print_config_file_to_archive(mz_zip_archive& archive, const Print& print);
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model);
|
||||
};
|
||||
|
@ -1477,6 +1628,14 @@ namespace Slic3r {
|
|||
return false;
|
||||
}
|
||||
|
||||
// adds layer height profile file
|
||||
if (!_add_layer_height_profile_file_to_archive(archive, model))
|
||||
{
|
||||
mz_zip_writer_end(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
// adds slic3r print config file
|
||||
if (export_print_config)
|
||||
{
|
||||
|
@ -1552,7 +1711,8 @@ namespace Slic3r {
|
|||
{
|
||||
std::stringstream stream;
|
||||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">\n";
|
||||
stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:slic3rpe=\"http://schemas.slic3r.org/3mf/2017/06\">\n";
|
||||
stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "</" << METADATA_TAG << ">\n";
|
||||
stream << " <" << RESOURCES_TAG << ">\n";
|
||||
|
||||
BuildItemsList build_items;
|
||||
|
@ -1736,6 +1896,44 @@ namespace Slic3r {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Exporter::_add_layer_height_profile_file_to_archive(mz_zip_archive& archive, Model& model)
|
||||
{
|
||||
std::string out = "";
|
||||
char buffer[1024];
|
||||
|
||||
unsigned int count = 0;
|
||||
for (const ModelObject* object : model.objects)
|
||||
{
|
||||
++count;
|
||||
std::vector<double> layer_height_profile = object->layer_height_profile_valid ? object->layer_height_profile : std::vector<double>();
|
||||
if ((layer_height_profile.size() >= 4) && ((layer_height_profile.size() % 2) == 0))
|
||||
{
|
||||
sprintf(buffer, "object_id=%d|", count);
|
||||
out += buffer;
|
||||
|
||||
// Store the layer height profile as a single semicolon separated list.
|
||||
for (size_t i = 0; i < layer_height_profile.size(); ++i)
|
||||
{
|
||||
sprintf(buffer, (i == 0) ? "%f" : ";%f", layer_height_profile[i]);
|
||||
out += buffer;
|
||||
}
|
||||
|
||||
out += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!out.empty())
|
||||
{
|
||||
if (!mz_zip_writer_add_mem(&archive, LAYER_HEIGHTS_PROFILE_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
||||
{
|
||||
add_error("Unable to add layer heights profile file to archive");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _3MF_Exporter::_add_print_config_file_to_archive(mz_zip_archive& archive, const Print& print)
|
||||
{
|
||||
char buffer[1024];
|
||||
|
@ -1744,10 +1942,13 @@ namespace Slic3r {
|
|||
|
||||
GCode::append_full_config(print, out);
|
||||
|
||||
if (!mz_zip_writer_add_mem(&archive, PRINT_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
||||
if (!out.empty())
|
||||
{
|
||||
add_error("Unable to add print config file to archive");
|
||||
return false;
|
||||
if (!mz_zip_writer_add_mem(&archive, PRINT_CONFIG_FILE.c_str(), (const void*)out.data(), out.length(), MZ_DEFAULT_COMPRESSION))
|
||||
{
|
||||
add_error("Unable to add print config file to archive");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1832,10 +2033,7 @@ namespace Slic3r {
|
|||
|
||||
_3MF_Importer importer;
|
||||
bool res = importer.load_model_from_file(path, *model, *bundle);
|
||||
|
||||
if (!res)
|
||||
importer.log_errors();
|
||||
|
||||
importer.log_errors();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
// VERSION NUMBERS
|
||||
// 0 : .amf, .amf.xml and .zip.amf files saved by older slic3r. No version definition in them.
|
||||
// 1 : Introduction of amf versioning. No other change in data saved into amf files.
|
||||
const unsigned int VERSION_AMF = 1;
|
||||
const char* SLIC3RPE_AMF_VERSION = "slic3rpe_amf_version";
|
||||
|
||||
const char* SLIC3R_CONFIG_TYPE = "slic3rpe_config";
|
||||
|
||||
namespace Slic3r
|
||||
|
@ -32,6 +38,7 @@ namespace Slic3r
|
|||
struct AMFParserContext
|
||||
{
|
||||
AMFParserContext(XML_Parser parser, const std::string& archive_filename, PresetBundle* preset_bundle, Model *model) :
|
||||
m_version(0),
|
||||
m_parser(parser),
|
||||
m_model(*model),
|
||||
m_object(nullptr),
|
||||
|
@ -137,6 +144,8 @@ struct AMFParserContext
|
|||
std::vector<Instance> instances;
|
||||
};
|
||||
|
||||
// Version of the amf file
|
||||
unsigned int m_version;
|
||||
// Current Expat XML parser instance.
|
||||
XML_Parser m_parser;
|
||||
// Model to receive objects extracted from an AMF file.
|
||||
|
@ -360,9 +369,9 @@ void AMFParserContext::endElement(const char * /* name */)
|
|||
case NODE_TYPE_VERTEX:
|
||||
assert(m_object);
|
||||
// Parse the vertex data
|
||||
m_object_vertices.emplace_back(atof(m_value[0].c_str()));
|
||||
m_object_vertices.emplace_back(atof(m_value[1].c_str()));
|
||||
m_object_vertices.emplace_back(atof(m_value[2].c_str()));
|
||||
m_object_vertices.emplace_back((float)atof(m_value[0].c_str()));
|
||||
m_object_vertices.emplace_back((float)atof(m_value[1].c_str()));
|
||||
m_object_vertices.emplace_back((float)atof(m_value[2].c_str()));
|
||||
m_value[0].clear();
|
||||
m_value[1].clear();
|
||||
m_value[2].clear();
|
||||
|
@ -462,6 +471,10 @@ void AMFParserContext::endElement(const char * /* name */)
|
|||
if (m_volume && m_value[0] == "name")
|
||||
m_volume->name = std::move(m_value[1]);
|
||||
}
|
||||
else if (strncmp(m_value[0].c_str(), SLIC3RPE_AMF_VERSION, strlen(SLIC3RPE_AMF_VERSION)) == 0) {
|
||||
m_version = (unsigned int)atoi(m_value[1].c_str());
|
||||
}
|
||||
|
||||
m_value[0].clear();
|
||||
m_value[1].clear();
|
||||
break;
|
||||
|
@ -543,46 +556,8 @@ bool load_amf_file(const char *path, PresetBundle* bundle, Model *model)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Load an AMF archive into a provided model.
|
||||
bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model)
|
||||
bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, const char* path, PresetBundle* bundle, Model* model, unsigned int& version)
|
||||
{
|
||||
if ((path == nullptr) || (model == nullptr))
|
||||
return false;
|
||||
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
mz_bool res = mz_zip_reader_init_file(&archive, path, 0);
|
||||
if (res == 0)
|
||||
{
|
||||
printf("Unable to init zip reader\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
|
||||
if (num_entries != 1)
|
||||
{
|
||||
printf("Found invalid number of entries\n");
|
||||
mz_zip_reader_end(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_zip_archive_file_stat stat;
|
||||
res = mz_zip_reader_file_stat(&archive, 0, &stat);
|
||||
if (res == 0)
|
||||
{
|
||||
printf("Unable to extract entry statistics\n");
|
||||
mz_zip_reader_end(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!boost::iends_with(stat.m_filename, ".amf"))
|
||||
{
|
||||
printf("Found invalid internal filename\n");
|
||||
mz_zip_reader_end(&archive);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stat.m_uncomp_size == 0)
|
||||
{
|
||||
printf("Found invalid size\n");
|
||||
|
@ -610,7 +585,7 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model)
|
|||
return false;
|
||||
}
|
||||
|
||||
res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0);
|
||||
mz_bool res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, parser_buffer, (size_t)stat.m_uncomp_size, 0);
|
||||
if (res == 0)
|
||||
{
|
||||
printf("Error while reading model data to buffer\n");
|
||||
|
@ -627,6 +602,62 @@ bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model)
|
|||
|
||||
ctx.endDocument();
|
||||
|
||||
version = ctx.m_version;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Load an AMF archive into a provided model.
|
||||
bool load_amf_archive(const char *path, PresetBundle* bundle, Model *model)
|
||||
{
|
||||
if ((path == nullptr) || (model == nullptr))
|
||||
return false;
|
||||
|
||||
unsigned int version = 0;
|
||||
|
||||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
|
||||
mz_bool res = mz_zip_reader_init_file(&archive, path, 0);
|
||||
if (res == 0)
|
||||
{
|
||||
printf("Unable to init zip reader\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
mz_uint num_entries = mz_zip_reader_get_num_files(&archive);
|
||||
|
||||
mz_zip_archive_file_stat stat;
|
||||
// we first loop the entries to read from the archive the .amf file only, in order to extract the version from it
|
||||
for (mz_uint i = 0; i < num_entries; ++i)
|
||||
{
|
||||
if (mz_zip_reader_file_stat(&archive, i, &stat))
|
||||
{
|
||||
if (boost::iends_with(stat.m_filename, ".amf"))
|
||||
{
|
||||
if (!extract_model_from_archive(archive, stat, path, bundle, model, version))
|
||||
{
|
||||
mz_zip_reader_end(&archive);
|
||||
printf("Archive does not contain a valid model");
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // forward compatibility
|
||||
// we then loop again the entries to read other files stored in the archive
|
||||
for (mz_uint i = 0; i < num_entries; ++i)
|
||||
{
|
||||
if (mz_zip_reader_file_stat(&archive, i, &stat))
|
||||
{
|
||||
// add code to extract the file
|
||||
}
|
||||
}
|
||||
#endif // forward compatibility
|
||||
|
||||
mz_zip_reader_end(&archive);
|
||||
return true;
|
||||
}
|
||||
|
@ -664,6 +695,7 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
|
|||
stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
stream << "<amf unit=\"millimeter\">\n";
|
||||
stream << "<metadata type=\"cad\">Slic3r " << SLIC3R_VERSION << "</metadata>\n";
|
||||
stream << "<metadata type=\"" << SLIC3RPE_AMF_VERSION << "\">" << VERSION_AMF << "</metadata>\n";
|
||||
|
||||
if (export_print_config)
|
||||
{
|
||||
|
|
|
@ -718,10 +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.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);
|
||||
preview_data.ranges.height.update_from(height_range);
|
||||
preview_data.ranges.width.update_from(width_range);
|
||||
preview_data.ranges.feedrate.update_from(feedrate_range);
|
||||
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
||||
|
@ -790,9 +790,9 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
|
|||
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);
|
||||
preview_data.ranges.height.update_from(height_range);
|
||||
preview_data.ranges.width.update_from(width_range);
|
||||
preview_data.ranges.feedrate.update_from(feedrate_range);
|
||||
}
|
||||
|
||||
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,13 +9,17 @@ namespace Slic3r {
|
|||
|
||||
class GCode;
|
||||
class Layer;
|
||||
class PerExtruderAdjustments;
|
||||
|
||||
/*
|
||||
A standalone G-code filter, to control cooling of the print.
|
||||
The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited
|
||||
and the print is modified to stretch over a minimum layer time.
|
||||
*/
|
||||
|
||||
// A standalone G-code filter, to control cooling of the print.
|
||||
// The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited
|
||||
// and the print is modified to stretch over a minimum layer time.
|
||||
//
|
||||
// The simple it sounds, the actual implementation is significantly more complex.
|
||||
// Namely, for a multi-extruder print, each material may require a different cooling logic.
|
||||
// For example, some materials may not like to print too slowly, while with some materials
|
||||
// we may slow down significantly.
|
||||
//
|
||||
class CoolingBuffer {
|
||||
public:
|
||||
CoolingBuffer(GCode &gcodegen);
|
||||
|
@ -25,7 +29,12 @@ public:
|
|||
GCode* gcodegen() { return &m_gcodegen; }
|
||||
|
||||
private:
|
||||
CoolingBuffer& operator=(const CoolingBuffer&);
|
||||
CoolingBuffer& operator=(const CoolingBuffer&) = delete;
|
||||
std::vector<PerExtruderAdjustments> parse_layer_gcode(const std::string &gcode, std::vector<float> ¤t_pos) const;
|
||||
float calculate_layer_slowdown(std::vector<PerExtruderAdjustments> &per_extruder_adjustments);
|
||||
// Apply slow down over G-code lines stored in per_extruder_adjustments, enable fan if needed.
|
||||
// Returns the adjusted G-code.
|
||||
std::string apply_layer_cooldown(const std::string &gcode, size_t layer_id, float layer_time, std::vector<PerExtruderAdjustments> &per_extruder_adjustments);
|
||||
|
||||
GCode& m_gcodegen;
|
||||
std::string m_gcode;
|
||||
|
@ -34,6 +43,9 @@ private:
|
|||
std::vector<char> m_axis;
|
||||
std::vector<float> m_current_pos;
|
||||
unsigned int m_current_extruder;
|
||||
|
||||
// Old logic: proportional.
|
||||
bool m_cooling_logic_proportional = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -99,17 +99,31 @@ void GCodePreviewData::Range::set_from(const Range& other)
|
|||
|
||||
float GCodePreviewData::Range::step_size() const
|
||||
{
|
||||
return (max - min) / (float)Colors_Count;
|
||||
return (max - min) / (float)(Colors_Count - 1);
|
||||
}
|
||||
|
||||
const GCodePreviewData::Color& GCodePreviewData::Range::get_color_at_max() const
|
||||
GCodePreviewData::Color GCodePreviewData::Range::get_color_at(float value) const
|
||||
{
|
||||
return colors[Colors_Count - 1];
|
||||
}
|
||||
if (empty())
|
||||
return Color::Dummy;
|
||||
|
||||
const GCodePreviewData::Color& GCodePreviewData::Range::get_color_at(float value) const
|
||||
{
|
||||
return empty() ? get_color_at_max() : colors[clamp((unsigned int)0, Colors_Count - 1, (unsigned int)((value - min) / step_size()))];
|
||||
float global_t = (value - min) / step_size();
|
||||
|
||||
unsigned int low = (unsigned int)global_t;
|
||||
unsigned int high = clamp((unsigned int)0, Colors_Count - 1, low + 1);
|
||||
|
||||
Color color_low = colors[low];
|
||||
Color color_high = colors[high];
|
||||
|
||||
float local_t = global_t - (float)low;
|
||||
|
||||
// interpolate in RGB space
|
||||
Color ret;
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
ret.rgba[i] = lerp(color_low.rgba[i], color_high.rgba[i], local_t);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
GCodePreviewData::LegendItem::LegendItem(const std::string& text, const GCodePreviewData::Color& color)
|
||||
|
@ -266,22 +280,22 @@ const GCodePreviewData::Color& GCodePreviewData::get_extrusion_role_color(Extrus
|
|||
return extrusion.role_colors[role];
|
||||
}
|
||||
|
||||
const GCodePreviewData::Color& GCodePreviewData::get_height_color(float height) const
|
||||
GCodePreviewData::Color GCodePreviewData::get_height_color(float height) const
|
||||
{
|
||||
return ranges.height.get_color_at(height);
|
||||
}
|
||||
|
||||
const GCodePreviewData::Color& GCodePreviewData::get_width_color(float width) const
|
||||
GCodePreviewData::Color GCodePreviewData::get_width_color(float width) const
|
||||
{
|
||||
return ranges.width.get_color_at(width);
|
||||
}
|
||||
|
||||
const GCodePreviewData::Color& GCodePreviewData::get_feedrate_color(float feedrate) const
|
||||
GCodePreviewData::Color GCodePreviewData::get_feedrate_color(float feedrate) const
|
||||
{
|
||||
return ranges.feedrate.get_color_at(feedrate);
|
||||
}
|
||||
|
||||
const GCodePreviewData::Color& GCodePreviewData::get_volumetric_rate_color(float rate) const
|
||||
GCodePreviewData::Color GCodePreviewData::get_volumetric_rate_color(float rate) const
|
||||
{
|
||||
return ranges.volumetric_rate.get_color_at(rate);
|
||||
}
|
||||
|
@ -370,10 +384,10 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
|
|||
list.reserve(Range::Colors_Count);
|
||||
|
||||
float step = range.step_size();
|
||||
for (unsigned int i = 0; i < Range::Colors_Count; ++i)
|
||||
for (int i = Range::Colors_Count - 1; i >= 0; --i)
|
||||
{
|
||||
char buf[1024];
|
||||
sprintf(buf, "%.*f/%.*f", decimals, scale_factor * (range.min + (float)i * step), decimals, scale_factor * (range.min + (float)(i + 1) * step));
|
||||
sprintf(buf, "%.*f", decimals, scale_factor * (range.min + (float)i * step));
|
||||
list.emplace_back(buf, range.colors[i]);
|
||||
}
|
||||
}
|
||||
|
@ -408,7 +422,7 @@ GCodePreviewData::LegendItemsList GCodePreviewData::get_legend_items(const std::
|
|||
}
|
||||
case Extrusion::Feedrate:
|
||||
{
|
||||
Helper::FillListFromRange(items, ranges.feedrate, 0, 1.0f);
|
||||
Helper::FillListFromRange(items, ranges.feedrate, 1, 1.0f);
|
||||
break;
|
||||
}
|
||||
case Extrusion::VolumetricRate:
|
||||
|
|
|
@ -41,8 +41,7 @@ public:
|
|||
void set_from(const Range& other);
|
||||
float step_size() const;
|
||||
|
||||
const Color& get_color_at(float value) const;
|
||||
const Color& get_color_at_max() const;
|
||||
Color get_color_at(float value) const;
|
||||
};
|
||||
|
||||
struct Ranges
|
||||
|
@ -189,10 +188,10 @@ public:
|
|||
bool empty() const;
|
||||
|
||||
const Color& get_extrusion_role_color(ExtrusionRole role) 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;
|
||||
Color get_height_color(float height) const;
|
||||
Color get_width_color(float width) const;
|
||||
Color get_feedrate_color(float feedrate) 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);
|
||||
|
|
|
@ -598,10 +598,10 @@ std::string Print::validate() const
|
|||
return "The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).";
|
||||
SlicingParameters slicing_params0 = this->objects.front()->slicing_parameters();
|
||||
|
||||
const PrintObject* most_layered_object = this->objects.front(); // object with highest layer_height_profile.size() encountered so far
|
||||
const PrintObject* tallest_object = this->objects.front(); // let's find the tallest object
|
||||
for (const auto* object : objects)
|
||||
if (object->layer_height_profile.size() > most_layered_object->layer_height_profile.size())
|
||||
most_layered_object = object;
|
||||
if (*(object->layer_height_profile.end()-2) > *(tallest_object->layer_height_profile.end()-2) )
|
||||
tallest_object = object;
|
||||
|
||||
for (PrintObject *object : this->objects) {
|
||||
SlicingParameters slicing_params = object->slicing_parameters();
|
||||
|
@ -618,17 +618,26 @@ std::string Print::validate() const
|
|||
object->update_layer_height_profile();
|
||||
object->layer_height_profile_valid = was_layer_height_profile_valid;
|
||||
|
||||
if ( this->config.variable_layer_height ) {
|
||||
int i = 0;
|
||||
while ( i < object->layer_height_profile.size() ) {
|
||||
if (std::abs(most_layered_object->layer_height_profile[i] - object->layer_height_profile[i]) > EPSILON)
|
||||
return "The Wipe tower is only supported if all objects have the same layer height profile";
|
||||
++i;
|
||||
if (i == object->layer_height_profile.size()-2) // this element contains the objects max z, if the other object is taller,
|
||||
// it does not have to match - we will step over it
|
||||
if (most_layered_object->layer_height_profile[i] > object->layer_height_profile[i])
|
||||
++i;
|
||||
if ( this->config.variable_layer_height ) { // comparing layer height profiles
|
||||
bool failed = false;
|
||||
if (tallest_object->layer_height_profile.size() >= object->layer_height_profile.size() ) {
|
||||
int i = 0;
|
||||
while ( i < object->layer_height_profile.size() && i < tallest_object->layer_height_profile.size()) {
|
||||
if (std::abs(tallest_object->layer_height_profile[i] - object->layer_height_profile[i])) {
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
if (i == object->layer_height_profile.size()-2) // this element contains this objects max z
|
||||
if (tallest_object->layer_height_profile[i] > object->layer_height_profile[i]) // the difference does not matter in this case
|
||||
++i;
|
||||
}
|
||||
}
|
||||
else
|
||||
failed = true;
|
||||
|
||||
if (failed)
|
||||
return "The Wipe tower is only supported if all objects have the same layer height profile";
|
||||
}
|
||||
|
||||
/*for (size_t i = 5; i < object->layer_height_profile.size(); i += 2)
|
||||
|
|
|
@ -1679,7 +1679,7 @@ PrintConfigDef::PrintConfigDef()
|
|||
"temperature control commands in the output.");
|
||||
def->cli = "temperature=i@";
|
||||
def->full_label = L("Temperature");
|
||||
def->max = 0;
|
||||
def->min = 0;
|
||||
def->max = max_temp;
|
||||
def->default_value = new ConfigOptionInts { 200 };
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <locale>
|
||||
|
||||
#include "libslic3r.h"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
extern void set_logging_level(unsigned int level);
|
||||
|
@ -60,6 +62,9 @@ extern std::string timestamp_str();
|
|||
// to be placed at the top of Slic3r generated files.
|
||||
inline std::string header_slic3r_generated() { return std::string("generated by " SLIC3R_FORK_NAME " " SLIC3R_VERSION " " ) + timestamp_str(); }
|
||||
|
||||
// getpid platform wrapper
|
||||
extern unsigned get_current_pid();
|
||||
|
||||
// Compute the next highest power of 2 of 32-bit v
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
template<typename T>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <boost/thread.hpp>
|
||||
|
||||
#define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
|
||||
#define SLIC3R_VERSION "1.39.0"
|
||||
#define SLIC3R_VERSION "1.40.0"
|
||||
#define SLIC3R_BUILD "UNKNOWN"
|
||||
|
||||
typedef int32_t coord_t;
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#include <locale>
|
||||
#include <ctime>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <boost/log/core.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/log/expressions.hpp>
|
||||
|
@ -271,4 +277,13 @@ std::string timestamp_str()
|
|||
return buf;
|
||||
}
|
||||
|
||||
unsigned get_current_pid()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return GetCurrentProcessId();
|
||||
#else
|
||||
return ::getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue