When importing 3mf which had texture mapping zones, make sure to assign or create a zone so textures are still visible
This commit is contained in:
@@ -1821,6 +1821,7 @@ static void append_triangle_material_data(std::vector<uint8_t> &uv_valid,
|
||||
void _extract_print_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, ConfigSubstitutionContext& subs_context, const std::string& archive_filename);
|
||||
//BBS: add project config file logic
|
||||
void _extract_project_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config, ConfigSubstitutionContext& subs_context, Model& model);
|
||||
void _extract_texture_mapping_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config);
|
||||
//BBS: extract project embedded presets
|
||||
void _extract_project_embedded_presets_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, std::vector<Preset*>&project_presets, Model& model, Preset::Type type, bool use_json = true);
|
||||
|
||||
@@ -2591,9 +2592,12 @@ static void append_triangle_material_data(std::vector<uint8_t> &uv_valid,
|
||||
// extract slic3r print config file
|
||||
// _extract_print_config_from_archive(archive, stat, config, config_substitutions, filename);
|
||||
//} else
|
||||
if (!dont_load_config && boost::algorithm::iequals(name, BBS_PROJECT_CONFIG_FILE)) {
|
||||
if (boost::algorithm::iequals(name, BBS_PROJECT_CONFIG_FILE)) {
|
||||
// extract slic3r print config file
|
||||
_extract_project_config_from_archive(archive, stat, config, config_substitutions, model);
|
||||
if (!dont_load_config)
|
||||
_extract_project_config_from_archive(archive, stat, config, config_substitutions, model);
|
||||
else
|
||||
_extract_texture_mapping_config_from_archive(archive, stat, config);
|
||||
}
|
||||
else if (boost::algorithm::iequals(name, CUT_INFORMATION_FILE)) {
|
||||
// extract object cut info
|
||||
@@ -3331,6 +3335,37 @@ static void append_triangle_material_data(std::vector<uint8_t> &uv_valid,
|
||||
}
|
||||
}
|
||||
|
||||
void _BBS_3MF_Importer::_extract_texture_mapping_config_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, DynamicPrintConfig& config)
|
||||
{
|
||||
if (stat.m_uncomp_size == 0)
|
||||
return;
|
||||
|
||||
std::string buffer(size_t(stat.m_uncomp_size), 0);
|
||||
mz_bool res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, (void *)buffer.data(), size_t(stat.m_uncomp_size), 0);
|
||||
if (res == 0)
|
||||
return;
|
||||
|
||||
try {
|
||||
const nlohmann::json root = nlohmann::json::parse(buffer);
|
||||
const auto texture_defs_it = root.find("texture_mapping_definitions");
|
||||
if (texture_defs_it != root.end() && texture_defs_it->is_string())
|
||||
config.set_key_value("texture_mapping_definitions", new ConfigOptionString(texture_defs_it->get<std::string>()));
|
||||
|
||||
const auto filament_colour_it = root.find("filament_colour");
|
||||
if (filament_colour_it != root.end() && filament_colour_it->is_array()) {
|
||||
std::vector<std::string> colors;
|
||||
colors.reserve(filament_colour_it->size());
|
||||
for (const nlohmann::json &entry : *filament_colour_it)
|
||||
if (entry.is_string())
|
||||
colors.emplace_back(entry.get<std::string>());
|
||||
if (!colors.empty())
|
||||
config.set_key_value("filament_colour", new ConfigOptionStrings(std::move(colors)));
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "_extract_texture_mapping_config_from_archive JSON parse failed: " << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
//BBS: extract project embedded presets
|
||||
void _BBS_3MF_Importer::_extract_project_embedded_presets_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, std::vector<Preset*>&project_presets, Model& model, Preset::Type type, bool use_json)
|
||||
{
|
||||
|
||||
@@ -641,9 +641,9 @@ static bool assign_imported_texture_mapping_zone(Model &model)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool texture_mapping_config_uses_zone_id(const ConfigOptionResolver &config, unsigned int zone_id)
|
||||
static const std::array<const char *, 6> &texture_mapping_filament_config_keys()
|
||||
{
|
||||
static constexpr std::array<const char *, 6> filament_keys = {
|
||||
static const std::array<const char *, 6> filament_keys = {
|
||||
"extruder",
|
||||
"wall_filament",
|
||||
"sparse_infill_filament",
|
||||
@@ -651,8 +651,13 @@ static bool texture_mapping_config_uses_zone_id(const ConfigOptionResolver &conf
|
||||
"support_filament",
|
||||
"support_interface_filament"
|
||||
};
|
||||
return filament_keys;
|
||||
}
|
||||
|
||||
static bool texture_mapping_config_uses_zone_id(const ConfigOptionResolver &config, unsigned int zone_id)
|
||||
{
|
||||
const int target = int(zone_id);
|
||||
for (const char *key : filament_keys) {
|
||||
for (const char *key : texture_mapping_filament_config_keys()) {
|
||||
const ConfigOptionInt *opt = dynamic_cast<const ConfigOptionInt *>(config.option(key));
|
||||
if (opt != nullptr && opt->getInt() == target)
|
||||
return true;
|
||||
@@ -687,6 +692,121 @@ static bool model_uses_texture_mapping_zone_id(const Model &model, const ConfigO
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::set<unsigned int> texture_mapping_zone_ids_from_import_config(const DynamicPrintConfig &config)
|
||||
{
|
||||
const ConfigOptionString *defs = config.option<ConfigOptionString>("texture_mapping_definitions");
|
||||
if (defs == nullptr || defs->value.empty())
|
||||
return {};
|
||||
|
||||
std::set<unsigned int> ids;
|
||||
try {
|
||||
const json root = json::parse(defs->value);
|
||||
if (!root.is_array())
|
||||
return {};
|
||||
for (const json &entry : root) {
|
||||
if (!entry.is_object() || !entry.value("enabled", true))
|
||||
continue;
|
||||
const unsigned int zone_id = entry.value("zone_id", entry.value("filament_id", 0u));
|
||||
if (zone_id != 0)
|
||||
ids.insert(zone_id);
|
||||
}
|
||||
} catch (...) {
|
||||
ids.clear();
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
static bool store_texture_mapping_definitions(PresetBundle &bundle)
|
||||
{
|
||||
const std::string serialized = bundle.texture_mapping_zones.serialize_entries();
|
||||
DynamicPrintConfig &project_config = bundle.project_config;
|
||||
if (ConfigOptionString *opt = project_config.option<ConfigOptionString>("texture_mapping_definitions"))
|
||||
opt->value = serialized;
|
||||
else
|
||||
project_config.set_key_value("texture_mapping_definitions", new ConfigOptionString(serialized));
|
||||
|
||||
DynamicPrintConfig &print_config = bundle.prints.get_edited_preset().config;
|
||||
if (ConfigOptionString *opt = print_config.option<ConfigOptionString>("texture_mapping_definitions"))
|
||||
opt->value = serialized;
|
||||
else
|
||||
print_config.set_key_value("texture_mapping_definitions", new ConfigOptionString(serialized));
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int ensure_texture_mapping_import_target_zone(PresetBundle &bundle, bool &changed)
|
||||
{
|
||||
DynamicPrintConfig &project_config = bundle.project_config;
|
||||
const ConfigOptionStrings *color_opt = project_config.option<ConfigOptionStrings>("filament_colour", false);
|
||||
if (color_opt == nullptr || color_opt->values.size() < 2)
|
||||
return 0;
|
||||
|
||||
project_config.option<ConfigOptionString>("texture_mapping_definitions", true);
|
||||
bundle.texture_mapping_zones.load_entries(project_config.opt_string("texture_mapping_definitions"), color_opt->values);
|
||||
for (const unsigned int zone_id : bundle.texture_mapping_zones.zone_ids_by_index())
|
||||
if (zone_id != 0)
|
||||
return zone_id;
|
||||
|
||||
const unsigned int zone_id = bundle.texture_mapping_zones.ensure_image_texture_zone(color_opt->values.size(), color_opt->values);
|
||||
if (zone_id != 0)
|
||||
changed |= store_texture_mapping_definitions(bundle);
|
||||
return zone_id;
|
||||
}
|
||||
|
||||
static bool remap_texture_mapping_model_config(ModelConfig &config, const std::set<unsigned int> &source_zone_ids, unsigned int target_zone_id)
|
||||
{
|
||||
bool changed = false;
|
||||
for (const char *key : texture_mapping_filament_config_keys()) {
|
||||
const ConfigOptionInt *opt = dynamic_cast<const ConfigOptionInt *>(config.option(key));
|
||||
if (opt == nullptr || source_zone_ids.find(unsigned(opt->getInt())) == source_zone_ids.end())
|
||||
continue;
|
||||
if (opt->getInt() != int(target_zone_id)) {
|
||||
config.set(key, int(target_zone_id));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
static bool assign_imported_3mf_texture_mapping_zones(Model &model, const std::set<unsigned int> &source_zone_ids)
|
||||
{
|
||||
if (source_zone_ids.empty())
|
||||
return false;
|
||||
|
||||
std::set<unsigned int> used_zone_ids;
|
||||
for (const unsigned int zone_id : source_zone_ids)
|
||||
if (model_uses_texture_mapping_zone_id(model, nullptr, zone_id))
|
||||
used_zone_ids.insert(zone_id);
|
||||
if (used_zone_ids.empty())
|
||||
return false;
|
||||
|
||||
PresetBundle *bundle = wxGetApp().preset_bundle;
|
||||
if (bundle == nullptr)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
const unsigned int target_zone_id = ensure_texture_mapping_import_target_zone(*bundle, changed);
|
||||
if (target_zone_id == 0)
|
||||
return changed;
|
||||
|
||||
for (ModelObject *object : model.objects) {
|
||||
if (object == nullptr)
|
||||
continue;
|
||||
changed |= remap_texture_mapping_model_config(object->config, used_zone_ids, target_zone_id);
|
||||
for (auto &layer_range : object->layer_config_ranges)
|
||||
changed |= remap_texture_mapping_model_config(layer_range.second, used_zone_ids, target_zone_id);
|
||||
for (ModelVolume *volume : object->volumes)
|
||||
if (volume != nullptr)
|
||||
changed |= remap_texture_mapping_model_config(volume->config, used_zone_ids, target_zone_id);
|
||||
}
|
||||
|
||||
std::map<unsigned int, unsigned int> state_map;
|
||||
for (const unsigned int zone_id : used_zone_ids)
|
||||
if (zone_id != target_zone_id)
|
||||
state_map[zone_id] = target_zone_id;
|
||||
changed |= remap_mmu_segmentation_filaments(model, state_map);
|
||||
return changed;
|
||||
}
|
||||
|
||||
static wxColour parse_texture_mapping_color(const std::string &hex)
|
||||
{
|
||||
unsigned char rgba[4] = {38, 166, 154, 255};
|
||||
@@ -8781,6 +8901,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
// const bool type_prusa = std::regex_match(path.string(), pattern_prusa);
|
||||
|
||||
Slic3r::Model model;
|
||||
std::set<unsigned int> imported_texture_mapping_zone_ids;
|
||||
// BBS: add auxiliary files related logic
|
||||
bool load_aux = strategy & LoadStrategy::LoadAuxiliary, load_old_project = false;
|
||||
if (load_model && load_config && type_3mf) {
|
||||
@@ -8818,9 +8939,14 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
if (cancel)
|
||||
is_user_cancel = cancel;
|
||||
});
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__
|
||||
<< boost::format(", plate_data.size %1%, project_preset.size %2%, is_bbs_or_orca_3mf %3%, file_version %4% \n") % plate_data.size() %
|
||||
project_presets.size() % (en_3mf_file_type == En3mfType::From_BBS || en_3mf_file_type == En3mfType::From_Orca) % file_version.to_string();
|
||||
imported_texture_mapping_zone_ids = texture_mapping_zone_ids_from_import_config(config_loaded);
|
||||
if (load_model && !load_config && assign_imported_3mf_texture_mapping_zones(model, imported_texture_mapping_zone_ids)) {
|
||||
sidebar->update_texture_mapping_panel(false);
|
||||
sidebar->update_dynamic_filament_list();
|
||||
}
|
||||
|
||||
// 1. add extruder for prusa model if the number of existing extruders is not enough
|
||||
// 2. add extruder for BBS or Other model if only import geometry
|
||||
@@ -9551,7 +9677,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
// convert_model_if(model, answer_convert_from_imperial_units == wxID_YES);
|
||||
}
|
||||
|
||||
if (!is_project_file && model.looks_like_multipart_object()) {
|
||||
if (!is_project_file && model.looks_like_multipart_object()) {
|
||||
MessageDialog msg_dlg(q, _L(
|
||||
"This file contains several objects positioned at multiple heights.\n"
|
||||
"Instead of considering them as multiple objects, should \n"
|
||||
@@ -9561,6 +9687,10 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
||||
model.convert_multipart_object(filaments_cnt);
|
||||
}
|
||||
}
|
||||
if (type_3mf && load_model && !load_config && assign_imported_3mf_texture_mapping_zones(model, imported_texture_mapping_zone_ids)) {
|
||||
sidebar->update_texture_mapping_panel(false);
|
||||
sidebar->update_dynamic_filament_list();
|
||||
}
|
||||
}
|
||||
// else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) {
|
||||
// MessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n",
|
||||
|
||||
Reference in New Issue
Block a user