From 5ba5c6672d8ae3afa2ab1504b892edc31343fb40 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Sun, 5 Jul 2026 16:40:00 +0800 Subject: [PATCH] Fix reload from disk for STEP models after reopening a project (#12992) (#14591) * Fix reload from disk for STEP models after reopening a project (#12992) reload_from_disk matched reloaded source volumes with an exact source.input_file string comparison. After a project is saved and reopened, the stored source path is only the filename (the default, non-full-path save) while a freshly re-imported volume carries a full path, so the comparison never matched: reload fell into fail_list and the "locate file" dialog was effectively useless for STEP models. Fall back to a case-insensitive filename comparison when the exact paths differ, so the existing same-folder source lookup (and the locate dialog) can reload the model. Projects that stored absolute source paths still match exactly as before; no 3mf format change. * Add Preferences option to store full source paths in projects Expose the existing export_sources_full_pathnames setting (previously only editable in the config file) as a checkbox under Preferences > General > Project. Enabling it stores absolute source paths in saved projects, so "Reload from disk" works when the source file is kept in a different folder than the project (companion to #12992). --- src/slic3r/GUI/Plater.cpp | 9 ++++++++- src/slic3r/GUI/Preferences.cpp | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 04fe7026f7..26b9217b3f 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -8959,7 +8959,14 @@ void Plater::priv::reload_from_disk() 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]->source.input_file == old_volume->source.input_file) { + const std::string &new_input_file = obj->volumes[old_volume->source.volume_idx]->source.input_file; + const std::string &old_input_file = old_volume->source.input_file; + // Orca: match on the exact source path first, then fall back to filename-only so reload + // still matches when the project stored a bare filename and the file was found next to + // the project (same-folder fallback) or picked via the locate dialog (#12992). + if (new_input_file == old_input_file || + boost::algorithm::iequals(fs::path(new_input_file).filename().string(), + fs::path(old_input_file).filename().string())) { new_volume_idx = old_volume->source.volume_idx; new_object_idx = old_volume->source.object_idx; match_found = true; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index b0aba418dc..af7522c33d 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1664,6 +1664,13 @@ void PreferencesDialog::create_items() ); g_sizer->Add(item_draco_bits); + auto item_full_source_paths = create_item_checkbox(_L("Store full source file paths in projects"), + _L("If enabled, saved projects store the absolute path to imported source files (STEP/STL/...), so " + "\"Reload from disk\" still works when the source file is kept in a different folder than the project. " + "If disabled, only the filename is stored, which keeps projects portable and avoids embedding absolute paths."), + "export_sources_full_pathnames"); + g_sizer->Add(item_full_source_paths); + //// GENERAL > Preset g_sizer->Add(create_item_title(_L("Preset")), 1, wxEXPAND);