LibOverride: Add 'delete and use linked data' operation.
This will re-link all usages of a library override data-block (including all of its override dependencies) to its reference linked IDs, and delete those liboverrides. As usual, it is available in the ID sub-menu of the outliner context right-click menu. Part of T76555.
This commit is contained in:
parent
59180ff153
commit
4aa04b6490
|
@ -81,6 +81,7 @@ bool BKE_lib_override_library_resync(struct Main *bmain,
|
|||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer,
|
||||
struct ID *id_root);
|
||||
void BKE_lib_override_library_delete(struct Main *bmain, struct ID *id_root);
|
||||
|
||||
struct IDOverrideLibraryProperty *BKE_lib_override_library_property_find(
|
||||
struct IDOverrideLibrary *override, const char *rna_path);
|
||||
|
|
|
@ -784,6 +784,50 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_
|
|||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced 'smart' function to delete library overrides (including their existing override
|
||||
* hierarchy) and remap their usages to their linked reference IDs.
|
||||
*
|
||||
* \note All IDs tagged with `LIB_TAG_DOIT` will be deleted.
|
||||
*
|
||||
* \param id_root The root liboverride ID to resync from.
|
||||
*/
|
||||
void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
|
||||
{
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
|
||||
|
||||
/* Tag all collections and objects, as well as other IDs using them. */
|
||||
id_root->tag |= LIB_TAG_DOIT;
|
||||
|
||||
/* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, and tag
|
||||
* linked reference ones to be overridden again. */
|
||||
BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, true);
|
||||
|
||||
ID *id;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (id->tag & LIB_TAG_DOIT) {
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
ID *id_override_reference = id->override_library->reference;
|
||||
|
||||
/* Remap the whole local IDs to use the linked data. */
|
||||
BKE_libblock_remap(bmain, id, id_override_reference, ID_REMAP_SKIP_INDIRECT_USAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
/* Delete the override IDs. */
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (id->tag & LIB_TAG_DOIT) {
|
||||
BKE_id_delete(bmain, id);
|
||||
}
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
/* Should not actually be needed here... */
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
}
|
||||
|
||||
BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_runtime_ensure(
|
||||
IDOverrideLibrary *override)
|
||||
{
|
||||
|
|
|
@ -860,6 +860,38 @@ static void id_override_library_resync_fn(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
static void id_override_library_delete_fn(bContext *C,
|
||||
ReportList *UNUSED(reports),
|
||||
Scene *UNUSED(scene),
|
||||
TreeElement *te,
|
||||
TreeStoreElem *UNUSED(tsep),
|
||||
TreeStoreElem *tselem,
|
||||
void *UNUSED(user_data))
|
||||
{
|
||||
BLI_assert(TSE_IS_REAL_ID(tselem));
|
||||
ID *id_root = tselem->id;
|
||||
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
id_root->tag |= LIB_TAG_DOIT;
|
||||
|
||||
/* Tag all linked parents in tree hierarchy to be also overridden. */
|
||||
while ((te = te->parent) != NULL) {
|
||||
if (!TSE_IS_REAL_ID(te->store_elem)) {
|
||||
continue;
|
||||
}
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) {
|
||||
break;
|
||||
}
|
||||
te->store_elem->id->tag |= LIB_TAG_DOIT;
|
||||
}
|
||||
BKE_lib_override_library_delete(bmain, id_root);
|
||||
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void id_fake_user_set_fn(bContext *UNUSED(C),
|
||||
ReportList *UNUSED(reports),
|
||||
Scene *UNUSED(scene),
|
||||
|
@ -1641,6 +1673,7 @@ typedef enum eOutlinerIdOpTypes {
|
|||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
|
||||
OUTLINER_IDOP_SINGLE,
|
||||
OUTLINER_IDOP_DELETE,
|
||||
OUTLINER_IDOP_REMAP,
|
||||
|
@ -1693,6 +1726,12 @@ static const EnumPropertyItem prop_id_op_types[] = {
|
|||
"Resync Library Override Hierarchy",
|
||||
"Rebuild this local override from its linked reference, as well as its hierarchy of "
|
||||
"dependencies"},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
|
||||
"OVERRIDE_LIBRARY_DELETE_HIERARCHY",
|
||||
0,
|
||||
"Delete Library Override Hierarchy",
|
||||
"Delete this local override (including its hierarchy of override dependencies) and relink "
|
||||
"its usages to the linked data-blocks"},
|
||||
{0, "", 0, NULL, NULL},
|
||||
{OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
|
||||
{OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
|
||||
|
@ -1725,6 +1764,8 @@ static bool outliner_id_operation_item_poll(bContext *C,
|
|||
return true;
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY:
|
||||
return true;
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY:
|
||||
return true;
|
||||
case OUTLINER_IDOP_SINGLE:
|
||||
if (!space_outliner || ELEM(space_outliner->outlinevis, SO_SCENES, SO_VIEW_LAYER)) {
|
||||
return true;
|
||||
|
@ -1919,6 +1960,18 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
ED_undo_push(C, "Resync Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: {
|
||||
/* make local */
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
&space_outliner->tree,
|
||||
id_override_library_delete_fn,
|
||||
&(OutlinerLibOverrideData){.do_hierarchy = true});
|
||||
ED_undo_push(C, "Delete Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_SINGLE: {
|
||||
/* make single user */
|
||||
switch (idlevel) {
|
||||
|
|
Loading…
Reference in New Issue