Fix #129207: GPv3: Linked GPv2 objects disappear when reopening file.

This happens because blender 4.3 only knows about GPv3 IDs, and
therefore stores a reference to a directly linked GPv2 obdata as a GPv3
one, which cannot be found again on next file load in the GPv2 library.

The idea of this fix is, if the looup of a idcode+idname fails, to also
search for the same name but with an older, deprecated ID code.

Pull Request: https://projects.blender.org/blender/blender/pulls/129220
This commit is contained in:
Bastien Montagne
2024-10-21 11:13:25 +02:00
committed by Bastien Montagne
parent acc2772c45
commit 7937a7eadf
3 changed files with 48 additions and 2 deletions

View File

@@ -108,6 +108,7 @@
#include "SEQ_utils.hh"
#include "readfile.hh"
#include "versioning_common.hh"
/* Make preferences read-only. */
#define U (*((const UserDef *)&U))
@@ -3932,9 +3933,27 @@ static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const
static BHead *find_bhead_from_idname(FileData *fd, const char *idname)
{
#ifdef USE_GHASH_BHEAD
return static_cast<BHead *>(BLI_ghash_lookup(fd->bhead_idname_hash, idname));
BHead *bhead = static_cast<BHead *>(BLI_ghash_lookup(fd->bhead_idname_hash, idname));
#else
return find_bhead_from_code_name(fd, GS(idname), idname + 2);
BHead *bhead = find_bhead_from_code_name(fd, GS(idname), idname + 2);
#endif
if (LIKELY(bhead)) {
return bhead;
}
/* Expected ID was not found, attempt to load the same name, but for an older, deprecated and
* converted ID type. */
const short id_code_old = do_versions_new_to_old_idcode_get(GS(idname));
if (id_code_old == ID_LINK_PLACEHOLDER) {
return bhead;
}
#ifdef USE_GHASH_BHEAD
char id_name_old[MAX_ID_NAME];
BLI_strncpy(id_name_old, idname, sizeof(id_name_old));
*reinterpret_cast<short *>(id_name_old) = id_code_old;
return static_cast<BHead *>(BLI_ghash_lookup(fd->bhead_idname_hash, id_name_old));
#else
return find_bhead_from_code_name(fd, id_code_old, idname + 2);
#endif
}

View File

@@ -47,6 +47,17 @@
using blender::Map;
using blender::StringRef;
short do_versions_new_to_old_idcode_get(const short id_code_new)
{
switch (id_code_new) {
case ID_GP:
/* ID_GD_LEGACY (Grease Pencil v2) is now converted to ID_GP (Grease Pencil v3). */
return ID_GD_LEGACY;
default:
return ID_LINK_PLACEHOLDER;
}
}
ARegion *do_versions_add_region_if_not_found(ListBase *regionbase,
int region_type,
const char *allocname,

View File

@@ -24,6 +24,22 @@ struct SceneRenderLayer;
using blender::FunctionRef;
/**
* Mapping from new ID types to old converted ID types.
*
* This is used by linking code, when a directly linked data comes from a library where it exists
* as an older, different type of ID.
*
* Since the current blendfile will convert that older ID type to the new one as part of its
* versioning process, when saved, it will store a reference to that linked ID using the _new_ ID
* type, which will not be found on next blendfile opening/reloading when searching for that ID in
* the library blendfile.
*
* \returns The old, deprecated ID type code if any matches the given `id_code_new` one, otherwise
* `ID_LINK_PLACEHOLDER`.
*/
short do_versions_new_to_old_idcode_get(short id_code_new);
/**
* Check if a region of type \a region_type exists in \a regionbase. Otherwise add it after the
* first region of type \a link_after_region_type.