Revert "Revert "LibOverride: Handle dependencies in both directions in partial override cases.""

This reverts commit rB31d80ddeaad, and fixes issue introduced in rBf0b4aa5d59e3
by not doing the 'reversed dependency check' in resync case.

Rational here are:
* Supporting reversed dependency in a reliable, coinsistent way in
  resync is likely to be a nightmare, if even possible at all.
* Needs for such reversed dependency in resync should be close to 0% of
  cases, as long as users remain reasonable with their organization of
  their assets (it could only become a problem in extreme bad practice
  and corner cases, like a geometry object being added as a child of a
  rig in a completely new, otherwise un-overridden collection, in
  partial override context).

This decision may need to be re-evaluated later in case we go more
towards a very highly partial-override  workflow, but even then I would
expect current solution to work fine in all reasonable use cases.
This commit is contained in:
Bastien Montagne 2022-06-29 10:25:00 +02:00
parent edbf04ff37
commit acdc043c30
1 changed files with 57 additions and 2 deletions

View File

@ -687,6 +687,51 @@ static void lib_override_group_tag_data_clear(LibOverrideGroupTagData *data)
memset(data, 0, sizeof(*data));
}
static void lib_override_hierarchy_dependencies_recursive_tag_from(LibOverrideGroupTagData *data)
{
Main *bmain = data->bmain;
ID *id = data->id_root;
const bool is_override = data->is_override;
if ((*(uint *)&id->tag & data->tag) == 0) {
/* This ID is not tagged, no reason to proceed further to its parents. */
return;
}
MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
BLI_ghash_lookup(bmain->relations->relations_from_pointers, id));
BLI_assert(entry != nullptr);
if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_FROM) {
/* 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_FROM;
for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != nullptr;
from_id_entry = from_id_entry->next) {
if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
/* Never consider non-overridable relationships ('from', 'parents', 'owner' etc. pointers)
* as actual dependencies. */
continue;
}
/* We only consider IDs from the same library. */
ID *from_id = from_id_entry->id_pointer.from;
if (from_id == nullptr || from_id->lib != id->lib ||
(is_override && !ID_IS_OVERRIDE_LIBRARY(from_id))) {
/* IDs from different libraries, or non-override IDs in case we are processing overrides,
* are both barriers of dependency. */
continue;
}
from_id->tag |= data->tag;
LibOverrideGroupTagData sub_data = *data;
sub_data.id_root = from_id;
lib_override_hierarchy_dependencies_recursive_tag_from(&sub_data);
}
}
/* Tag all IDs in dependency relationships within an override hierarchy/group.
*
* Requires existing `Main.relations`.
@ -698,18 +743,19 @@ static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTa
Main *bmain = data->bmain;
ID *id = data->id_root;
const bool is_override = data->is_override;
const bool is_resync = data->is_resync;
MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
BLI_ghash_lookup(bmain->relations->relations_from_pointers, id));
BLI_assert(entry != nullptr);
if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO) {
/* This ID has already been processed. */
return (*(uint *)&id->tag & data->tag) != 0;
}
/* This way we won't process again that ID, should we encounter it again through another
* relationship hierarchy. */
entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO;
for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
to_id_entry = to_id_entry->next) {
@ -733,6 +779,15 @@ static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTa
}
}
/* If the current ID is/has been tagged for override above, then check its reversed dependencies
* (i.e. IDs that depend on the current one).
*
* This will cover e.g. the case where user override an armature, and would expect the mesh
* object deformed by that armature to also be overridden. */
if ((*(uint *)&id->tag & data->tag) != 0 && !is_resync) {
lib_override_hierarchy_dependencies_recursive_tag_from(data);
}
return (*(uint *)&id->tag & data->tag) != 0;
}