diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp
index 0e44cc14ea..ad428a7357 100644
--- a/src/libslic3r/Format/3mf.cpp
+++ b/src/libslic3r/Format/3mf.cpp
@@ -121,18 +121,21 @@ static constexpr const char* LAST_TRIANGLE_ID_ATTR = "lastid";
static constexpr const char* OBJECT_TYPE = "object";
static constexpr const char* VOLUME_TYPE = "volume";
-static constexpr const char* NAME_KEY = "name";
-static constexpr const char* MODIFIER_KEY = "modifier";
+static constexpr const char* NAME_KEY = "name";
+static constexpr const char* MODIFIER_KEY = "modifier";
static constexpr const char* VOLUME_TYPE_KEY = "volume_type";
-static constexpr const char* MATRIX_KEY = "matrix";
-static constexpr const char* SOURCE_FILE_KEY = "source_file";
-static constexpr const char* SOURCE_OBJECT_ID_KEY = "source_object_id";
-static constexpr const char* SOURCE_VOLUME_ID_KEY = "source_volume_id";
-static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x";
-static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
-static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
-static constexpr const char* SOURCE_IN_INCHES = "source_in_inches";
-static constexpr const char* SOURCE_IN_METERS = "source_in_meters";
+static constexpr const char* MATRIX_KEY = "matrix";
+static constexpr const char* SOURCE_FILE_KEY = "source_file";
+static constexpr const char* SOURCE_OBJECT_ID_KEY = "source_object_id";
+static constexpr const char* SOURCE_VOLUME_ID_KEY = "source_volume_id";
+static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x";
+static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y";
+static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z";
+static constexpr const char* SOURCE_IN_INCHES_KEY = "source_in_inches";
+static constexpr const char* SOURCE_IN_METERS_KEY = "source_in_meters";
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+static constexpr const char* SOURCE_IS_BUILTIN_VOLUME_KEY = "source_is_builtin_volume";
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
static constexpr const char* MESH_STAT_EDGES_FIXED = "edges_fixed";
static constexpr const char* MESH_STAT_DEGENERATED_FACETS = "degenerate_facets";
@@ -816,6 +819,20 @@ namespace Slic3r {
return false;
}
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ for (int obj_id = 0; obj_id < int(model.objects.size()); ++obj_id) {
+ ModelObject* o = model.objects[obj_id];
+ for (int vol_id = 0; vol_id < int(o->volumes.size()); ++vol_id) {
+ ModelVolume* v = o->volumes[vol_id];
+ if (v->source.input_file.empty())
+ v->source.input_file = v->name.empty() ? filename : v->name;
+ if (v->source.volume_idx == -1)
+ v->source.volume_idx = vol_id;
+ if (v->source.object_idx == -1)
+ v->source.object_idx = obj_id;
+ }
+ }
+#else
int object_idx = 0;
for (ModelObject* o : model.objects) {
int volume_idx = 0;
@@ -831,6 +848,7 @@ namespace Slic3r {
}
++object_idx;
}
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
// // fixes the min z of the model if negative
// model.adjust_min_z();
@@ -2052,15 +2070,19 @@ namespace Slic3r {
else if (metadata.key == SOURCE_VOLUME_ID_KEY)
volume->source.volume_idx = ::atoi(metadata.value.c_str());
else if (metadata.key == SOURCE_OFFSET_X_KEY)
- volume->source.mesh_offset(0) = ::atof(metadata.value.c_str());
+ volume->source.mesh_offset.x() = ::atof(metadata.value.c_str());
else if (metadata.key == SOURCE_OFFSET_Y_KEY)
- volume->source.mesh_offset(1) = ::atof(metadata.value.c_str());
+ volume->source.mesh_offset.y() = ::atof(metadata.value.c_str());
else if (metadata.key == SOURCE_OFFSET_Z_KEY)
- volume->source.mesh_offset(2) = ::atof(metadata.value.c_str());
- else if (metadata.key == SOURCE_IN_INCHES)
+ volume->source.mesh_offset.z() = ::atof(metadata.value.c_str());
+ else if (metadata.key == SOURCE_IN_INCHES_KEY)
volume->source.is_converted_from_inches = metadata.value == "1";
- else if (metadata.key == SOURCE_IN_METERS)
+ else if (metadata.key == SOURCE_IN_METERS_KEY)
volume->source.is_converted_from_meters = metadata.value == "1";
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ else if (metadata.key == SOURCE_IS_BUILTIN_VOLUME_KEY)
+ volume->source.is_from_builtin_objects = metadata.value == "1";
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
else
volume->config.set_deserialize(metadata.key, metadata.value, config_substitutions);
}
@@ -2981,7 +3003,7 @@ namespace Slic3r {
// stores volume's local matrix
stream << " <" << METADATA_TAG << " " << TYPE_ATTR << "=\"" << VOLUME_TYPE << "\" " << KEY_ATTR << "=\"" << MATRIX_KEY << "\" " << VALUE_ATTR << "=\"";
- Transform3d matrix = volume->get_matrix() * volume->source.transform.get_matrix();
+ const Transform3d matrix = volume->get_matrix() * volume->source.transform.get_matrix();
for (int r = 0; r < 4; ++r) {
for (int c = 0; c < 4; ++c) {
stream << matrix(r, c);
@@ -3005,9 +3027,13 @@ namespace Slic3r {
}
assert(! volume->source.is_converted_from_inches || ! volume->source.is_converted_from_meters);
if (volume->source.is_converted_from_inches)
- stream << prefix << SOURCE_IN_INCHES << "\" " << VALUE_ATTR << "=\"1\"/>\n";
+ stream << prefix << SOURCE_IN_INCHES_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n";
else if (volume->source.is_converted_from_meters)
- stream << prefix << SOURCE_IN_METERS << "\" " << VALUE_ATTR << "=\"1\"/>\n";
+ stream << prefix << SOURCE_IN_METERS_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n";
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ if (volume->source.is_from_builtin_objects)
+ stream << prefix << SOURCE_IS_BUILTIN_VOLUME_KEY << "\" " << VALUE_ATTR << "=\"1\"/>\n";
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
}
// stores volume's config data
diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp
index a8b66b15b1..f2a902758e 100644
--- a/src/libslic3r/Format/AMF.cpp
+++ b/src/libslic3r/Format/AMF.cpp
@@ -657,11 +657,16 @@ void AMFParserContext::endElement(const char * /* name */)
if (bool has_transform = !m_volume_transform.isApprox(Transform3d::Identity(), 1e-10); has_transform)
m_volume->source.transform = Slic3r::Geometry::Transformation(m_volume_transform);
- if (m_volume->source.input_file.empty() && (m_volume->type() == ModelVolumeType::MODEL_PART)) {
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ if (m_volume->source.input_file.empty()) {
+#else
+ if (m_volume->source.input_file.empty() && m_volume->type() == ModelVolumeType::MODEL_PART) {
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
m_volume->source.object_idx = (int)m_model.objects.size() - 1;
m_volume->source.volume_idx = (int)m_model.objects.back()->volumes.size() - 1;
m_volume->center_geometry_after_creation();
- } else
+ }
+ else
// pass false if the mesh offset has been already taken from the data
m_volume->center_geometry_after_creation(m_volume->source.input_file.empty());
@@ -792,46 +797,44 @@ void AMFParserContext::endElement(const char * /* name */)
// Is this volume a modifier volume?
// "modifier" flag comes first in the XML file, so it may be later overwritten by the "type" flag.
m_volume->set_type((atoi(m_value[1].c_str()) == 1) ? ModelVolumeType::PARAMETER_MODIFIER : ModelVolumeType::MODEL_PART);
- } else if (strcmp(opt_key, "volume_type") == 0) {
+ }
+ else if (strcmp(opt_key, "volume_type") == 0)
m_volume->set_type(ModelVolume::type_from_string(m_value[1]));
- }
- else if (strcmp(opt_key, "matrix") == 0) {
+ else if (strcmp(opt_key, "matrix") == 0)
m_volume_transform = Slic3r::Geometry::transform3d_from_string(m_value[1]);
- }
- else if (strcmp(opt_key, "source_file") == 0) {
+ else if (strcmp(opt_key, "source_file") == 0)
m_volume->source.input_file = m_value[1];
- }
- else if (strcmp(opt_key, "source_object_id") == 0) {
+ else if (strcmp(opt_key, "source_object_id") == 0)
m_volume->source.object_idx = ::atoi(m_value[1].c_str());
- }
- else if (strcmp(opt_key, "source_volume_id") == 0) {
+ else if (strcmp(opt_key, "source_volume_id") == 0)
m_volume->source.volume_idx = ::atoi(m_value[1].c_str());
- }
- else if (strcmp(opt_key, "source_offset_x") == 0) {
- m_volume->source.mesh_offset(0) = ::atof(m_value[1].c_str());
- }
- else if (strcmp(opt_key, "source_offset_y") == 0) {
- m_volume->source.mesh_offset(1) = ::atof(m_value[1].c_str());
- }
- else if (strcmp(opt_key, "source_offset_z") == 0) {
- m_volume->source.mesh_offset(2) = ::atof(m_value[1].c_str());
- }
- else if (strcmp(opt_key, "source_in_inches") == 0) {
+ else if (strcmp(opt_key, "source_offset_x") == 0)
+ m_volume->source.mesh_offset.x() = ::atof(m_value[1].c_str());
+ else if (strcmp(opt_key, "source_offset_y") == 0)
+ m_volume->source.mesh_offset.y() = ::atof(m_value[1].c_str());
+ else if (strcmp(opt_key, "source_offset_z") == 0)
+ m_volume->source.mesh_offset.z() = ::atof(m_value[1].c_str());
+ else if (strcmp(opt_key, "source_in_inches") == 0)
m_volume->source.is_converted_from_inches = m_value[1] == "1";
- }
- else if (strcmp(opt_key, "source_in_meters") == 0) {
+ else if (strcmp(opt_key, "source_in_meters") == 0)
m_volume->source.is_converted_from_meters = m_value[1] == "1";
- }
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ else if (strcmp(opt_key, "source_is_builtin_volume") == 0)
+ m_volume->source.is_from_builtin_objects = m_value[1] == "1";
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
}
- } else if (m_path.size() == 3) {
+ }
+ else if (m_path.size() == 3) {
if (m_path[1] == NODE_TYPE_MATERIAL) {
if (m_material)
m_material->attributes[m_value[0]] = m_value[1];
- } else if (m_path[1] == NODE_TYPE_OBJECT) {
+ }
+ else if (m_path[1] == NODE_TYPE_OBJECT) {
if (m_object && m_value[0] == "name")
m_object->name = std::move(m_value[1]);
}
- } else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME) {
+ }
+ else if (m_path.size() == 5 && m_path[3] == NODE_TYPE_VOLUME) {
if (m_volume && m_value[0] == "name")
m_volume->name = std::move(m_value[1]);
}
@@ -919,7 +922,11 @@ bool load_amf_file(const char *path, DynamicPrintConfig *config, ConfigSubstitut
unsigned int counter = 0;
for (ModelVolume* v : o->volumes) {
++counter;
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ if (v->source.input_file.empty())
+#else
if (v->source.input_file.empty() && v->type() == ModelVolumeType::MODEL_PART)
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
v->source.input_file = path;
if (v->name.empty()) {
v->name = o->name;
@@ -1068,7 +1075,11 @@ bool load_amf_archive(const char* path, DynamicPrintConfig* config, ConfigSubsti
for (ModelObject *o : model->objects)
for (ModelVolume *v : o->volumes)
- if (v->source.input_file.empty() && (v->type() == ModelVolumeType::MODEL_PART))
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ if (v->source.input_file.empty())
+#else
+ if (v->source.input_file.empty() && v->type() == ModelVolumeType::MODEL_PART)
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
v->source.input_file = path;
return true;
@@ -1237,18 +1248,15 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
stream << " ";
const Transform3d& matrix = volume->get_matrix() * volume->source.transform.get_matrix();
stream << std::setprecision(std::numeric_limits::max_digits10);
- for (int r = 0; r < 4; ++r)
- {
- for (int c = 0; c < 4; ++c)
- {
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
stream << matrix(r, c);
- if ((r != 3) || (c != 3))
+ if (r != 3 || c != 3)
stream << " ";
}
}
stream << "\n";
- if (!volume->source.input_file.empty())
- {
+ if (!volume->source.input_file.empty()) {
std::string input_file = xml_escape(fullpath_sources ? volume->source.input_file : boost::filesystem::path(volume->source.input_file).filename().string());
stream << " " << input_file << "\n";
stream << " " << volume->source.object_idx << "\n";
@@ -1262,12 +1270,16 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
stream << " 1\n";
else if (volume->source.is_converted_from_meters)
stream << " 1\n";
- stream << std::setprecision(std::numeric_limits::max_digits10);
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ if (volume->source.is_from_builtin_objects)
+ stream << " 1\n";
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
+ stream << std::setprecision(std::numeric_limits::max_digits10);
const indexed_triangle_set &its = volume->mesh().its;
for (size_t i = 0; i < its.indices.size(); ++i) {
stream << " \n";
for (int j = 0; j < 3; ++j)
- stream << " " << its.indices[i][j] + vertices_offset << "\n";
+ stream << " " << its.indices[i][j] + vertices_offset << "\n";
stream << " \n";
}
stream << " \n";
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 52c9e10d3c..da55ae4ff4 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -70,6 +70,8 @@
#define ENABLE_GLBEGIN_GLEND_REMOVAL (1 && ENABLE_2_5_0_ALPHA1)
// Enable show non-manifold edges
#define ENABLE_SHOW_NON_MANIFOLD_EDGES (1 && ENABLE_2_5_0_ALPHA1)
+// Enable rework of Reload from disk command
+#define ENABLE_RELOAD_FROM_DISK_REWORK (1 && ENABLE_2_5_0_ALPHA1)
#endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 2b551eaca1..27c374b3f8 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -1691,16 +1691,16 @@ void ObjectList::load_shape_object(const std::string& type_name)
if (selection.get_object_idx() != -1)
return;
- const int obj_idx = m_objects->size();
- if (obj_idx < 0)
- return;
-
take_snapshot(_L("Add Shape"));
// Create mesh
BoundingBoxf3 bb;
TriangleMesh mesh = create_mesh(type_name, bb);
load_mesh_object(mesh, _L("Shape") + "-" + _(type_name));
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ if (!m_objects->empty())
+ m_objects->back()->volumes.front()->source.is_from_builtin_objects = true;
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
wxGetApp().mainframe->update_title();
}
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index a6447745cb..ecdd857e1c 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -3531,8 +3531,45 @@ void Plater::priv::replace_with_stl()
}
}
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+static std::vector> reloadable_volumes(const Model& model, const Selection& selection)
+{
+ std::vector> ret;
+ const std::set& selected_volumes_idxs = selection.get_volume_idxs();
+ for (unsigned int idx : selected_volumes_idxs) {
+ const GLVolume& v = *selection.get_volume(idx);
+ const int o_idx = v.object_idx();
+ if (0 <= o_idx && o_idx < int(model.objects.size())) {
+ const ModelObject* obj = model.objects[o_idx];
+ const int v_idx = v.volume_idx();
+ if (0 <= v_idx && v_idx < int(obj->volumes.size())) {
+ const ModelVolume* vol = obj->volumes[v_idx];
+ if (!vol->source.is_from_builtin_objects && !vol->source.input_file.empty() &&
+ vol->source.input_file != obj->input_file && !fs::path(vol->source.input_file).extension().string().empty())
+ ret.push_back({ o_idx, v_idx });
+ }
+ }
+ }
+ return ret;
+}
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
+
void Plater::priv::reload_from_disk()
{
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ // collect selected reloadable ModelVolumes
+ std::vector> selected_volumes = reloadable_volumes(model, get_selection());
+
+ // nothing to reload, return
+ if (selected_volumes.empty())
+ return;
+
+ std::sort(selected_volumes.begin(), selected_volumes.end(), [](const std::pair& v1, const std::pair& v2) {
+ return (v1.first < v2.first) || (v1.first == v2.first && v1.second < v2.second);
+ });
+ selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end(), [](const std::pair& v1, const std::pair& v2) {
+ return (v1.first == v2.first) && (v1.second == v2.second); }), selected_volumes.end());
+#else
Plater::TakeSnapshot snapshot(q, _L("Reload from disk"));
const Selection& selection = get_selection();
@@ -3565,10 +3602,36 @@ void Plater::priv::reload_from_disk()
}
std::sort(selected_volumes.begin(), selected_volumes.end());
selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end()), selected_volumes.end());
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
// collects paths of files to load
std::vector input_paths;
std::vector missing_input_paths;
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ std::vector> replace_paths;
+ for (auto [obj_idx, vol_idx] : selected_volumes) {
+ const ModelObject* object = model.objects[obj_idx];
+ const ModelVolume* volume = object->volumes[vol_idx];
+ if (fs::exists(volume->source.input_file))
+ input_paths.push_back(volume->source.input_file);
+ else {
+ // searches the source in the same folder containing the object
+ bool found = false;
+ if (!object->input_file.empty()) {
+ fs::path object_path = fs::path(object->input_file).remove_filename();
+ if (!object_path.empty()) {
+ object_path /= fs::path(volume->source.input_file).filename();
+ if (fs::exists(object_path)) {
+ input_paths.push_back(object_path);
+ found = true;
+ }
+ }
+ }
+ if (!found)
+ missing_input_paths.push_back(volume->source.input_file);
+ }
+ }
+#else
std::vector replace_paths;
for (const SelectedVolume& v : selected_volumes) {
const ModelObject* object = model.objects[v.object_idx];
@@ -3598,6 +3661,7 @@ void Plater::priv::reload_from_disk()
else if (!object->input_file.empty() && volume->is_model_part() && !volume->name.empty() && !volume->source.is_from_builtin_objects)
missing_input_paths.push_back(volume->name);
}
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
std::sort(missing_input_paths.begin(), missing_input_paths.end());
missing_input_paths.erase(std::unique(missing_input_paths.begin(), missing_input_paths.end()), missing_input_paths.end());
@@ -3641,7 +3705,11 @@ void Plater::priv::reload_from_disk()
//wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
MessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
if (dlg.ShowModal() == wxID_YES)
- replace_paths.push_back(sel_filename_path);
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ replace_paths.emplace_back(search, sel_filename_path);
+#else
+ replace_paths.emplace_back(sel_filename_path);
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
missing_input_paths.pop_back();
}
}
@@ -3652,6 +3720,10 @@ void Plater::priv::reload_from_disk()
std::sort(replace_paths.begin(), replace_paths.end());
replace_paths.erase(std::unique(replace_paths.begin(), replace_paths.end()), replace_paths.end());
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ Plater::TakeSnapshot snapshot(q, _L("Reload from disk"));
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
+
std::vector fail_list;
Busy busy(_L("Reload from:"), q->get_current_canvas3D()->get_wxglcanvas());
@@ -3680,6 +3752,86 @@ void Plater::priv::reload_from_disk()
}
// update the selected volumes whose source is the current file
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ for (auto [obj_idx, vol_idx] : selected_volumes) {
+ ModelObject* old_model_object = model.objects[obj_idx];
+ ModelVolume* old_volume = old_model_object->volumes[vol_idx];
+
+ bool sinking = old_model_object->bounding_box().min.z() < SINKING_Z_THRESHOLD;
+
+ bool has_source = !old_volume->source.input_file.empty() && boost::algorithm::iequals(fs::path(old_volume->source.input_file).filename().string(), fs::path(path).filename().string());
+ bool has_name = !old_volume->name.empty() && boost::algorithm::iequals(old_volume->name, fs::path(path).filename().string());
+ if (has_source || has_name) {
+ int new_volume_idx = -1;
+ int new_object_idx = -1;
+ bool match_found = false;
+ // take idxs from the matching volume
+ if (has_source && old_volume->source.object_idx < int(new_model.objects.size())) {
+ const ModelObject* obj = new_model.objects[old_volume->source.object_idx];
+ if (old_volume->source.volume_idx < int(obj->volumes.size())) {
+ if (obj->volumes[old_volume->source.volume_idx]->name == old_volume->name) {
+ new_volume_idx = old_volume->source.volume_idx;
+ new_object_idx = old_volume->source.object_idx;
+ match_found = true;
+ }
+ }
+ }
+
+ if (!match_found && has_name) {
+ // take idxs from the 1st matching volume
+ for (size_t o = 0; o < new_model.objects.size(); ++o) {
+ ModelObject* obj = new_model.objects[o];
+ bool found = false;
+ for (size_t v = 0; v < obj->volumes.size(); ++v) {
+ if (obj->volumes[v]->name == old_volume->name) {
+ new_volume_idx = (int)v;
+ new_object_idx = (int)o;
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+ }
+
+ if (new_object_idx < 0 || int(new_model.objects.size()) <= new_object_idx) {
+ fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));
+ continue;
+ }
+ ModelObject* new_model_object = new_model.objects[new_object_idx];
+ if (new_volume_idx < 0 || int(new_model_object->volumes.size()) <= new_volume_idx) {
+ fail_list.push_back(from_u8(has_source ? old_volume->source.input_file : old_volume->name));
+ continue;
+ }
+
+ old_model_object->add_volume(*new_model_object->volumes[new_volume_idx]);
+ ModelVolume* new_volume = old_model_object->volumes.back();
+ new_volume->set_new_unique_id();
+ new_volume->config.apply(old_volume->config);
+ new_volume->set_type(old_volume->type());
+ new_volume->set_material_id(old_volume->material_id());
+ new_volume->set_transformation(Geometry::assemble_transform(old_volume->source.transform.get_offset()) *
+ old_volume->get_transformation().get_matrix(true) *
+ old_volume->source.transform.get_matrix(true));
+ new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset));
+ new_volume->source.object_idx = old_volume->source.object_idx;
+ new_volume->source.volume_idx = old_volume->source.volume_idx;
+ assert(!old_volume->source.is_converted_from_inches || !old_volume->source.is_converted_from_meters);
+ if (old_volume->source.is_converted_from_inches)
+ new_volume->convert_from_imperial_units();
+ else if (old_volume->source.is_converted_from_meters)
+ new_volume->convert_from_meters();
+ std::swap(old_model_object->volumes[vol_idx], old_model_object->volumes.back());
+ old_model_object->delete_volume(old_model_object->volumes.size() - 1);
+ if (!sinking)
+ old_model_object->ensure_on_bed();
+ old_model_object->sort_volumes(wxGetApp().app_config->get("order_volumes") == "1");
+
+ sla::reproject_points_and_holes(old_model_object);
+ }
+ }
+#else
for (const SelectedVolume& sel_v : selected_volumes) {
ModelObject* old_model_object = model.objects[sel_v.object_idx];
ModelVolume* old_volume = old_model_object->volumes[sel_v.volume_idx];
@@ -3756,10 +3908,19 @@ void Plater::priv::reload_from_disk()
sla::reproject_points_and_holes(old_model_object);
}
}
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
}
busy.reset();
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ for (auto [src, dest] : replace_paths) {
+ for (auto [obj_idx, vol_idx] : selected_volumes) {
+ if (boost::algorithm::iequals(model.objects[obj_idx]->volumes[vol_idx]->source.input_file, src.string()))
+ replace_volume_with_stl(obj_idx, vol_idx, dest, "");
+ }
+ }
+#else
for (size_t i = 0; i < replace_paths.size(); ++i) {
const auto& path = replace_paths[i].string();
for (const SelectedVolume& sel_v : selected_volumes) {
@@ -3769,6 +3930,7 @@ void Plater::priv::reload_from_disk()
replace_volume_with_stl(sel_v.object_idx, sel_v.volume_idx, path, "");
}
}
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
if (!fail_list.empty()) {
wxString message = _L("Unable to reload:") + "\n";
@@ -4556,6 +4718,13 @@ bool Plater::priv::can_replace_with_stl() const
bool Plater::priv::can_reload_from_disk() const
{
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ // collect selected reloadable ModelVolumes
+ std::vector> selected_volumes = reloadable_volumes(model, get_selection());
+ // nothing to reload, return
+ if (selected_volumes.empty())
+ return false;
+#else
// struct to hold selected ModelVolumes by their indices
struct SelectedVolume
{
@@ -4581,6 +4750,21 @@ bool Plater::priv::can_reload_from_disk() const
selected_volumes.push_back({ o_idx, v_idx });
}
}
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
+
+#if ENABLE_RELOAD_FROM_DISK_REWORK
+ std::sort(selected_volumes.begin(), selected_volumes.end(), [](const std::pair& v1, const std::pair& v2) {
+ return (v1.first < v2.first) || (v1.first == v2.first && v1.second < v2.second);
+ });
+ selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end(), [](const std::pair& v1, const std::pair& v2) {
+ return (v1.first == v2.first) && (v1.second == v2.second); }), selected_volumes.end());
+
+ // collects paths of files to load
+ std::vector paths;
+ for (auto [obj_idx, vol_idx] : selected_volumes) {
+ paths.push_back(model.objects[obj_idx]->volumes[vol_idx]->source.input_file);
+ }
+#else
std::sort(selected_volumes.begin(), selected_volumes.end());
selected_volumes.erase(std::unique(selected_volumes.begin(), selected_volumes.end()), selected_volumes.end());
@@ -4594,6 +4778,7 @@ bool Plater::priv::can_reload_from_disk() const
else if (!object->input_file.empty() && !volume->name.empty() && !volume->source.is_from_builtin_objects)
paths.push_back(volume->name);
}
+#endif // ENABLE_RELOAD_FROM_DISK_REWORK
std::sort(paths.begin(), paths.end());
paths.erase(std::unique(paths.begin(), paths.end()), paths.end());