LibOverride: Outliner: Add an operation to override the selected ID and its parents.

This will override all linked data-blocks in the tree branch leading to
the selected one.
This commit is contained in:
Bastien Montagne 2020-07-14 14:49:59 +02:00
parent 140b26909e
commit e3fd60b182
1 changed files with 76 additions and 11 deletions

View File

@ -54,6 +54,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
@ -739,22 +740,63 @@ static void id_local_cb(bContext *C,
}
}
typedef struct OutlinerLibOverrideData {
bool do_hierarchy;
} OutlinerLibOverrideData;
static void id_override_library_cb(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
TreeElement *UNUSED(te),
TreeElement *te,
TreeStoreElem *UNUSED(tsep),
TreeStoreElem *tselem,
void *UNUSED(user_data))
void *user_data)
{
if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id)) {
BLI_assert(TSE_IS_REAL_ID(tselem));
ID *id_root = tselem->id;
if (ID_IS_LINKED(id_root) &&
(BKE_idtype_get_info_from_id(id_root)->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0) {
Main *bmain = CTX_data_main(C);
OutlinerLibOverrideData *data = user_data;
const bool do_hierarchy = data->do_hierarchy;
id_root->tag |= LIB_TAG_DOIT;
printf("%s: Tagging root id %s\n", __func__, id_root->name);
/* For now, remapp all local usages of linked ID to local override one here. */
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
ID *override_id = BKE_lib_override_library_create_from_id(bmain, tselem->id, true);
if (override_id != NULL) {
BKE_main_id_clear_newpoins(bmain);
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
if (ID_IS_LINKED(id_iter)) {
id_iter->tag &= ~LIB_TAG_DOIT;
}
else {
id_iter->tag |= LIB_TAG_DOIT;
}
}
FOREACH_MAIN_ID_END;
if (do_hierarchy) {
/* 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_LINKED(te->store_elem->id)) {
break;
}
te->store_elem->id->tag |= LIB_TAG_DOIT;
printf("%s: Tagging parent id %s\n", __func__, te->store_elem->id->name);
}
BKE_lib_override_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, true);
BKE_lib_override_library_create_from_tag(bmain);
}
else if (ID_IS_OVERRIDABLE_LIBRARY(id_root)) {
BKE_lib_override_library_create_from_id(bmain, id_root, true);
}
BKE_main_id_clear_newpoins(bmain);
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
}
@ -1326,8 +1368,8 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
}
else if (event == OL_OP_REMAP) {
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
/* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth trick
* does not work here). */
/* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
* trick does not work here). */
}
else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb);
@ -1508,6 +1550,7 @@ typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_UNLINK,
OUTLINER_IDOP_LOCAL,
OUTLINER_IDOP_OVERRIDE_LIBRARY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY,
OUTLINER_IDOP_SINGLE,
OUTLINER_IDOP_DELETE,
OUTLINER_IDOP_REMAP,
@ -1531,6 +1574,11 @@ static const EnumPropertyItem prop_id_op_types[] = {
0,
"Add Library Override",
"Add a local override of this linked data-block"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY,
"OVERRIDE_LIBRARY_HIERARCHY",
0,
"Add Library Override Hierarchy",
"Add a local override of this linked data-block, and its hierarchy of dependencies"},
{OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""},
{OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""},
{OUTLINER_IDOP_REMAP,
@ -1678,8 +1726,25 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
}
case OUTLINER_IDOP_OVERRIDE_LIBRARY: {
/* make local */
outliner_do_libdata_operation(
C, op->reports, scene, soops, &soops->tree, id_override_library_cb, NULL);
outliner_do_libdata_operation(C,
op->reports,
scene,
soops,
&soops->tree,
id_override_library_cb,
&(OutlinerLibOverrideData){.do_hierarchy = false});
ED_undo_push(C, "Overridden Data");
break;
}
case OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY: {
/* make local */
outliner_do_libdata_operation(C,
op->reports,
scene,
soops,
&soops->tree,
id_override_library_cb,
&(OutlinerLibOverrideData){.do_hierarchy = true});
ED_undo_push(C, "Overridden Data");
break;
}