diff options
author | Bastien Montagne <bastien@blender.org> | 2021-02-10 19:10:24 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2021-02-10 19:10:43 +0300 |
commit | f269fbd64a5a0cb7cab894284b37334888e72aaf (patch) | |
tree | d4cc9cf14ebe515d2216e71a1775e38cf0523f1c | |
parent | b5536c97b756224324995fc2a766a38d53a31d11 (diff) |
LibOverride: Refactor: Switch more code to using Main.relations.
This potentially could fix some missed cases in dependency tagging (when
dealing with overrides hierarchies), since relying on tag in ID itself
is not a good idea to check whether an ID has been propcessed or not
(exterior code may have forced that tag on some IDs e.g., which would
prevent them from ever being processed properly).
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.c | 99 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_ID.h | 4 |
2 files changed, 91 insertions, 12 deletions
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 0f753018c46..63709080b5c 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -423,6 +423,8 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat Main *bmain = data->bmain; ID *id_owner = data->id_root; BLI_assert(ID_IS_LINKED(id_owner)); + const uint tag = data->tag; + const uint missing_tag = data->missing_tag; MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id_owner); @@ -430,7 +432,6 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { /* This ID has already been processed. */ - printf("%s already processed\n", id_owner->name); return; } /* This way we won't process again that ID, should we encounter it again through another @@ -439,9 +440,10 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; to_id_entry = to_id_entry->next) { - if ((to_id_entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) { - /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as - * actual dependencies. */ + if ((to_id_entry->usage_flag & + (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) != 0) { + /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers), nor + * override references or embedded ID pointers, as actual dependencies. */ continue; } @@ -460,10 +462,10 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat * Note: missing IDs (aka placeholders) are never overridden. */ if (ELEM(GS(to_id->name), ID_OB, ID_GR)) { if ((to_id->tag & LIB_TAG_MISSING)) { - to_id->tag |= data->missing_tag; + to_id->tag |= missing_tag; } else { - to_id->tag |= data->tag; + to_id->tag |= tag; } } @@ -570,23 +572,93 @@ static int lib_override_local_group_tag_cb(LibraryIDLinkCallbackData *cb_data) return IDWALK_RET_NOP; } +static void lib_override_local_group_tag_recursive(LibOverrideGroupTagData *data) +{ + Main *bmain = data->bmain; + ID *id_owner = data->id_root; + BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner)); + const uint tag = data->tag; + const uint missing_tag = data->missing_tag; + + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, + id_owner); + BLI_assert(entry != NULL); + + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { + /* This ID has already been processed. */ + return; + } + /* This way we won't process again that ID, should we encounter it again through another + * relationship hierarchy. */ + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; + + for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; + to_id_entry = to_id_entry->next) { + if ((to_id_entry->usage_flag & + (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) != 0) { + /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers), nor + * override references or embedded ID pointers, as actual dependencies. */ + continue; + } + + ID *to_id = *to_id_entry->id_pointer.to; + if (ELEM(to_id, NULL, id_owner)) { + continue; + } + if (!ID_IS_OVERRIDE_LIBRARY(to_id) || ID_IS_LINKED(to_id)) { + continue; + } + + /* Do not tag 'virtual' overrides (shape keys here, as we already rejected embedded case + * above). */ + if (ID_IS_OVERRIDE_LIBRARY_REAL(to_id)) { + ID *reference_lib = NULL; + if (GS(id_owner->name) == ID_KE) { + reference_lib = ((Key *)id_owner)->from->override_library->reference->lib; + } + else { + reference_lib = id_owner->override_library->reference->lib; + } + if (to_id->override_library->reference->lib != reference_lib) { + /* We do not override data-blocks from other libraries, nor do we process them. */ + continue; + } + + if (to_id->override_library->reference->tag & LIB_TAG_MISSING) { + to_id->tag |= missing_tag; + } + else { + to_id->tag |= tag; + } + } + + /* Recursively process the dependencies. */ + LibOverrideGroupTagData sub_data = *data; + sub_data.id_root = to_id; + lib_override_local_group_tag_recursive(&sub_data); + } +} + /* This will tag all override IDs of an override group defined by the given `id_root`. */ static void lib_override_local_group_tag(LibOverrideGroupTagData *data) { - Main *bmain = data->bmain; ID *id_root = data->id_root; + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root) && !ID_IS_LINKED(id_root)); - id_root->tag |= data->tag; + if ((id_root->override_library->reference->tag & LIB_TAG_MISSING)) { + id_root->tag |= data->missing_tag; + } + else { + id_root->tag |= data->tag; + } /* Tag all local overrides in id_root's group. */ - BKE_library_foreach_ID_link( - bmain, id_root, lib_override_local_group_tag_cb, data, IDWALK_READONLY | IDWALK_RECURSE); + lib_override_local_group_tag_recursive(data); } static bool lib_override_library_create_do(Main *bmain, ID *id_root) { BKE_main_relations_create(bmain, 0); - LibOverrideGroupTagData data = { .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; lib_override_linked_group_tag(&data); @@ -790,11 +862,11 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ ID *id_root_reference = id_root->override_library->reference; BKE_main_relations_create(bmain, 0); - LibOverrideGroupTagData data = { .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; lib_override_local_group_tag(&data); + BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); data.id_root = id_root_reference; lib_override_linked_group_tag(&data); @@ -999,10 +1071,13 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root) BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); /* Tag all library overrides in the chains of dependencies from the given root one. */ + BKE_main_relations_create(bmain, 0); LibOverrideGroupTagData data = { .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; lib_override_local_group_tag(&data); + BKE_main_relations_free(bmain); + ID *id; FOREACH_MAIN_ID_BEGIN (bmain, id) { if (id->tag & LIB_TAG_DOIT) { diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index d9c821d3ba7..00d0d4e3626 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -427,6 +427,10 @@ typedef struct PreviewImage { (ID_IS_LINKED(_id) && !ID_MISSING(_id) && (((const ID *)(_id))->tag & LIB_TAG_EXTERN) != 0 && \ (BKE_idtype_get_info_from_id((const ID *)(_id))->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0) +/* NOTE: The three checks below do not take into account whether given ID is linked or not (when + * chaining overrides over several libraries). User must ensure the ID is not linked itself + * currently. */ +/* TODO: add `_EDITABLE` versions of those macros (that would check if ID is linked or not)? */ #define ID_IS_OVERRIDE_LIBRARY_REAL(_id) \ (((const ID *)(_id))->override_library != NULL && \ ((const ID *)(_id))->override_library->reference != NULL) |