Fix (unreported) liboverride: Hierarchy corruption when making some override local.

Making some liboverride local will break/corrupt liboverride hierarchies
in many cases. So that function (or its caller, in some cases) need to
call #BKE_lib_override_library_main_hierarchy_root_ensure to re-validate
(and re-generate if needed) the liboverride hierarchy roots.
This commit is contained in:
Bastien Montagne
2023-10-10 16:52:59 +02:00
parent c5e10920f9
commit a238ab737b
6 changed files with 21 additions and 7 deletions

View File

@@ -284,10 +284,14 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root);
/**
* Make given ID fully local.
*
* \param bmain If given, all liboverrides hierarchy roots will be re-validated/generated after
* clearing the liboverride data from given \a id. If nullptr, caller is responsible to perform
* this action (call #BKE_lib_override_library_main_hierarchy_root_ensure) itself.
*
* \note Only differs from lower-level #BKE_lib_override_library_free in infamous embedded ID
* cases.
*/
void BKE_lib_override_library_make_local(ID *id);
void BKE_lib_override_library_make_local(Main *bmain, ID *id);
/**
* Find override property from given RNA path, if it exists.

View File

@@ -506,7 +506,7 @@ void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
if (force_local) {
BKE_lib_id_clear_library_data(bmain, id, flags);
if ((flags & LIB_ID_MAKELOCAL_LIBOVERRIDE_CLEAR) != 0) {
BKE_lib_override_library_make_local(id);
BKE_lib_override_library_make_local(bmain, id);
}
BKE_lib_id_expand_local(bmain, id, flags);
}
@@ -1826,7 +1826,9 @@ void BKE_library_make_local(Main *bmain,
ELEM(lib, nullptr, id->override_library->reference->lib) &&
((untagged_only == false) || !(id->tag & LIB_TAG_PRE_EXISTING)))
{
BKE_lib_override_library_make_local(id);
/* Validating liboverride hierarchy root pointers will happen later in this function,
* rather than doing it for each and every localized ID. */
BKE_lib_override_library_make_local(nullptr, id);
}
}
/* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so it's possible to tag data
@@ -1966,6 +1968,10 @@ void BKE_library_make_local(Main *bmain,
}
}
/* Making some liboverride local may have had some impact on validity of liboverrides hierarchy
* roots, these need to be re-validated/re-generated. */
BKE_lib_override_library_main_hierarchy_root_ensure(bmain);
#ifdef DEBUG_TIME
printf("Step 4: Remap local usages of old (linked) ID to new (local) ID: Done.\n");
TIMEIT_VALUE_PRINT(make_local);

View File

@@ -3587,7 +3587,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
void BKE_lib_override_library_make_local(ID *id)
void BKE_lib_override_library_make_local(Main *bmain, ID *id)
{
if (!ID_IS_OVERRIDE_LIBRARY(id)) {
return;
@@ -3617,6 +3617,10 @@ void BKE_lib_override_library_make_local(ID *id)
if (node_tree != nullptr) {
node_tree->id.flag &= ~LIB_EMBEDDED_DATA_LIB_OVERRIDE;
}
/* In case a liboverride hierarchy root is 'made local', i.e. is not a liboverride anymore, all
* hierarchy roots of all liboverrides need to be validated/re-generated again. */
BKE_lib_override_library_main_hierarchy_root_ensure(bmain);
}
/* We only build override GHash on request. */

View File

@@ -1017,7 +1017,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
template_id_liboverride_hierarchy_make(C, bmain, template_ui, &idptr, &undo_push_label);
}
else {
BKE_lib_override_library_make_local(id);
BKE_lib_override_library_make_local(bmain, id);
/* Reassign to get proper updates/notifiers. */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, nullptr);

View File

@@ -1002,7 +1002,7 @@ static void id_local_fn(bContext *C,
}
}
else if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id)) {
BKE_lib_override_library_make_local(tselem->id);
BKE_lib_override_library_make_local(CTX_data_main(C), tselem->id);
}
}

View File

@@ -1095,7 +1095,7 @@ static ID *rna_ID_make_local(ID *self, Main *bmain, bool /*clear_proxy*/)
BKE_lib_id_make_local(bmain, self, 0);
}
else if (ID_IS_OVERRIDE_LIBRARY_REAL(self)) {
BKE_lib_override_library_make_local(self);
BKE_lib_override_library_make_local(bmain, self);
}
ID *ret_id = self->newid ? self->newid : self;