mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-17 11:47:54 -06:00
Merge remote-tracking branch 'remote/master' into feature/merge_upstream
# Conflicts: # bbl/i18n/OrcaSlicer.pot # bbl/i18n/de/OrcaSlicer_de.po # bbl/i18n/en/OrcaSlicer_en.po # bbl/i18n/es/OrcaSlicer_es.po # bbl/i18n/fr/OrcaSlicer_fr.po # bbl/i18n/hu/OrcaSlicer_hu.po # bbl/i18n/it/OrcaSlicer_it.po # bbl/i18n/ja/OrcaSlicer_ja.po # bbl/i18n/nl/OrcaSlicer_nl.po # bbl/i18n/sv/OrcaSlicer_sv.po # bbl/i18n/zh_cn/OrcaSlicer_zh_CN.po # resources/config.json # resources/i18n/de/BambuStudio.mo # resources/i18n/en/BambuStudio.mo # resources/i18n/es/BambuStudio.mo # resources/i18n/fr/BambuStudio.mo # resources/i18n/hu/BambuStudio.mo # resources/i18n/it/BambuStudio.mo # resources/i18n/ja/OrcaSlicer.mo # resources/i18n/nl/BambuStudio.mo # resources/i18n/sv/BambuStudio.mo # resources/i18n/zh_cn/BambuStudio.mo # resources/images/ams_humidity_2.svg # resources/images/ams_humidity_3.svg # resources/images/ams_humidity_4.svg # resources/images/ams_humidity_tips.svg # resources/images/monitor_state_on.svg # resources/images/sdcard_state_normal.svg # resources/profiles/BBL.json # resources/profiles/BBL/filament/Bambu PETG-CF @base.json # resources/profiles/BBL/filament/Generic PETG-CF @base.json # resources/profiles/BBL/machine/Bambu Lab P1P 0.4 nozzle.json # resources/web/data/text.js # resources/web/guide/3/index.html # resources/web/guide/31/index.html # src/BambuStudio.cpp # src/libslic3r/AABBTreeLines.hpp # src/libslic3r/Brim.cpp # src/libslic3r/CMakeLists.txt # src/libslic3r/ExPolygon.hpp # src/libslic3r/Fill/FillBase.hpp # src/libslic3r/Format/bbs_3mf.cpp # src/libslic3r/GCodeWriter.cpp # src/libslic3r/Line.hpp # src/libslic3r/PerimeterGenerator.cpp # src/libslic3r/Preset.cpp # src/libslic3r/Print.cpp # src/libslic3r/Print.hpp # src/libslic3r/PrintConfig.cpp # src/libslic3r/PrintConfig.hpp # src/libslic3r/TreeSupport.cpp # src/slic3r/GUI/AmsMappingPopup.cpp # src/slic3r/GUI/BackgroundSlicingProcess.cpp # src/slic3r/GUI/ConfigManipulation.cpp # src/slic3r/GUI/GCodeViewer.cpp # src/slic3r/GUI/GCodeViewer.hpp # src/slic3r/GUI/GLCanvas3D.cpp # src/slic3r/GUI/GUI_App.cpp # src/slic3r/GUI/MainFrame.cpp # src/slic3r/GUI/PartPlate.cpp # src/slic3r/GUI/Plater.cpp # src/slic3r/GUI/Preferences.cpp # src/slic3r/GUI/SelectMachine.cpp # src/slic3r/GUI/Widgets/AMSControl.cpp # src/slic3r/GUI/wxMediaCtrl2.cpp # src/slic3r/Utils/Process.cpp # version.inc
This commit is contained in:
commit
9f598046d1
658 changed files with 70312 additions and 4877 deletions
|
@ -110,6 +110,7 @@ const std::string BBS_SEAM_PAINTING_VERSION = "BambuStudio:SeamPaintingV
|
|||
const std::string BBS_MM_PAINTING_VERSION = "BambuStudio:MmPaintingVersion";
|
||||
const std::string BBL_MODEL_ID_TAG = "model_id";
|
||||
const std::string BBL_MODEL_NAME_TAG = "Title";
|
||||
const std::string BBL_ORIGIN_TAG = "Origin";
|
||||
const std::string BBL_DESIGNER_TAG = "Designer";
|
||||
const std::string BBL_DESIGNER_USER_ID_TAG = "DesignerUserId";
|
||||
const std::string BBL_DESIGNER_COVER_FILE_TAG = "DesignerCover";
|
||||
|
@ -121,6 +122,12 @@ const std::string BBL_MODIFICATION_TAG = "ModificationDate";
|
|||
const std::string BBL_CREATION_DATE_TAG = "CreationDate";
|
||||
const std::string BBL_APPLICATION_TAG = "Application";
|
||||
|
||||
const std::string BBL_PROFILE_TITLE_TAG = "ProfileTitle";
|
||||
const std::string BBL_PROFILE_COVER_TAG = "ProfileCover";
|
||||
const std::string BBL_PROFILE_DESCRIPTION_TAG = "ProfileDescription";
|
||||
const std::string BBL_PROFILE_USER_ID_TAG = "ProfileUserId";
|
||||
const std::string BBL_PROFILE_USER_NAME_TAG = "ProfileUserName";
|
||||
|
||||
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
|
||||
|
@ -156,7 +163,7 @@ const std::string PROJECT_EMBEDDED_PRINT_PRESETS_FILE = "Metadata/print_setting_
|
|||
const std::string PROJECT_EMBEDDED_SLICE_PRESETS_FILE = "Metadata/process_settings_";
|
||||
const std::string PROJECT_EMBEDDED_FILAMENT_PRESETS_FILE = "Metadata/filament_settings_";
|
||||
const std::string PROJECT_EMBEDDED_PRINTER_PRESETS_FILE = "Metadata/machine_settings_";
|
||||
|
||||
const std::string CUT_INFORMATION_FILE = "Metadata/cut_information.xml";
|
||||
|
||||
const unsigned int AUXILIARY_STR_LEN = 12;
|
||||
const unsigned int METADATA_STR_LEN = 9;
|
||||
|
@ -199,6 +206,24 @@ static constexpr const char* ASSEMBLE_ITEM_TAG = "assemble_item";
|
|||
static constexpr const char* SLICE_HEADER_TAG = "header";
|
||||
static constexpr const char* SLICE_HEADER_ITEM_TAG = "header_item";
|
||||
|
||||
// text_info
|
||||
static constexpr const char* TEXT_INFO_TAG = "text_info";
|
||||
static constexpr const char* TEXT_ATTR = "text";
|
||||
static constexpr const char* FONT_NAME_ATTR = "font_name";
|
||||
static constexpr const char* FONT_INDEX_ATTR = "font_index";
|
||||
static constexpr const char* FONT_SIZE_ATTR = "font_size";
|
||||
static constexpr const char* THICKNESS_ATTR = "thickness";
|
||||
static constexpr const char* EMBEDED_DEPTH_ATTR = "embeded_depth";
|
||||
static constexpr const char* ROTATE_ANGLE_ATTR = "rotate_angle";
|
||||
static constexpr const char* TEXT_GAP_ATTR = "text_gap";
|
||||
static constexpr const char* BOLD_ATTR = "bold";
|
||||
static constexpr const char* ITALIC_ATTR = "italic";
|
||||
static constexpr const char* SURFACE_TEXT_ATTR = "surface_text";
|
||||
static constexpr const char* KEEP_HORIZONTAL_ATTR = "keep_horizontal";
|
||||
static constexpr const char* HIT_MESH_ATTR = "hit_mesh";
|
||||
static constexpr const char* HIT_POSITION_ATTR = "hit_position";
|
||||
static constexpr const char* HIT_NORMAL_ATTR = "hit_normal";
|
||||
|
||||
// BBS: encrypt
|
||||
static constexpr const char* RELATIONSHIP_TAG = "Relationship";
|
||||
static constexpr const char* PID_ATTR = "pid";
|
||||
|
@ -243,11 +268,13 @@ static constexpr const char* BED_TYPE_ATTR = "bed_type";
|
|||
static constexpr const char* PRINT_SEQUENCE_ATTR = "print_sequence";
|
||||
static constexpr const char* GCODE_FILE_ATTR = "gcode_file";
|
||||
static constexpr const char* THUMBNAIL_FILE_ATTR = "thumbnail_file";
|
||||
static constexpr const char* TOP_FILE_ATTR = "top_file";
|
||||
static constexpr const char* PICK_FILE_ATTR = "pick_file";
|
||||
static constexpr const char* PATTERN_FILE_ATTR = "pattern_file";
|
||||
static constexpr const char* PATTERN_BBOX_FILE_ATTR = "pattern_bbox_file";
|
||||
static constexpr const char* OBJECT_ID_ATTR = "object_id";
|
||||
static constexpr const char* INSTANCEID_ATTR = "instance_id";
|
||||
static constexpr const char* ARRANGE_ORDER_ATTR = "arrange_order";
|
||||
static constexpr const char* IDENTIFYID_ATTR = "identify_id";
|
||||
static constexpr const char* PLATERID_ATTR = "plater_id";
|
||||
static constexpr const char* PLATER_NAME_ATTR = "plater_name";
|
||||
static constexpr const char* PLATE_IDX_ATTR = "index";
|
||||
|
@ -363,6 +390,33 @@ bool bbs_get_attribute_value_bool(const char** attributes, unsigned int attribut
|
|||
return (text != nullptr) ? (bool)::atoi(text) : true;
|
||||
}
|
||||
|
||||
void add_vec3(std::stringstream &stream, const Slic3r::Vec3f &tr)
|
||||
{
|
||||
for (unsigned r = 0; r < 3; ++r) {
|
||||
stream << tr(r);
|
||||
if (r != 2)
|
||||
stream << " ";
|
||||
}
|
||||
}
|
||||
|
||||
Slic3r::Vec3f get_vec3_from_string(const std::string &pos_str)
|
||||
{
|
||||
Slic3r::Vec3f pos(0, 0, 0);
|
||||
if (pos_str.empty())
|
||||
return pos;
|
||||
|
||||
std::vector<std::string> values;
|
||||
boost::split(values, pos_str, boost::is_any_of(" "), boost::token_compress_on);
|
||||
|
||||
if (values.size() != 3)
|
||||
return pos;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
pos(i) = ::atof(values[i].c_str());
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
Slic3r::Transform3d bbs_get_transform_from_3mf_specs_string(const std::string& mat_str)
|
||||
{
|
||||
// check: https://3mf.io/3d-manufacturing-format/ or https://github.com/3MFConsortium/spec_core/blob/master/3MF%20Core%20Specification.md
|
||||
|
@ -608,7 +662,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
int object_id;
|
||||
int instance_id;
|
||||
int arrange_order;
|
||||
int identify_id;
|
||||
};
|
||||
|
||||
struct Instance
|
||||
|
@ -648,6 +702,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
MetadataList metadata;
|
||||
RepairedMeshErrors mesh_stats;
|
||||
ModelVolumeType part_type;
|
||||
TextInfo text_info;
|
||||
|
||||
VolumeMetadata(unsigned int first_triangle_id, unsigned int last_triangle_id, ModelVolumeType type = ModelVolumeType::MODEL_PART)
|
||||
: first_triangle_id(first_triangle_id)
|
||||
|
@ -672,6 +727,19 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
VolumeMetadataList volumes;
|
||||
};
|
||||
|
||||
struct CutObjectInfo
|
||||
{
|
||||
struct Connector
|
||||
{
|
||||
int volume_id;
|
||||
int type;
|
||||
float r_tolerance;
|
||||
float h_tolerance;
|
||||
};
|
||||
CutObjectBase id;
|
||||
std::vector<Connector> connectors;
|
||||
};
|
||||
|
||||
// Map from a 1 based 3MF object ID to a 0 based ModelObject index inside m_model->objects.
|
||||
//typedef std::pair<std::string, int> Id; // BBS: encrypt
|
||||
typedef std::map<Id, CurrentObject> IdToCurrentObjectMap;
|
||||
|
@ -680,6 +748,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
//typedef std::map<Id, ComponentsList> IdToAliasesMap;
|
||||
typedef std::vector<Instance> InstancesList;
|
||||
typedef std::map<int, ObjectMetadata> IdToMetadataMap;
|
||||
typedef std::map<int, CutObjectInfo> IdToCutObjectInfoMap;
|
||||
//typedef std::map<Id, Geometry> IdToGeometryMap;
|
||||
typedef std::map<int, std::vector<coordf_t>> IdToLayerHeightsProfileMap;
|
||||
/*typedef std::map<int, t_layer_config_ranges> IdToLayerConfigRangesMap;
|
||||
|
@ -848,6 +917,11 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
std::string m_designer_cover;
|
||||
ModelInfo model_info;
|
||||
BBLProject project_info;
|
||||
std::string m_profile_title;
|
||||
std::string m_profile_cover;
|
||||
std::string m_Profile_description;
|
||||
std::string m_profile_user_id;
|
||||
std::string m_profile_user_name;
|
||||
|
||||
XML_Parser m_xml_parser;
|
||||
// Error code returned by the application side of the parser. In that case the expat may not reliably deliver the error state
|
||||
|
@ -866,6 +940,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
//IdToGeometryMap m_orig_geometries; // backup & restore
|
||||
CurrentConfig m_curr_config;
|
||||
IdToMetadataMap m_objects_metadata;
|
||||
IdToCutObjectInfoMap m_cut_object_infos;
|
||||
IdToLayerHeightsProfileMap m_layer_heights_profiles;
|
||||
/*IdToLayerConfigRangesMap m_layer_config_ranges;
|
||||
IdToSlaSupportPointsMap m_sla_support_points;
|
||||
|
@ -924,6 +999,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool _extract_xml_from_archive(mz_zip_archive& archive, std::string const & path, XML_StartElementHandler start_handler, XML_EndElementHandler end_handler);
|
||||
bool _extract_xml_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, XML_StartElementHandler start_handler, XML_EndElementHandler end_handler);
|
||||
bool _extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
void _extract_cut_information_from_archive(mz_zip_archive &archive, const mz_zip_archive_file_stat &stat, ConfigSubstitutionContext &config_substitutions);
|
||||
void _extract_layer_heights_profile_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
void _extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, ConfigSubstitutionContext& config_substitutions);
|
||||
void _extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat);
|
||||
|
@ -1031,6 +1107,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool _handle_start_assemble_item(const char** attributes, unsigned int num_attributes);
|
||||
bool _handle_end_assemble_item();
|
||||
|
||||
bool _handle_start_text_info_item(const char **attributes, unsigned int num_attributes);
|
||||
bool _handle_end_text_info_item();
|
||||
|
||||
// BBS: callbacks to parse the .rels file
|
||||
static void XMLCALL _handle_start_relationships_element(void* userData, const char* name, const char** attributes);
|
||||
static void XMLCALL _handle_end_relationships_element(void* userData, const char* name);
|
||||
|
@ -1128,7 +1207,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
m_plater_data.clear();
|
||||
m_curr_instance.object_id = -1;
|
||||
m_curr_instance.instance_id = -1;
|
||||
m_curr_instance.arrange_order = 0;
|
||||
m_curr_instance.identify_id = 0;
|
||||
clear_errors();
|
||||
|
||||
// restore
|
||||
|
@ -1380,6 +1459,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
m_model->design_info->Designer = m_designer;
|
||||
}
|
||||
|
||||
m_model->profile_info = std::make_shared<ModelProfileInfo>();
|
||||
m_model->profile_info->ProfileTile = m_profile_title;
|
||||
m_model->profile_info->ProfileCover = m_profile_cover;
|
||||
m_model->profile_info->ProfileDescription = m_Profile_description;
|
||||
m_model->profile_info->ProfileUserId = m_profile_user_id;
|
||||
m_model->profile_info->ProfileUserName = m_profile_user_name;
|
||||
|
||||
|
||||
m_model->model_info = std::make_shared<ModelInfo>();
|
||||
m_model->model_info->load(model_info);
|
||||
|
||||
|
@ -1445,6 +1532,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
// extract slic3r print config file
|
||||
_extract_project_config_from_archive(archive, stat, config, config_substitutions, model);
|
||||
}
|
||||
else if (boost::algorithm::iequals(name, CUT_INFORMATION_FILE)) {
|
||||
// extract object cut info
|
||||
_extract_cut_information_from_archive(archive, stat, config_substitutions);
|
||||
}
|
||||
//BBS: project embedded presets
|
||||
else if (!dont_load_config && boost::algorithm::istarts_with(name, PROJECT_EMBEDDED_PRINT_PRESETS_FILE)) {
|
||||
// extract slic3r layer config ranges file
|
||||
|
@ -1668,6 +1759,19 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
if (!_generate_volumes_new(*model_object, object_id_list, *volumes_ptr, config_substitutions))
|
||||
return false;
|
||||
|
||||
// Apply cut information for object if any was loaded
|
||||
// m_cut_object_ids are indexed by a 1 based model object index.
|
||||
IdToCutObjectInfoMap::iterator cut_object_info = m_cut_object_infos.find(object.second + 1);
|
||||
if (cut_object_info != m_cut_object_infos.end()) {
|
||||
model_object->cut_id = cut_object_info->second.id;
|
||||
|
||||
for (auto connector : cut_object_info->second.connectors) {
|
||||
assert(0 <= connector.volume_id && connector.volume_id <= int(model_object->volumes.size()));
|
||||
model_object->volumes[connector.volume_id]->cut_info =
|
||||
ModelVolume::CutInfo(CutConnectorType(connector.type), connector.r_tolerance, connector.h_tolerance, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If instances contain a single volume, the volume offset should be 0,0,0
|
||||
|
@ -1776,12 +1880,15 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
plate_data_list[it->first-1]->slice_filaments_info = it->second->slice_filaments_info;
|
||||
plate_data_list[it->first-1]->warnings = it->second->warnings;
|
||||
plate_data_list[it->first-1]->thumbnail_file = (m_load_restore || it->second->thumbnail_file.empty()) ? it->second->thumbnail_file : m_backup_path + "/" + it->second->thumbnail_file;
|
||||
plate_data_list[it->first-1]->pattern_file = (m_load_restore || it->second->pattern_file.empty()) ? it->second->pattern_file : m_backup_path + "/" + it->second->pattern_file;
|
||||
//plate_data_list[it->first-1]->pattern_file = (m_load_restore || it->second->pattern_file.empty()) ? it->second->pattern_file : m_backup_path + "/" + it->second->pattern_file;
|
||||
plate_data_list[it->first-1]->top_file = (m_load_restore || it->second->top_file.empty()) ? it->second->top_file : m_backup_path + "/" + it->second->top_file;
|
||||
plate_data_list[it->first-1]->pick_file = (m_load_restore || it->second->pick_file.empty()) ? it->second->pick_file : m_backup_path + "/" + it->second->pick_file;
|
||||
plate_data_list[it->first-1]->pattern_bbox_file = (m_load_restore || it->second->pattern_bbox_file.empty()) ? it->second->pattern_bbox_file : m_backup_path + "/" + it->second->pattern_bbox_file;
|
||||
plate_data_list[it->first-1]->config = it->second->config;
|
||||
|
||||
current_plate_data = plate_data_list[it->first - 1];
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", plate %1%, thumbnail_file=%2%")%it->first %plate_data_list[it->first-1]->thumbnail_file;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", top_thumbnail_file=%1%, pick_thumbnail_file=%2%")%plate_data_list[it->first-1]->top_file %plate_data_list[it->first-1]->pick_file;
|
||||
it++;
|
||||
|
||||
//update the arrange order
|
||||
|
@ -1817,7 +1924,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
continue;
|
||||
}
|
||||
ModelInstance* inst = obj->instances[inst_index];
|
||||
inst->arrange_order = map_it->second.second;
|
||||
inst->loaded_id = map_it->second.second;
|
||||
map_it++;
|
||||
}
|
||||
}
|
||||
|
@ -2022,6 +2129,61 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
return true;
|
||||
}
|
||||
|
||||
void _BBS_3MF_Importer::_extract_cut_information_from_archive(mz_zip_archive &archive, const mz_zip_archive_file_stat &stat, ConfigSubstitutionContext &config_substitutions)
|
||||
{
|
||||
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 cut information data to buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
std::istringstream iss(buffer); // wrap returned xml to istringstream
|
||||
pt::ptree objects_tree;
|
||||
pt::read_xml(iss, objects_tree);
|
||||
|
||||
for (const auto &object : objects_tree.get_child("objects")) {
|
||||
pt::ptree object_tree = object.second;
|
||||
int obj_idx = object_tree.get<int>("<xmlattr>.id", -1);
|
||||
if (obj_idx <= 0) {
|
||||
add_error("Found invalid object id");
|
||||
continue;
|
||||
}
|
||||
|
||||
IdToCutObjectInfoMap::iterator object_item = m_cut_object_infos.find(obj_idx);
|
||||
if (object_item != m_cut_object_infos.end()) {
|
||||
add_error("Found duplicated cut_object_id");
|
||||
continue;
|
||||
}
|
||||
|
||||
CutObjectBase cut_id;
|
||||
std::vector<CutObjectInfo::Connector> connectors;
|
||||
|
||||
for (const auto &obj_cut_info : object_tree) {
|
||||
if (obj_cut_info.first == "cut_id") {
|
||||
pt::ptree cut_id_tree = obj_cut_info.second;
|
||||
cut_id = CutObjectBase(ObjectID(cut_id_tree.get<size_t>("<xmlattr>.id")), cut_id_tree.get<size_t>("<xmlattr>.check_sum"),
|
||||
cut_id_tree.get<size_t>("<xmlattr>.connectors_cnt"));
|
||||
}
|
||||
if (obj_cut_info.first == "connectors") {
|
||||
pt::ptree cut_connectors_tree = obj_cut_info.second;
|
||||
for (const auto &cut_connector : cut_connectors_tree) {
|
||||
if (cut_connector.first != "connector") continue;
|
||||
pt::ptree connector_tree = cut_connector.second;
|
||||
CutObjectInfo::Connector connector = {connector_tree.get<int>("<xmlattr>.volume_id"), connector_tree.get<int>("<xmlattr>.type"),
|
||||
connector_tree.get<float>("<xmlattr>.r_tolerance"), connector_tree.get<float>("<xmlattr>.h_tolerance")};
|
||||
connectors.emplace_back(connector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CutObjectInfo cut_info{cut_id, connectors};
|
||||
m_cut_object_infos.insert({obj_idx, cut_info});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _BBS_3MF_Importer::_extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, const std::string& archive_filename)
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
|
@ -2709,6 +2871,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
res = _handle_start_assemble(attributes, num_attributes);
|
||||
else if (::strcmp(ASSEMBLE_ITEM_TAG, name) == 0)
|
||||
res = _handle_start_assemble_item(attributes, num_attributes);
|
||||
else if (::strcmp(TEXT_INFO_TAG, name) == 0)
|
||||
res = _handle_start_text_info_item(attributes, num_attributes);
|
||||
|
||||
if (!res)
|
||||
_stop_xml_parser();
|
||||
|
@ -3075,7 +3239,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
bool _BBS_3MF_Importer::_handle_start_component(const char** attributes, unsigned int num_attributes)
|
||||
{
|
||||
int object_id = bbs_get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR);
|
||||
std::string path = bbs_get_attribute_value_string(attributes, num_attributes, PPATH_ATTR);
|
||||
int object_id = bbs_get_attribute_value_int(attributes, num_attributes, OBJECTID_ATTR);
|
||||
Transform3d transform = bbs_get_transform_from_3mf_specs_string(bbs_get_attribute_value_string(attributes, num_attributes, TRANSFORM_ATTR));
|
||||
|
||||
/*Id id = std::make_pair(m_sub_model_path, object_id);
|
||||
|
@ -3089,7 +3254,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
}*/
|
||||
|
||||
if (m_curr_object) {
|
||||
Id id = std::make_pair(m_sub_model_path, object_id);
|
||||
Id id = std::make_pair(m_sub_model_path.empty() ? path : m_sub_model_path, object_id);
|
||||
m_curr_object->components.emplace_back(id, transform);
|
||||
}
|
||||
|
||||
|
@ -3158,7 +3323,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool _BBS_3MF_Importer::_handle_end_metadata()
|
||||
{
|
||||
if ((m_curr_metadata_name == BBS_3MF_VERSION)||(m_curr_metadata_name == BBS_3MF_VERSION1)) {
|
||||
m_is_bbl_3mf = true;
|
||||
//m_is_bbl_3mf = true;
|
||||
m_version = (unsigned int)atoi(m_curr_characters.c_str());
|
||||
/*if (m_check_version && (m_version > VERSION_BBS_3MF_COMPATIBLE)) {
|
||||
// std::string msg = _(L("The selected 3mf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible."));
|
||||
|
@ -3195,6 +3360,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
} else if (m_curr_metadata_name == BBL_MODEL_NAME_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found model name = " << m_curr_characters;
|
||||
model_info.model_name = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_ORIGIN_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found model name = " << m_curr_characters;
|
||||
model_info.origin = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_DESIGNER_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found designer = " << m_curr_characters;
|
||||
m_designer = xml_unescape(m_curr_characters);
|
||||
|
@ -3216,6 +3384,21 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
} else if (m_curr_metadata_name == BBL_REGION_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found region = " << m_curr_characters;
|
||||
m_contry_code = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_PROFILE_TITLE_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found profile_title = " << m_curr_characters;
|
||||
m_profile_title = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_PROFILE_COVER_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found profile_cover = " << m_curr_characters;
|
||||
m_profile_cover = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_PROFILE_DESCRIPTION_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found profile_description = " << m_curr_characters;
|
||||
m_Profile_description = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_PROFILE_USER_ID_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found profile_user_id = " << m_curr_characters;
|
||||
m_profile_user_id = xml_unescape(m_curr_characters);
|
||||
}else if (m_curr_metadata_name == BBL_PROFILE_USER_NAME_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found profile_user_name = " << m_curr_characters;
|
||||
m_profile_user_name = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_CREATION_DATE_TAG) {
|
||||
;
|
||||
} else if (m_curr_metadata_name == BBL_MODIFICATION_TAG) {
|
||||
|
@ -3497,10 +3680,18 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
m_curr_plater->thumbnail_file = value;
|
||||
}
|
||||
else if (key == PATTERN_FILE_ATTR)
|
||||
else if (key == TOP_FILE_ATTR)
|
||||
{
|
||||
m_curr_plater->pattern_file = value;
|
||||
m_curr_plater->top_file = value;
|
||||
}
|
||||
else if (key == PICK_FILE_ATTR)
|
||||
{
|
||||
m_curr_plater->pick_file = value;
|
||||
}
|
||||
//else if (key == PATTERN_FILE_ATTR)
|
||||
//{
|
||||
// m_curr_plater->pattern_file = value;
|
||||
//}
|
||||
else if (key == PATTERN_BBOX_FILE_ATTR)
|
||||
{
|
||||
m_curr_plater->pattern_bbox_file = value;
|
||||
|
@ -3509,9 +3700,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
m_curr_instance.instance_id = atoi(value.c_str());
|
||||
}
|
||||
else if (key == ARRANGE_ORDER_ATTR)
|
||||
else if (key == IDENTIFYID_ATTR)
|
||||
{
|
||||
m_curr_instance.arrange_order = atoi(value.c_str());
|
||||
m_curr_instance.identify_id = atoi(value.c_str());
|
||||
}
|
||||
else if (key == OBJECT_ID_ATTR)
|
||||
{
|
||||
|
@ -3666,13 +3857,13 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
//add_error("invalid object id/instance id");
|
||||
//skip this instance
|
||||
m_curr_instance.object_id = m_curr_instance.instance_id = -1;
|
||||
m_curr_instance.arrange_order = 0;
|
||||
m_curr_instance.identify_id = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
m_curr_plater->obj_inst_map.emplace(m_curr_instance.object_id, std::make_pair(m_curr_instance.instance_id, m_curr_instance.arrange_order));
|
||||
m_curr_plater->obj_inst_map.emplace(m_curr_instance.object_id, std::make_pair(m_curr_instance.instance_id, m_curr_instance.identify_id));
|
||||
m_curr_instance.object_id = m_curr_instance.instance_id = -1;
|
||||
m_curr_instance.arrange_order = 0;
|
||||
m_curr_instance.identify_id = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3721,6 +3912,56 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Importer::_handle_start_text_info_item(const char **attributes, unsigned int num_attributes)
|
||||
{
|
||||
IdToMetadataMap::iterator object = m_objects_metadata.find(m_curr_config.object_id);
|
||||
if (object == m_objects_metadata.end()) {
|
||||
add_error("can not find object for text_info, id " + std::to_string(m_curr_config.object_id));
|
||||
return false;
|
||||
}
|
||||
if ((m_curr_config.volume_id == -1) || ((object->second.volumes.size() - 1) < m_curr_config.volume_id)) {
|
||||
add_error("can not find part for text_info");
|
||||
return false;
|
||||
}
|
||||
|
||||
ObjectMetadata::VolumeMetadata &volume = object->second.volumes[m_curr_config.volume_id];
|
||||
|
||||
TextInfo text_info;
|
||||
text_info.m_text = bbs_get_attribute_value_string(attributes, num_attributes, TEXT_ATTR);
|
||||
text_info.m_font_name = bbs_get_attribute_value_string(attributes, num_attributes, FONT_NAME_ATTR);
|
||||
|
||||
text_info.m_curr_font_idx = bbs_get_attribute_value_int(attributes, num_attributes, FONT_INDEX_ATTR);
|
||||
|
||||
text_info.m_font_size = bbs_get_attribute_value_float(attributes, num_attributes, FONT_SIZE_ATTR);
|
||||
text_info.m_thickness = bbs_get_attribute_value_float(attributes, num_attributes, THICKNESS_ATTR);
|
||||
text_info.m_embeded_depth = bbs_get_attribute_value_float(attributes, num_attributes, EMBEDED_DEPTH_ATTR);
|
||||
text_info.m_rotate_angle = bbs_get_attribute_value_float(attributes, num_attributes, ROTATE_ANGLE_ATTR);
|
||||
text_info.m_text_gap = bbs_get_attribute_value_float(attributes, num_attributes, TEXT_GAP_ATTR);
|
||||
|
||||
text_info.m_bold = bbs_get_attribute_value_int(attributes, num_attributes, BOLD_ATTR);
|
||||
text_info.m_italic = bbs_get_attribute_value_int(attributes, num_attributes, ITALIC_ATTR);
|
||||
text_info.m_is_surface_text = bbs_get_attribute_value_int(attributes, num_attributes, SURFACE_TEXT_ATTR);
|
||||
text_info.m_keep_horizontal = bbs_get_attribute_value_int(attributes, num_attributes, KEEP_HORIZONTAL_ATTR);
|
||||
|
||||
text_info.m_rr.mesh_id = bbs_get_attribute_value_int(attributes, num_attributes, HIT_MESH_ATTR);
|
||||
|
||||
std::string hit_pos = bbs_get_attribute_value_string(attributes, num_attributes, HIT_POSITION_ATTR);
|
||||
if (!hit_pos.empty())
|
||||
text_info.m_rr.hit = get_vec3_from_string(hit_pos);
|
||||
|
||||
std::string hit_normal = bbs_get_attribute_value_string(attributes, num_attributes, HIT_NORMAL_ATTR);
|
||||
if (!hit_normal.empty())
|
||||
text_info.m_rr.normal = get_vec3_from_string(hit_normal);
|
||||
|
||||
volume.text_info = text_info;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Importer::_handle_end_text_info_item()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void XMLCALL _BBS_3MF_Importer::_handle_start_relationships_element(void* userData, const char* name, const char** attributes)
|
||||
{
|
||||
_BBS_3MF_Importer* importer = (_BBS_3MF_Importer*)userData;
|
||||
|
@ -3906,16 +4147,17 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
TriangleMesh triangle_mesh(std::move(its), volume_data->mesh_stats);
|
||||
|
||||
if (!m_is_bbl_3mf) {
|
||||
// if the 3mf was not produced by OrcaSlicer and there is only one instance,
|
||||
// bake the transformation into the geometry to allow the reload from disk command
|
||||
// to work properly
|
||||
if (object.instances.size() == 1) {
|
||||
triangle_mesh.transform(object.instances.front()->get_transformation().get_matrix(), false);
|
||||
object.instances.front()->set_transformation(Slic3r::Geometry::Transformation());
|
||||
//FIXME do the mesh fixing?
|
||||
}
|
||||
}
|
||||
// BBS: no need to multiply the instance matrix into the volume
|
||||
//if (!m_is_bbl_3mf) {
|
||||
// // if the 3mf was not produced by BambuStudio and there is only one instance,
|
||||
// // bake the transformation into the geometry to allow the reload from disk command
|
||||
// // to work properly
|
||||
// if (object.instances.size() == 1) {
|
||||
// triangle_mesh.transform(object.instances.front()->get_transformation().get_matrix(), false);
|
||||
// object.instances.front()->set_transformation(Slic3r::Geometry::Transformation());
|
||||
// //FIXME do the mesh fixing?
|
||||
// }
|
||||
//}
|
||||
if (triangle_mesh.volume() < 0)
|
||||
triangle_mesh.flip_triangles();
|
||||
|
||||
|
@ -3972,6 +4214,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
volume->set_type(volume_data->part_type);
|
||||
|
||||
if (!volume_data->text_info.m_text.empty())
|
||||
volume->set_text_info(volume_data->text_info);
|
||||
|
||||
// apply the remaining volume's metadata
|
||||
for (const Metadata& metadata : volume_data->metadata) {
|
||||
if (metadata.key == NAME_KEY)
|
||||
|
@ -4716,6 +4961,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool m_save_gcode { false }; // whether to save gcode for normal save
|
||||
bool m_skip_model { false }; // skip model when exporting .gcode.3mf
|
||||
bool m_skip_auxiliary { false }; // skip normal axuiliary files
|
||||
bool m_use_loaded_id { false }; // whether to use loaded id for identify_id
|
||||
|
||||
public:
|
||||
//BBS: add plate data related logic
|
||||
|
@ -4734,6 +4980,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
std::vector<Preset*>& project_presets,
|
||||
const DynamicPrintConfig* config,
|
||||
const std::vector<ThumbnailData*>& thumbnail_data,
|
||||
const std::vector<ThumbnailData*>& top_thumbnail_data,
|
||||
const std::vector<ThumbnailData*>& pick_thumbnail_data,
|
||||
Export3mfProgressFn proFn,
|
||||
const std::vector<ThumbnailData*>& calibration_data,
|
||||
const std::vector<PlateBBoxData*>& id_bboxes,
|
||||
|
@ -4744,7 +4992,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
|
||||
|
||||
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, int index);
|
||||
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index);
|
||||
bool _add_calibration_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, int index);
|
||||
bool _add_bbox_file_to_archive(mz_zip_archive& archive, const PlateBBoxData& id_bboxes, int index);
|
||||
bool _add_relationships_file_to_archive(mz_zip_archive & archive,
|
||||
|
@ -4767,7 +5015,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool _add_project_config_file_to_archive(mz_zip_archive& archive, const DynamicPrintConfig &config, Model& model);
|
||||
//BBS: add project embedded preset files
|
||||
bool _add_project_embedded_presets_to_archive(mz_zip_archive& archive, Model& model, std::vector<Preset*> project_presets);
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx = -1, bool save_gcode = true);
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx = -1, bool save_gcode = true, bool use_loaded_id = false);
|
||||
bool _add_cut_information_file_to_archive(mz_zip_archive &archive, Model &model);
|
||||
bool _add_slice_info_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list);
|
||||
bool _add_gcode_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, Export3mfProgressFn proFn = nullptr);
|
||||
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model, const DynamicPrintConfig* config);
|
||||
|
@ -4801,12 +5050,15 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
m_skip_model = store_params.strategy & SaveStrategy::SkipModel;
|
||||
m_skip_auxiliary = store_params.strategy & SaveStrategy::SkipAuxiliary;
|
||||
|
||||
m_use_loaded_id = store_params.strategy & SaveStrategy::UseLoadedId;
|
||||
|
||||
boost::system::error_code ec;
|
||||
std::string filename = std::string(store_params.path);
|
||||
boost::filesystem::remove(filename + ".tmp", ec);
|
||||
|
||||
bool result = _save_model_to_file(filename + ".tmp", *store_params.model, store_params.plate_data_list, store_params.project_presets, store_params.config,
|
||||
store_params.thumbnail_data, store_params.proFn, store_params.calibration_thumbnail_data, store_params.id_bboxes, store_params.project, store_params.export_plate_idx);
|
||||
store_params.thumbnail_data, store_params.top_thumbnail_data, store_params.pick_thumbnail_data, store_params.proFn,
|
||||
store_params.calibration_thumbnail_data, store_params.id_bboxes, store_params.project, store_params.export_plate_idx);
|
||||
if (result) {
|
||||
boost::filesystem::rename(filename + ".tmp", filename, ec);
|
||||
if (ec) {
|
||||
|
@ -4874,6 +5126,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
std::vector<Preset*>& project_presets,
|
||||
const DynamicPrintConfig* config,
|
||||
const std::vector<ThumbnailData*>& thumbnail_data,
|
||||
const std::vector<ThumbnailData*>& top_thumbnail_data,
|
||||
const std::vector<ThumbnailData*>& pick_thumbnail_data,
|
||||
Export3mfProgressFn proFn,
|
||||
const std::vector<ThumbnailData*>& calibration_data,
|
||||
const std::vector<PlateBBoxData*>& id_bboxes,
|
||||
|
@ -4888,7 +5142,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool cb_cancel = false;
|
||||
|
||||
//BBS progress point
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",before open zip writer, m_skip_static %1%, m_save_gcode %2%\n")%m_skip_static %m_save_gcode;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ <<
|
||||
boost::format(",before open zip writer, m_skip_static %1%, m_save_gcode %2%, m_use_loaded_id %3%")%m_skip_static %m_save_gcode %m_use_loaded_id;
|
||||
if (proFn) {
|
||||
proFn(EXPORT_STAGE_OPEN_3MF, 0, 1, cb_cancel);
|
||||
if (cb_cancel)
|
||||
|
@ -4927,43 +5182,115 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
}
|
||||
|
||||
//BBS progress point
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(",before add thumbnails, count %1%\n") % thumbnail_data.size();
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(",before add thumbnails, count %1%") % thumbnail_data.size();
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",top&&pick thumbnails, count %1%")%top_thumbnail_data.size();
|
||||
|
||||
//BBS: add thumbnail for each plate
|
||||
if (!m_skip_static && thumbnail_data.size() > 0) {
|
||||
// Adds the file Metadata/thumbnail.png.
|
||||
if (!m_skip_static) {
|
||||
std::vector<bool> thumbnail_status(plate_data_list.size(), false);
|
||||
std::vector<bool> top_thumbnail_status(plate_data_list.size(), false);
|
||||
std::vector<bool> pick_thumbnail_status(plate_data_list.size(), false);
|
||||
|
||||
if ((thumbnail_data.size() > 0)&&(thumbnail_data.size() > plate_data_list.size())) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", thumbnail_data size %1% > plate count %2%")
|
||||
% thumbnail_data.size() %plate_data_list.size();
|
||||
return false;
|
||||
}
|
||||
if ((top_thumbnail_data.size() > 0)&&(top_thumbnail_data.size() > plate_data_list.size())) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", top_thumbnail_data size %1% > plate count %2%")
|
||||
% top_thumbnail_data.size() %plate_data_list.size();
|
||||
return false;
|
||||
}
|
||||
if ((pick_thumbnail_data.size() > 0)&&(pick_thumbnail_data.size() > plate_data_list.size())) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", pick_thumbnail_data size %1% > plate count %2%")
|
||||
% pick_thumbnail_data.size() %plate_data_list.size();
|
||||
return false;
|
||||
}
|
||||
if (top_thumbnail_data.size() != pick_thumbnail_data.size()) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", top_thumbnail_data size %1% != pick_thumbnail_data size %2%")
|
||||
% top_thumbnail_data.size() %pick_thumbnail_data.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (proFn) {
|
||||
proFn(EXPORT_STAGE_ADD_THUMBNAILS, 0, plate_data_list.size(), cb_cancel);
|
||||
if (cb_cancel)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (unsigned int index = 0; index < thumbnail_data.size(); index++)
|
||||
{
|
||||
if (proFn) {
|
||||
proFn(EXPORT_STAGE_ADD_THUMBNAILS, index, thumbnail_data.size(), cb_cancel);
|
||||
if (cb_cancel)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thumbnail_data[index]->is_valid())
|
||||
{
|
||||
if (!_add_thumbnail_file_to_archive(archive, *thumbnail_data[index], index)) {
|
||||
if (!_add_thumbnail_file_to_archive(archive, *thumbnail_data[index], "Metadata/plate", index)) {
|
||||
return false;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",add thumbnail %1%'s data into 3mf")%(index+1);
|
||||
thumbnail_status[index] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!m_skip_static && plate_data_list.size() > 0) {
|
||||
|
||||
// Adds the file Metadata/top_i.png and Metadata/pick_i.png
|
||||
for (unsigned int index = 0; index < top_thumbnail_data.size(); index++)
|
||||
{
|
||||
if (top_thumbnail_data[index]->is_valid())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",add top thumbnail %1%'s data into 3mf")%(index+1);
|
||||
if (!_add_thumbnail_file_to_archive(archive, *top_thumbnail_data[index], "Metadata/top", index)) {
|
||||
return false;
|
||||
}
|
||||
top_thumbnail_status[index] = true;
|
||||
}
|
||||
|
||||
if (pick_thumbnail_data[index]->is_valid())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",add pick thumbnail %1%'s data into 3mf")%(index+1);
|
||||
if (!_add_thumbnail_file_to_archive(archive, *pick_thumbnail_data[index], "Metadata/pick", index)) {
|
||||
return false;
|
||||
}
|
||||
pick_thumbnail_status[index] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < plate_data_list.size(); i++) {
|
||||
PlateData *plate_data = plate_data_list[i];
|
||||
if (proFn) {
|
||||
proFn(EXPORT_STAGE_ADD_THUMBNAILS, i, plate_data_list.size(), cb_cancel);
|
||||
if (cb_cancel)
|
||||
return false;
|
||||
}
|
||||
if (!plate_data->thumbnail_file.empty() && (boost::filesystem::exists(plate_data->thumbnail_file))){
|
||||
|
||||
if (!thumbnail_status[i] && !plate_data->thumbnail_file.empty() && (boost::filesystem::exists(plate_data->thumbnail_file))){
|
||||
std::string dst_in_3mf = (boost::format("Metadata/plate_%1%.png") % (i + 1)).str();
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", add thumbnail %1% from file %2%") % (i+1) %plate_data->thumbnail_file;
|
||||
|
||||
if (!_add_file_to_archive(archive, dst_in_3mf, plate_data->thumbnail_file)) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", add thumbnail %1% from file %2% failed\n") % (i+1) %plate_data->thumbnail_file;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!top_thumbnail_status[i] && !plate_data->top_file.empty() && (boost::filesystem::exists(plate_data->top_file))){
|
||||
std::string dst_in_3mf = (boost::format("Metadata/top_%1%.png") % (i + 1)).str();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", add top thumbnail %1% from file %2%") % (i+1) %plate_data->top_file;
|
||||
if (!_add_file_to_archive(archive, dst_in_3mf, plate_data->top_file)) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", add top thumbnail %1% failed") % (i+1);
|
||||
return false;
|
||||
}
|
||||
top_thumbnail_status[i] = true;
|
||||
}
|
||||
|
||||
if (!pick_thumbnail_status[i] && !plate_data->pick_file.empty() && (boost::filesystem::exists(plate_data->pick_file))){
|
||||
std::string dst_in_3mf = (boost::format("Metadata/pick_%1%.png") % (i + 1)).str();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", add pick thumbnail %1% from file %2%") % (i+1) %plate_data->pick_file;
|
||||
if (!_add_file_to_archive(archive, dst_in_3mf, plate_data->pick_file)) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", add pick thumbnail %1% failed") % (i+1);
|
||||
return false;
|
||||
}
|
||||
pick_thumbnail_status[i] = true;
|
||||
}
|
||||
}
|
||||
if (proFn) {
|
||||
proFn(EXPORT_STAGE_ADD_THUMBNAILS, plate_data_list.size(), plate_data_list.size(), cb_cancel);
|
||||
if (cb_cancel)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5155,11 +5482,16 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
// This file contains all the attributes of all ModelObjects and their ModelVolumes (names, parameter overrides).
|
||||
// As there is just a single Indexed Triangle Set data stored per ModelObject, offsets of volumes into their respective Indexed Triangle Set data
|
||||
// is stored here as well.
|
||||
if (!_add_model_config_file_to_archive(archive, model, plate_data_list, objects_data, export_plate_idx, m_save_gcode)) {
|
||||
if (!_add_model_config_file_to_archive(archive, model, plate_data_list, objects_data, export_plate_idx, m_save_gcode, m_use_loaded_id)) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", _add_model_config_file_to_archive failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_add_cut_information_file_to_archive(archive, model)) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", _add_cut_information_file_to_archive failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//BBS progress point
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(", before add sliced info to 3mf\n");
|
||||
if (proFn) {
|
||||
|
@ -5267,14 +5599,14 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, int index)
|
||||
bool _BBS_3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
size_t png_size = 0;
|
||||
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)thumbnail_data.pixels.data(), thumbnail_data.width, thumbnail_data.height, 4, &png_size, MZ_DEFAULT_COMPRESSION, 1);
|
||||
if (png_data != nullptr) {
|
||||
std::string thumbnail_name = (boost::format("Metadata/plate_%1%.png") % (index + 1)).str();
|
||||
std::string thumbnail_name = (boost::format("%1%_%2%.png")%local_path % (index + 1)).str();
|
||||
res = mz_zip_writer_add_mem(&archive, thumbnail_name.c_str(), (const void*)png_data, png_size, MZ_NO_COMPRESSION);
|
||||
mz_free(png_data);
|
||||
}
|
||||
|
@ -5291,7 +5623,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
bool res = false;
|
||||
|
||||
size_t png_size = 0;
|
||||
/*size_t png_size = 0;
|
||||
void* png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)thumbnail_data.pixels.data(), thumbnail_data.width, thumbnail_data.height, 4, &png_size, MZ_DEFAULT_COMPRESSION, 1);
|
||||
if (png_data != nullptr) {
|
||||
std::string thumbnail_name = (boost::format(PATTERN_FILE_FORMAT) % (index + 1)).str();
|
||||
|
@ -5302,7 +5634,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
if (!res) {
|
||||
add_error("Unable to add thumbnail file to archive");
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", Unable to add thumbnail file to archive\n");
|
||||
}
|
||||
}*/
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -5437,6 +5769,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
stream << " xmlns:p=\"http://schemas.microsoft.com/3dmanufacturing/production/2015/06\" requiredextensions=\"p\"";
|
||||
stream << ">\n";
|
||||
|
||||
std::string origin;
|
||||
std::string name;
|
||||
std::string user_name;
|
||||
std::string user_id;
|
||||
|
@ -5465,6 +5798,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
description = model.model_info->description;
|
||||
copyright = model.model_info->copyright;
|
||||
name = model.model_info->model_name;
|
||||
origin = model.model_info->origin;
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, save_3mf found designer_cover = " << design_cover;
|
||||
}
|
||||
// remember to use metadata_item_map to store metadata info
|
||||
|
@ -5476,6 +5810,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
}
|
||||
|
||||
metadata_item_map[BBL_MODEL_NAME_TAG] = xml_escape(name);
|
||||
metadata_item_map[BBL_ORIGIN_TAG] = xml_escape(origin);
|
||||
metadata_item_map[BBL_DESIGNER_TAG] = xml_escape(user_name);
|
||||
metadata_item_map[BBL_DESIGNER_USER_ID_TAG] = user_id;
|
||||
metadata_item_map[BBL_DESIGNER_COVER_FILE_TAG] = xml_escape(design_cover);
|
||||
|
@ -5650,6 +5985,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
mz_zip_archive archive;
|
||||
mz_zip_zero_struct(&archive);
|
||||
mz_zip_writer_init_heap(&archive, 0, 1024 * 1024);
|
||||
CNumericLocalesSetter locales_setter;
|
||||
_add_model_file_to_archive(object_paths[i], archive, model, objects_data2, nullptr, project);
|
||||
iter->second = objects_data2.begin()->second;
|
||||
void *ppBuf; size_t pSize;
|
||||
|
@ -6302,7 +6638,39 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx, bool save_gcode)
|
||||
void _add_text_info_to_archive(std::stringstream& stream, const TextInfo& text_info) {
|
||||
stream << " <" << TEXT_INFO_TAG << " ";
|
||||
|
||||
stream << TEXT_ATTR << "=\"" << text_info.m_text << "\" ";
|
||||
stream << FONT_NAME_ATTR << "=\"" << text_info.m_font_name << "\" ";
|
||||
|
||||
stream << FONT_INDEX_ATTR << "=\"" << text_info.m_curr_font_idx << "\" ";
|
||||
|
||||
stream << FONT_SIZE_ATTR << "=\"" << text_info.m_font_size << "\" ";
|
||||
stream << THICKNESS_ATTR << "=\"" << text_info.m_thickness << "\" ";
|
||||
stream << EMBEDED_DEPTH_ATTR << "=\"" << text_info.m_embeded_depth << "\" ";
|
||||
stream << ROTATE_ANGLE_ATTR << "=\"" << text_info.m_rotate_angle << "\" ";
|
||||
stream << TEXT_GAP_ATTR << "=\"" << text_info.m_text_gap << "\" ";
|
||||
|
||||
stream << BOLD_ATTR << "=\"" << (text_info.m_bold ? 1 : 0) << "\" ";
|
||||
stream << ITALIC_ATTR << "=\"" << (text_info.m_italic ? 1 : 0) << "\" ";
|
||||
stream << SURFACE_TEXT_ATTR << "=\"" << (text_info.m_is_surface_text ? 1 : 0) << "\" ";
|
||||
stream << KEEP_HORIZONTAL_ATTR << "=\"" << (text_info.m_keep_horizontal ? 1 : 0) << "\" ";
|
||||
|
||||
stream << HIT_MESH_ATTR << "=\"" << text_info.m_rr.mesh_id << "\" ";
|
||||
|
||||
stream << HIT_POSITION_ATTR << "=\"";
|
||||
add_vec3(stream, text_info.m_rr.hit);
|
||||
stream << "\" ";
|
||||
|
||||
stream << HIT_NORMAL_ATTR << "=\"";
|
||||
add_vec3(stream, text_info.m_rr.normal);
|
||||
stream << "\" ";
|
||||
|
||||
stream << "/>\n";
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const IdToObjectDataMap &objects_data, int export_plate_idx, bool save_gcode, bool use_loaded_id)
|
||||
{
|
||||
std::stringstream stream;
|
||||
std::map<const TriangleMesh*, int> shared_meshes;
|
||||
|
@ -6398,6 +6766,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
stream << " <" << METADATA_TAG << " "<< KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << volume->config.opt_serialize(key) << "\"/>\n";
|
||||
}
|
||||
|
||||
const TextInfo &text_info = volume->get_text_info();
|
||||
if (!text_info.m_text.empty())
|
||||
_add_text_info_to_archive(stream, text_info);
|
||||
|
||||
//add the shared mesh logic
|
||||
const TriangleMesh* current_mesh = volume->mesh_ptr();
|
||||
std::map<const TriangleMesh*,int>::iterator mesh_iter;
|
||||
|
@ -6464,10 +6836,20 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << THUMBNAIL_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << thumbnail_file_in_3mf << "\"/>\n";
|
||||
}
|
||||
|
||||
if (!plate_data->pattern_file.empty()) {
|
||||
if (!plate_data->top_file.empty()) {
|
||||
std::string top_file_in_3mf = (boost::format(TOP_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << TOP_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << top_file_in_3mf << "\"/>\n";
|
||||
}
|
||||
|
||||
if (!plate_data->pick_file.empty()) {
|
||||
std::string pick_file_in_3mf = (boost::format(PICK_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PICK_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pick_file_in_3mf << "\"/>\n";
|
||||
}
|
||||
|
||||
/*if (!plate_data->pattern_file.empty()) {
|
||||
std::string pattern_file_in_3mf = (boost::format(PATTERN_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PATTERN_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pattern_file_in_3mf << "\"/>\n";
|
||||
}
|
||||
}*/
|
||||
if (!plate_data->pattern_bbox_file.empty()) {
|
||||
std::string pattern_bbox_file_in_3mf = (boost::format(PATTERN_CONFIG_FILE_FORMAT) % (plate_data->plate_index + 1)).str();
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PATTERN_BBOX_FILE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha << pattern_bbox_file_in_3mf << "\"/>\n";
|
||||
|
@ -6480,7 +6862,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
stream << " <" << INSTANCE_TAG << ">\n";
|
||||
int obj_id = plate_data->objects_and_instances[j].first;
|
||||
int inst_id = plate_data->objects_and_instances[j].second;
|
||||
int arrange_o = 0;
|
||||
int identify_id = 0;
|
||||
ModelObject* obj = NULL;
|
||||
ModelInstance* inst = NULL;
|
||||
if (obj_id >= model.objects.size()) {
|
||||
|
@ -6494,7 +6876,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
}
|
||||
else if (obj){
|
||||
inst = obj->instances[inst_id];
|
||||
arrange_o = inst->arrange_order;
|
||||
if (use_loaded_id && (inst->loaded_id > 0))
|
||||
identify_id = inst->loaded_id;
|
||||
else
|
||||
identify_id = inst->id().id;
|
||||
}
|
||||
if (m_skip_static && obj) {
|
||||
obj_id = obj->get_backup_id();
|
||||
|
@ -6505,7 +6890,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OBJECT_ID_ATTR << "\" " << VALUE_ATTR << "=\"" << obj_id << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << INSTANCEID_ATTR << "\" " << VALUE_ATTR << "=\"" << inst_id << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << ARRANGE_ORDER_ATTR << "\" " << VALUE_ATTR << "=\"" << arrange_o << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << IDENTIFYID_ATTR << "\" " << VALUE_ATTR << "=\"" << identify_id << "\"/>\n";
|
||||
stream << " </" << INSTANCE_TAG << ">\n";
|
||||
}
|
||||
}
|
||||
|
@ -6562,6 +6947,67 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_cut_information_file_to_archive(mz_zip_archive &archive, Model &model)
|
||||
{
|
||||
std::string out = "";
|
||||
pt::ptree tree;
|
||||
|
||||
unsigned int object_cnt = 0;
|
||||
for (const ModelObject *object : model.objects) {
|
||||
object_cnt++;
|
||||
pt::ptree &obj_tree = tree.add("objects.object", "");
|
||||
|
||||
obj_tree.put("<xmlattr>.id", object_cnt);
|
||||
|
||||
// Store info for cut_id
|
||||
pt::ptree &cut_id_tree = obj_tree.add("cut_id", "");
|
||||
|
||||
// store cut_id atributes
|
||||
cut_id_tree.put("<xmlattr>.id", object->cut_id.id().id);
|
||||
cut_id_tree.put("<xmlattr>.check_sum", object->cut_id.check_sum());
|
||||
cut_id_tree.put("<xmlattr>.connectors_cnt", object->cut_id.connectors_cnt());
|
||||
|
||||
int volume_idx = -1;
|
||||
for (const ModelVolume *volume : object->volumes) {
|
||||
++volume_idx;
|
||||
if (volume->is_cut_connector()) {
|
||||
pt::ptree &connectors_tree = obj_tree.add("connectors.connector", "");
|
||||
connectors_tree.put("<xmlattr>.volume_id", volume_idx);
|
||||
connectors_tree.put("<xmlattr>.type", int(volume->cut_info.connector_type));
|
||||
connectors_tree.put("<xmlattr>.r_tolerance", volume->cut_info.radius_tolerance);
|
||||
connectors_tree.put("<xmlattr>.h_tolerance", volume->cut_info.height_tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tree.empty()) {
|
||||
std::ostringstream oss;
|
||||
pt::write_xml(oss, tree);
|
||||
out = oss.str();
|
||||
|
||||
// Post processing("beautification") of the output string for a better preview
|
||||
boost::replace_all(out, "><object", ">\n <object");
|
||||
boost::replace_all(out, "><cut_id", ">\n <cut_id");
|
||||
boost::replace_all(out, "></cut_id>", ">\n </cut_id>");
|
||||
boost::replace_all(out, "><connectors", ">\n <connectors");
|
||||
boost::replace_all(out, "></connectors>", ">\n </connectors>");
|
||||
boost::replace_all(out, "><connector", ">\n <connector");
|
||||
boost::replace_all(out, "></connector>", ">\n </connector>");
|
||||
boost::replace_all(out, "></object>", ">\n </object>");
|
||||
// OR just
|
||||
boost::replace_all(out, "><", ">\n<");
|
||||
}
|
||||
|
||||
if (!out.empty()) {
|
||||
if (!mz_zip_writer_add_mem(&archive, CUT_INFORMATION_FILE.c_str(), (const void *) out.data(), out.length(), MZ_DEFAULT_COMPRESSION)) {
|
||||
add_error("Unable to add cut information file to archive");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_slice_info_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
@ -7105,7 +7551,10 @@ public:
|
|||
while (true)
|
||||
{
|
||||
while (m_tasks.empty()) {
|
||||
m_cond.timed_wait(lock, m_next_backup);
|
||||
if (m_interval > 0)
|
||||
m_cond.timed_wait(lock, m_next_backup);
|
||||
else
|
||||
m_cond.wait(lock);
|
||||
if (m_interval > 0 && boost::get_system_time() > m_next_backup) {
|
||||
m_tasks.push_back({ Backup, 0, std::string(), nullptr, ++m_task_seq });
|
||||
m_next_backup += boost::posix_time::seconds(m_interval);
|
||||
|
|
|
@ -16,7 +16,9 @@ struct ThumbnailData;
|
|||
|
||||
#define GCODE_FILE_FORMAT "Metadata/plate_%1%.gcode"
|
||||
#define THUMBNAIL_FILE_FORMAT "Metadata/plate_%1%.png"
|
||||
#define PATTERN_FILE_FORMAT "Metadata/plate_%1%_pattern_layer_0.png"
|
||||
#define TOP_FILE_FORMAT "Metadata/top_%1%.png"
|
||||
#define PICK_FILE_FORMAT "Metadata/pick_%1%.png"
|
||||
//#define PATTERN_FILE_FORMAT "Metadata/plate_%1%_pattern_layer_0.png"
|
||||
#define PATTERN_CONFIG_FILE_FORMAT "Metadata/plate_%1%.json"
|
||||
#define EMBEDDED_PRINT_FILE_FORMAT "Metadata/process_settings_%1%.config"
|
||||
#define EMBEDDED_FILAMENT_FILE_FORMAT "Metadata/filament_settings_%1%.config"
|
||||
|
@ -65,8 +67,10 @@ struct PlateData
|
|||
std::string gcode_file_md5;
|
||||
std::string thumbnail_file;
|
||||
ThumbnailData plate_thumbnail;
|
||||
ThumbnailData pattern_thumbnail;
|
||||
std::string pattern_file;
|
||||
std::string top_file;
|
||||
std::string pick_file;
|
||||
//ThumbnailData pattern_thumbnail;
|
||||
//std::string pattern_file;
|
||||
std::string pattern_bbox_file;
|
||||
std::string gcode_prediction;
|
||||
std::string gcode_weight;
|
||||
|
@ -103,6 +107,7 @@ enum class SaveStrategy
|
|||
SkipModel = 1 << 7,
|
||||
WithSliceInfo = 1 << 8,
|
||||
SkipAuxiliary = 1 << 9,
|
||||
UseLoadedId = 1 << 10,
|
||||
|
||||
SplitModel = 0x1000 | ProductionExt,
|
||||
Encrypted = SecureContentExt | SplitModel,
|
||||
|
@ -195,6 +200,8 @@ struct StoreParams
|
|||
std::vector<Preset*> project_presets;
|
||||
DynamicPrintConfig* config;
|
||||
std::vector<ThumbnailData*> thumbnail_data;
|
||||
std::vector<ThumbnailData*> top_thumbnail_data;
|
||||
std::vector<ThumbnailData*> pick_thumbnail_data;
|
||||
std::vector<ThumbnailData*> calibration_thumbnail_data;
|
||||
SaveStrategy strategy = SaveStrategy::Zip64;
|
||||
Export3mfProgressFn proFn = nullptr;
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "TopExp_Explorer.hxx"
|
||||
#include "TopoDS.hxx"
|
||||
#include "BRepExtrema_SelfIntersection.hxx"
|
||||
#include "clipper/clipper.hpp"
|
||||
|
||||
using namespace ClipperLib;
|
||||
|
||||
namespace Slic3r {
|
||||
const double STEP_TRANS_CHORD_ERROR = 0.005;
|
||||
|
@ -188,7 +191,8 @@ bool get_svg_profile(const char *path, std::vector<Element_Info> &element_infos,
|
|||
}
|
||||
}
|
||||
// keep the start and end points of profile connected
|
||||
profile_line_points.back().second = profile_line_points[0].first;
|
||||
if (shape->fill.gradient != nullptr)
|
||||
profile_line_points.back().second = profile_line_points[0].first;
|
||||
|
||||
if (is_profile_self_interaction(profile_line_points))
|
||||
BOOST_LOG_TRIVIAL(warning) << "the profile is self interaction.";
|
||||
|
@ -196,6 +200,56 @@ bool get_svg_profile(const char *path, std::vector<Element_Info> &element_infos,
|
|||
path_line_points.push_back(profile_line_points);
|
||||
}
|
||||
|
||||
if (shape->fill.gradient == nullptr) {
|
||||
double scale_size = 1e6;
|
||||
std::vector<std::vector<std::pair<gp_Pnt, gp_Pnt>>> new_path_line_points;
|
||||
float stroke_width = shape->strokeWidth * scale_size;
|
||||
Polygons polygons;
|
||||
bool close_polygon = false;
|
||||
for (int i = 0; i < path_line_points.size(); ++i) {
|
||||
ClipperLib::Path pt_path;
|
||||
for (auto line_point : path_line_points[i]) {
|
||||
pt_path.push_back(IntPoint(line_point.first.X() * scale_size, line_point.first.Y() * scale_size));
|
||||
}
|
||||
pt_path.push_back(IntPoint(path_line_points[i].back().second.X() * scale_size, path_line_points[i].back().second.Y() * scale_size));
|
||||
|
||||
ClipperLib::Paths out_paths;
|
||||
ClipperLib::ClipperOffset co;
|
||||
if (pt_path.front() == pt_path.back()) {
|
||||
co.AddPath(pt_path, ClipperLib::jtMiter, ClipperLib::etClosedLine);
|
||||
close_polygon = true;
|
||||
} else {
|
||||
co.AddPath(pt_path, ClipperLib::jtMiter, ClipperLib::etOpenSquare);
|
||||
close_polygon = false;
|
||||
}
|
||||
co.Execute(out_paths, stroke_width / 2);
|
||||
|
||||
for (auto out_path : out_paths) {
|
||||
polygons.emplace_back(Polygon(out_path));
|
||||
}
|
||||
}
|
||||
|
||||
if (!close_polygon)
|
||||
polygons = union_(polygons);
|
||||
|
||||
std::vector<std::pair<gp_Pnt, gp_Pnt>> profile_line_points;
|
||||
for (auto polygon : polygons) {
|
||||
profile_line_points.clear();
|
||||
for (int i = 0; i < polygon.size() - 1; ++i) {
|
||||
gp_Pnt pt1(double(polygon[i][0] / scale_size), double(polygon[i][1] / scale_size), 0);
|
||||
gp_Pnt pt2(double(polygon[i + 1][0] / scale_size), double(polygon[i + 1][1] / scale_size), 0);
|
||||
profile_line_points.push_back({pt1, pt2});
|
||||
}
|
||||
gp_Pnt pt1(double(polygon.back()[0] / scale_size), double(polygon.back()[1] / scale_size), 0);
|
||||
gp_Pnt pt2(double(polygon.front()[0] / scale_size), double(polygon.front()[1] / scale_size), 0);
|
||||
profile_line_points.push_back({pt1, pt2});
|
||||
|
||||
new_path_line_points.push_back(profile_line_points);
|
||||
}
|
||||
|
||||
path_line_points = new_path_line_points;
|
||||
}
|
||||
|
||||
// generate all profile curves
|
||||
std::vector<TopoDS_Wire> wires;
|
||||
int index = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue