IDType owner ID accessor: Add option to skip relationship sanity checks.

While currently, all cases where `BKE_id_owner_get` is called are
'safe', there are some points in code where the pointers ensureing the
relationship between an embedded ID and its owner are not (fully) valid.

This new option (`false` by default) allows to skip the debug asserts
ensuring the sanity of these 'owner <-> embedded' ID pointers in the
relevant `owner_pointer_get` callbacks.

This change is not expected to have any effect in current codebase.
This commit is contained in:
Bastien Montagne 2024-05-02 14:04:22 +02:00
parent 8ba6c16242
commit eb9bec54ad
6 changed files with 32 additions and 14 deletions

@ -89,7 +89,15 @@ using IDTypeForeachCacheFunction = void (*)(ID *id,
using IDTypeForeachPathFunction = void (*)(ID *id, BPathForeachPathData *bpath_data);
using IDTypeEmbeddedOwnerPointerGetFunction = ID **(*)(ID *id);
/**
* Callback returning the address of the pointer to the owner ID, for embedded (and Shapekey) ones.
*
* \param debug_relationship_assert: usually the owner <-> embedded relation pointers should be
* fully valid, and can be asserted on. But in some cases, they are not (fully) valid, e.g when
* copying an ID and all of its embedded data.
*/
using IDTypeEmbeddedOwnerPointerGetFunction = ID *
*(*)(ID * id, const bool debug_relationship_assert);
using IDTypeBlendWriteFunction = void (*)(BlendWriter *writer, ID *id, const void *id_address);
using IDTypeBlendReadDataFunction = void (*)(BlendDataReader *reader, ID *id);

@ -711,8 +711,12 @@ bool BKE_id_can_be_asset(const ID *id);
* Return the owner ID of the given `id`, if any.
*
* \note This will only return non-NULL for embedded IDs (master collections etc.), and shape-keys.
*
* \param debug_relationship_assert: True by default, whether to perform debug checks on validity
* of the pointers between owner and embedded IDs. In some cases, these relations are not yet
* (fully) valid, e.g. during ID copying.
*/
ID *BKE_id_owner_get(ID *id);
ID *BKE_id_owner_get(ID *id, const bool debug_relationship_assert = true);
/**
* Check if that ID can be considered as editable from a high-level (editor) perspective.

@ -249,7 +249,7 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
static ID **collection_owner_pointer_get(ID *id)
static ID **collection_owner_pointer_get(ID *id, const bool debug_relationship_assert)
{
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
return nullptr;
@ -257,9 +257,11 @@ static ID **collection_owner_pointer_get(ID *id)
Collection *master_collection = (Collection *)id;
BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
if (debug_relationship_assert) {
BLI_assert(master_collection->owner_id != nullptr);
BLI_assert(GS(master_collection->owner_id->name) == ID_SCE);
BLI_assert(((Scene *)master_collection->owner_id)->master_collection == master_collection);
}
return &master_collection->owner_id;
}

@ -103,12 +103,14 @@ static void shapekey_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
static ID **shapekey_owner_pointer_get(ID *id)
static ID **shapekey_owner_pointer_get(ID *id, const bool debug_relationship_assert)
{
Key *key = (Key *)id;
if (debug_relationship_assert) {
BLI_assert(key->from != nullptr);
BLI_assert(BKE_key_from_id(key->from) == key);
}
return &key->from;
}

@ -2209,11 +2209,11 @@ bool BKE_id_can_be_asset(const ID *id)
BKE_idtype_idcode_is_linkable(GS(id->name));
}
ID *BKE_id_owner_get(ID *id)
ID *BKE_id_owner_get(ID *id, const bool debug_relationship_assert)
{
const IDTypeInfo *idtype = BKE_idtype_get_info_from_id(id);
if (idtype->owner_pointer_get != nullptr) {
ID **owner_id_pointer = idtype->owner_pointer_get(id);
ID **owner_id_pointer = idtype->owner_pointer_get(id, debug_relationship_assert);
if (owner_id_pointer != nullptr) {
return *owner_id_pointer;
}

@ -456,7 +456,7 @@ static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
}
}
static ID **node_owner_pointer_get(ID *id)
static ID **node_owner_pointer_get(ID *id, const bool debug_relationship_assert)
{
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
return nullptr;
@ -465,8 +465,10 @@ static ID **node_owner_pointer_get(ID *id)
// BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
if (debug_relationship_assert) {
BLI_assert(ntree->owner_id != nullptr);
BLI_assert(ntreeFromID(ntree->owner_id) == ntree);
}
return &ntree->owner_id;
}