From 9e129abcf2a2ccd1f1201f9fed33df93c191df60 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Mon, 4 Sep 2023 15:53:31 +0200 Subject: [PATCH] Fix #111905: Filewrite: Do not write ShapeKeys of unused geometry. This is more of a temp hack than a proper fix, proper solution would be to make shapekeys actual embedded IDs (which they are, in all aspects but actual implementation), and to address long-standing design tasks about handling of unused data on file save (see #61209 and #87490). But for now, simply do not write ShapeKeys IDs if they have no owner, or their owner has no user (and is therefore also not written to disk). --- source/blender/blenloader/intern/writefile.cc | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/source/blender/blenloader/intern/writefile.cc b/source/blender/blenloader/intern/writefile.cc index 41afebf8587..6866f00abf9 100644 --- a/source/blender/blenloader/intern/writefile.cc +++ b/source/blender/blenloader/intern/writefile.cc @@ -84,6 +84,7 @@ #include "DNA_collection_types.h" #include "DNA_fileglobal_types.h" #include "DNA_genfile.h" +#include "DNA_key_types.h" #include "DNA_sdna_types.h" #include "BLI_bitmap.h" @@ -1282,12 +1283,31 @@ static bool write_file_handle(Main *mainvar, BLI_assert( (id->tag & (LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT | LIB_TAG_NOT_ALLOCATED)) == 0); - /* We only write unused IDs in undo case. - * NOTE: All Scenes, WindowManagers and WorkSpaces should always be written to disk, so - * their user-count should never be zero currently. */ - if (id->us == 0 && !wd->use_memfile) { - BLI_assert(!ELEM(GS(id->name), ID_SCE, ID_WM, ID_WS)); - continue; + /* We only write unused IDs in undo case. */ + if (!wd->use_memfile) { + /* NOTE: All Scenes, WindowManagers and WorkSpaces should always be written to disk, so + * their user-count should never be zero currently. */ + if (id->us == 0) { + BLI_assert(!ELEM(GS(id->name), ID_SCE, ID_WM, ID_WS)); + continue; + } + + /* XXX Special handling for ShapeKeys, as having unused shapekeys is not a good thing + * (and reported as error by e.g. `BLO_main_validate_shapekeys`), skip writing shapekeys + * when their 'owner' is not written. + * + * NOTE: Since ShapeKeys are conceptually embedded IDs (like root node trees e.g.), this + * behavior actually makes sense anyway. This remains more of a temp hack until topic of + * how to handle unused data on save is properly tackled. */ + if (GS(id->name) == ID_KE) { + Key *shape_key = reinterpret_cast(id); + /* NOTE: Here we are accessing the real owner ID data, not it's 'proxy' shallow copy + * generated for its file-writing. This is not expected to be an issue, but is worth + * noting. */ + if (shape_key->from == nullptr || shape_key->from->us == 0) { + continue; + } + } } if ((id->tag & LIB_TAG_RUNTIME) != 0 && !wd->use_memfile) {