LibOverride: support 'make override' for all selected items.
This commit allows to select several data-blocks in the outliner and create overrides from all of them, not only the active one. It properly creates a single hierarchy when several IDs from a same hierarchy root data are selected. Reviewed By: Severin Differential Revision: https://developer.blender.org/D15497
This commit is contained in:
parent
0dcee6a386
commit
ee3facd087
|
@ -31,8 +31,11 @@
|
|||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_animsys.h"
|
||||
|
@ -90,7 +93,9 @@ static CLG_LogRef LOG = {"ed.outliner.tools"};
|
|||
|
||||
using namespace blender::ed::outliner;
|
||||
|
||||
using blender::Map;
|
||||
using blender::Set;
|
||||
using blender::Vector;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name ID/Library/Data Set/Un-link Utilities
|
||||
|
@ -777,6 +782,25 @@ static void id_local_fn(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
struct OutlinerLiboverrideDataIDRoot {
|
||||
/** The linked ID that was selected for override. */
|
||||
ID *id_root_reference;
|
||||
|
||||
/** The root of the override hierarchy to which the override of `id_root` belongs, once
|
||||
* known/created. */
|
||||
ID *id_hierarchy_root_override;
|
||||
|
||||
/** The ID that was detected as being a good candidate as instanciation hint for newly overridden
|
||||
* objects, may be null.
|
||||
*
|
||||
* \note Typically currently only used when the root ID to override is a collection instanced by
|
||||
* an emtpy object. */
|
||||
ID *id_instance_hint;
|
||||
|
||||
/** If this override comes from an instancing object (which would be `id_instance_hint` then). */
|
||||
bool is_override_instancing_object;
|
||||
};
|
||||
|
||||
struct OutlinerLibOverrideData {
|
||||
bool do_hierarchy;
|
||||
|
||||
|
@ -789,21 +813,44 @@ struct OutlinerLibOverrideData {
|
|||
* solving broken overrides while not losing *all* of your overrides. */
|
||||
bool do_resync_hierarchy_enforce;
|
||||
|
||||
/** The override hierarchy root, when known/created. */
|
||||
ID *id_hierarchy_root_override;
|
||||
|
||||
/** A hash of the selected tree elements' ID 'uuid'. Used to clear 'system override' flags on
|
||||
/** A set of the selected tree elements' ID 'uuid'. Used to clear 'system override' flags on
|
||||
* their newly-created liboverrides in post-process step of override hierarchy creation. */
|
||||
Set<uint> selected_id_uid;
|
||||
|
||||
/** A mapping from the found hierarchy roots to a linked list of IDs to override for each of
|
||||
* these roots.
|
||||
*
|
||||
* \note the key may be either linked (in which case it will be replaced by the newly created
|
||||
* override), or an actual already existing override. */
|
||||
Map<ID *, Vector<OutlinerLiboverrideDataIDRoot>> id_hierarchy_roots;
|
||||
|
||||
/** All 'session_uuid' of all hierarchy root IDs used or created by the operation. */
|
||||
Set<uint> id_hierarchy_roots_uid;
|
||||
|
||||
void id_root_add(ID *id_hierarchy_root_reference,
|
||||
ID *id_root_reference,
|
||||
ID *id_instance_hint,
|
||||
const bool is_override_instancing_object)
|
||||
{
|
||||
OutlinerLiboverrideDataIDRoot id_root_data;
|
||||
id_root_data.id_root_reference = id_root_reference;
|
||||
id_root_data.id_hierarchy_root_override = nullptr;
|
||||
id_root_data.id_instance_hint = id_instance_hint;
|
||||
id_root_data.is_override_instancing_object = is_override_instancing_object;
|
||||
|
||||
Vector<OutlinerLiboverrideDataIDRoot> &value = id_hierarchy_roots.lookup_or_add_default(
|
||||
id_hierarchy_root_reference);
|
||||
value.append(id_root_data);
|
||||
}
|
||||
};
|
||||
|
||||
/* Store 'UUID' of IDs of selected elements in the Outliner tree, before generating the override
|
||||
* hierarchy. */
|
||||
static void id_override_library_create_hierarchy_pre_process_fn(bContext *UNUSED(C),
|
||||
ReportList *UNUSED(reports),
|
||||
static void id_override_library_create_hierarchy_pre_process_fn(bContext *C,
|
||||
ReportList *reports,
|
||||
Scene *UNUSED(scene),
|
||||
TreeElement *UNUSED(te),
|
||||
TreeStoreElem *UNUSED(tsep),
|
||||
TreeElement *te,
|
||||
TreeStoreElem *tsep,
|
||||
TreeStoreElem *tselem,
|
||||
void *user_data)
|
||||
{
|
||||
|
@ -829,28 +876,6 @@ static void id_override_library_create_hierarchy_pre_process_fn(bContext *UNUSED
|
|||
}
|
||||
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
|
||||
}
|
||||
}
|
||||
|
||||
static void id_override_library_create_fn(bContext *C,
|
||||
ReportList *reports,
|
||||
Scene *scene,
|
||||
TreeElement *te,
|
||||
TreeStoreElem *tsep,
|
||||
TreeStoreElem *tselem,
|
||||
void *user_data)
|
||||
{
|
||||
BLI_assert(TSE_IS_REAL_ID(tselem));
|
||||
|
||||
/* We can only safely apply this operation on one item at a time, so only do it on the active
|
||||
* one. */
|
||||
if ((tselem->flag & TSE_ACTIVE) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ID *id_root_reference = tselem->id;
|
||||
OutlinerLibOverrideData *data = reinterpret_cast<OutlinerLibOverrideData *>(user_data);
|
||||
const bool do_hierarchy = data->do_hierarchy;
|
||||
bool success = false;
|
||||
|
||||
ID *id_instance_hint = nullptr;
|
||||
bool is_override_instancing_object = false;
|
||||
|
@ -866,15 +891,131 @@ static void id_override_library_create_fn(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
if (ID_IS_OVERRIDABLE_LIBRARY(id_root_reference) ||
|
||||
(ID_IS_LINKED(id_root_reference) && do_hierarchy)) {
|
||||
Main *bmain = CTX_data_main(C);
|
||||
if (!ID_IS_OVERRIDABLE_LIBRARY(id_root_reference) &&
|
||||
!(ID_IS_LINKED(id_root_reference) && do_hierarchy)) {
|
||||
return;
|
||||
}
|
||||
|
||||
id_root_reference->tag |= LIB_TAG_DOIT;
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
if (do_hierarchy) {
|
||||
/* Tag all linked parents in tree hierarchy to be also overridden. */
|
||||
ID *id_hierarchy_root_reference = id_root_reference;
|
||||
while ((te = te->parent) != nullptr) {
|
||||
if (!TSE_IS_REAL_ID(te->store_elem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Tentative hierarchy root. */
|
||||
ID *id_current_hierarchy_root = te->store_elem->id;
|
||||
|
||||
/* If the parent ID is from a different library than the reference root one, we are done
|
||||
* with upwards tree processing in any case. */
|
||||
if (id_current_hierarchy_root->lib != id_root_reference->lib) {
|
||||
if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id_current_hierarchy_root)) {
|
||||
/* Virtual overrides (i.e. embedded IDs), we can simply keep processing their parent to
|
||||
* get an actual real override. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the parent ID is already an override, and is valid (i.e. local override), we can
|
||||
* access its hierarchy root directly. */
|
||||
if (!ID_IS_LINKED(id_current_hierarchy_root) &&
|
||||
ID_IS_OVERRIDE_LIBRARY_REAL(id_current_hierarchy_root) &&
|
||||
id_current_hierarchy_root->override_library->reference->lib ==
|
||||
id_root_reference->lib) {
|
||||
id_hierarchy_root_reference =
|
||||
id_current_hierarchy_root->override_library->hierarchy_root;
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference));
|
||||
break;
|
||||
}
|
||||
|
||||
if (ID_IS_LINKED(id_current_hierarchy_root)) {
|
||||
/* No local 'anchor' was found for the hierarchy to override, do not proceed, as this
|
||||
* would most likely generate invisible/confusing/hard to use and manage overrides. */
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Invalid anchor ('%s') found, needed to create library override from "
|
||||
"data-block '%s'",
|
||||
id_current_hierarchy_root->name,
|
||||
id_root_reference->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* In all other cases, `id_current_hierarchy_root` cannot be a valid hierarchy root, so
|
||||
* current `id_hierarchy_root_reference` is our best candidate. */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* If some element in the tree needs to be overridden, but its ID is not overridable,
|
||||
* abort. */
|
||||
if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id_current_hierarchy_root)) {
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Could not create library override from data-block '%s', one of its parents "
|
||||
"is not overridable ('%s')",
|
||||
id_root_reference->name,
|
||||
id_current_hierarchy_root->name);
|
||||
return;
|
||||
}
|
||||
id_current_hierarchy_root->tag |= LIB_TAG_DOIT;
|
||||
id_hierarchy_root_reference = id_current_hierarchy_root;
|
||||
}
|
||||
|
||||
/* That case can happen when linked data is a complex mix involving several libraries and/or
|
||||
* linked overrides. E.g. a mix of overrides from one library, and indirectly linked data
|
||||
* from another library. Do not try to support such cases for now. */
|
||||
if (!((id_hierarchy_root_reference->lib == id_root_reference->lib) ||
|
||||
(!ID_IS_LINKED(id_hierarchy_root_reference) &&
|
||||
ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference) &&
|
||||
id_hierarchy_root_reference->override_library->reference->lib ==
|
||||
id_root_reference->lib))) {
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Invalid hierarchy root ('%s') found, needed to create library override from "
|
||||
"data-block '%s'",
|
||||
id_hierarchy_root_reference->name,
|
||||
id_root_reference->name);
|
||||
return;
|
||||
}
|
||||
|
||||
data->id_root_add(id_hierarchy_root_reference,
|
||||
id_root_reference,
|
||||
id_instance_hint,
|
||||
is_override_instancing_object);
|
||||
}
|
||||
else if (ID_IS_OVERRIDABLE_LIBRARY(id_root_reference)) {
|
||||
data->id_root_add(
|
||||
id_root_reference, id_root_reference, id_instance_hint, is_override_instancing_object);
|
||||
}
|
||||
}
|
||||
|
||||
static void id_override_library_create_hierarchy(
|
||||
Main &bmain,
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
OutlinerLibOverrideData &data,
|
||||
ID *id_hierarchy_root_reference,
|
||||
Vector<OutlinerLiboverrideDataIDRoot> &data_idroots,
|
||||
bool &r_aggregated_success)
|
||||
{
|
||||
BLI_assert(ID_IS_LINKED(id_hierarchy_root_reference) ||
|
||||
ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference));
|
||||
|
||||
const bool do_hierarchy = data.do_hierarchy;
|
||||
|
||||
/* NOTE: This process is not the most efficient, but allows to re-use existing code.
|
||||
* If this becomes a bottle-neck at some point, we need to implement a new
|
||||
* `BKE_lib_override_library_hierarchy_create()` function able to process several roots inside of
|
||||
* a same hierarchy in a single call. */
|
||||
for (OutlinerLiboverrideDataIDRoot &data_idroot : data_idroots) {
|
||||
/* For now, remap all local usages of linked ID to local override one here. */
|
||||
ID *id_iter;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
|
||||
FOREACH_MAIN_ID_BEGIN (&bmain, id_iter) {
|
||||
if (ID_IS_LINKED(id_iter) || ID_IS_OVERRIDE_LIBRARY(id_iter)) {
|
||||
id_iter->tag &= ~LIB_TAG_DOIT;
|
||||
}
|
||||
|
@ -884,154 +1025,105 @@ static void id_override_library_create_fn(bContext *C,
|
|||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
bool success;
|
||||
if (do_hierarchy) {
|
||||
/* Tag all linked parents in tree hierarchy to be also overridden. */
|
||||
ID *id_hierarchy_root_reference = id_root_reference;
|
||||
while ((te = te->parent) != nullptr) {
|
||||
if (!TSE_IS_REAL_ID(te->store_elem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Tentative hierarchy root. */
|
||||
ID *id_current_hierarchy_root = te->store_elem->id;
|
||||
|
||||
/* If the parent ID is from a different library than the reference root one, we are done
|
||||
* with upwards tree processing in any case. */
|
||||
if (id_current_hierarchy_root->lib != id_root_reference->lib) {
|
||||
if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id_current_hierarchy_root)) {
|
||||
/* Virtual overrides (i.e. embedded IDs), we can simply keep processing their parent to
|
||||
* get an actual real override. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the parent ID is already an override, and is valid (i.e. local override), we can
|
||||
* access its hierarchy root directly. */
|
||||
if (!ID_IS_LINKED(id_current_hierarchy_root) &&
|
||||
ID_IS_OVERRIDE_LIBRARY_REAL(id_current_hierarchy_root) &&
|
||||
id_current_hierarchy_root->override_library->reference->lib ==
|
||||
id_root_reference->lib) {
|
||||
id_hierarchy_root_reference =
|
||||
id_current_hierarchy_root->override_library->hierarchy_root;
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference));
|
||||
break;
|
||||
}
|
||||
|
||||
if (ID_IS_LINKED(id_current_hierarchy_root)) {
|
||||
/* No local 'anchor' was found for the hierarchy to override, do not proceed, as this
|
||||
* would most likely generate invisible/confusing/hard to use and manage overrides. */
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Invalid anchor ('%s') found, needed to create library override from "
|
||||
"data-block '%s'",
|
||||
id_current_hierarchy_root->name,
|
||||
id_root_reference->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* In all other cases, `id_current_hierarchy_root` cannot be a valid hierarchy root, so
|
||||
* current `id_hierarchy_root_reference` is our best candidate. */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* If some element in the tree needs to be overridden, but its ID is not overridable,
|
||||
* abort. */
|
||||
if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id_current_hierarchy_root)) {
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Could not create library override from data-block '%s', one of its parents "
|
||||
"is not overridable ('%s')",
|
||||
id_root_reference->name,
|
||||
id_current_hierarchy_root->name);
|
||||
return;
|
||||
}
|
||||
id_current_hierarchy_root->tag |= LIB_TAG_DOIT;
|
||||
id_hierarchy_root_reference = id_current_hierarchy_root;
|
||||
}
|
||||
|
||||
/* That case can happen when linked data is a complex mix involving several libraries and/or
|
||||
* linked overrides. E.g. a mix of overrides from one library, and indirectly linked data
|
||||
* from another library. Do not try to support such cases for now. */
|
||||
if (!((id_hierarchy_root_reference->lib == id_root_reference->lib) ||
|
||||
(!ID_IS_LINKED(id_hierarchy_root_reference) &&
|
||||
ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference) &&
|
||||
id_hierarchy_root_reference->override_library->reference->lib ==
|
||||
id_root_reference->lib))) {
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Invalid hierarchy root ('%s') found, needed to create library override from "
|
||||
"data-block '%s'",
|
||||
id_hierarchy_root_reference->name,
|
||||
id_root_reference->name);
|
||||
return;
|
||||
}
|
||||
|
||||
ID *id_root_override = nullptr;
|
||||
success = BKE_lib_override_library_create(bmain,
|
||||
CTX_data_scene(C),
|
||||
CTX_data_view_layer(C),
|
||||
success = BKE_lib_override_library_create(&bmain,
|
||||
scene,
|
||||
view_layer,
|
||||
nullptr,
|
||||
id_root_reference,
|
||||
data_idroot.id_root_reference,
|
||||
id_hierarchy_root_reference,
|
||||
id_instance_hint,
|
||||
data_idroot.id_instance_hint,
|
||||
&id_root_override,
|
||||
data->do_fully_editable);
|
||||
data.do_fully_editable);
|
||||
|
||||
BLI_assert(id_root_override != nullptr);
|
||||
BLI_assert(!ID_IS_LINKED(id_root_override));
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root_override));
|
||||
if (ID_IS_LINKED(id_hierarchy_root_reference)) {
|
||||
BLI_assert(
|
||||
id_root_override->override_library->hierarchy_root->override_library->reference ==
|
||||
id_hierarchy_root_reference);
|
||||
data->id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
|
||||
}
|
||||
else {
|
||||
BLI_assert(id_root_override->override_library->hierarchy_root ==
|
||||
id_hierarchy_root_reference);
|
||||
data->id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
|
||||
if (success) {
|
||||
BLI_assert(id_root_override != nullptr);
|
||||
BLI_assert(!ID_IS_LINKED(id_root_override));
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root_override));
|
||||
|
||||
ID *id_hierarchy_root_override = id_root_override->override_library->hierarchy_root;
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_override));
|
||||
if (ID_IS_LINKED(id_hierarchy_root_reference)) {
|
||||
BLI_assert(id_hierarchy_root_override->override_library->reference ==
|
||||
id_hierarchy_root_reference);
|
||||
/* If the hierarchy root reference was a linked data, after the first iteration there is
|
||||
* now a matching override, which shall be used for all further partial overrides with
|
||||
* this same hierarchy. */
|
||||
id_hierarchy_root_reference = id_hierarchy_root_override;
|
||||
}
|
||||
else {
|
||||
BLI_assert(id_hierarchy_root_override == id_hierarchy_root_reference);
|
||||
}
|
||||
data_idroot.id_hierarchy_root_override = id_hierarchy_root_override;
|
||||
data.id_hierarchy_roots_uid.add(id_hierarchy_root_override->session_uuid);
|
||||
}
|
||||
}
|
||||
else if (ID_IS_OVERRIDABLE_LIBRARY(id_root_reference)) {
|
||||
success = BKE_lib_override_library_create_from_id(bmain, id_root_reference, true) != nullptr;
|
||||
else if (ID_IS_OVERRIDABLE_LIBRARY(data_idroot.id_root_reference)) {
|
||||
ID *id_root_override = BKE_lib_override_library_create_from_id(
|
||||
&bmain, data_idroot.id_root_reference, true);
|
||||
|
||||
success = id_root_override != nullptr;
|
||||
if (success) {
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root_override));
|
||||
id_root_override->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
|
||||
}
|
||||
/* Cleanup. */
|
||||
BKE_main_id_newptr_and_tag_clear(bmain);
|
||||
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
|
||||
BKE_main_id_newptr_and_tag_clear(&bmain);
|
||||
BKE_main_id_tag_all(&bmain, LIB_TAG_DOIT, false);
|
||||
}
|
||||
|
||||
/* Remove the instance empty from this scene, the items now have an overridden collection
|
||||
* instead. */
|
||||
if (success && is_override_instancing_object) {
|
||||
ED_object_base_free_and_unlink(bmain, scene, (Object *)id_instance_hint);
|
||||
if (success && data_idroot.is_override_instancing_object) {
|
||||
BLI_assert(GS(data_idroot.id_instance_hint) == ID_OB);
|
||||
ED_object_base_free_and_unlink(
|
||||
&bmain, scene, reinterpret_cast<Object *>(data_idroot.id_instance_hint));
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Could not create library override from data-block '%s'",
|
||||
id_root_reference->name);
|
||||
|
||||
r_aggregated_success = r_aggregated_success && success;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear system override flag from newly created overrides which linked reference were previously
|
||||
* selected in the Outliner tree. */
|
||||
static void id_override_library_create_hierarchy_post_process(bContext *C,
|
||||
OutlinerLibOverrideData *data)
|
||||
static void id_override_library_create_hierarchy_process(bContext *C,
|
||||
ReportList *reports,
|
||||
OutlinerLibOverrideData &data)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ID *id_hierarchy_root_override = data->id_hierarchy_root_override;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
const bool do_hierarchy = data.do_hierarchy;
|
||||
|
||||
bool success = true;
|
||||
for (auto &&[id_hierarchy_root_reference, data_idroots] : data.id_hierarchy_roots.items()) {
|
||||
id_override_library_create_hierarchy(
|
||||
*bmain, scene, view_layer, data, id_hierarchy_root_reference, data_idroots, success);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Could not create library override from one or more of the selected data-blocks");
|
||||
}
|
||||
|
||||
if (!do_hierarchy) {
|
||||
return;
|
||||
}
|
||||
|
||||
ID *id_iter;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
|
||||
if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ||
|
||||
id_iter->override_library->hierarchy_root != id_hierarchy_root_override) {
|
||||
if (ID_IS_LINKED(id_iter) || !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) {
|
||||
continue;
|
||||
}
|
||||
if (data->selected_id_uid.contains(id_iter->override_library->reference->session_uuid)) {
|
||||
if (!data.id_hierarchy_roots_uid.contains(
|
||||
id_iter->override_library->hierarchy_root->session_uuid)) {
|
||||
continue;
|
||||
}
|
||||
if (data.selected_id_uid.contains(id_iter->override_library->reference->session_uuid) ||
|
||||
data.selected_id_uid.contains(id_iter->session_uuid)) {
|
||||
id_iter->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
|
||||
}
|
||||
}
|
||||
|
@ -2254,8 +2346,18 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE: {
|
||||
OutlinerLibOverrideData override_data{};
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_create_fn, &override_data);
|
||||
override_data.do_hierarchy = false;
|
||||
override_data.do_fully_editable = true;
|
||||
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
id_override_library_create_hierarchy_pre_process_fn,
|
||||
&override_data);
|
||||
|
||||
id_override_library_create_hierarchy_process(C, op->reports, override_data);
|
||||
|
||||
ED_undo_push(C, "Overridden Data");
|
||||
break;
|
||||
}
|
||||
|
@ -2263,15 +2365,15 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
OutlinerLibOverrideData override_data{};
|
||||
override_data.do_hierarchy = true;
|
||||
override_data.do_fully_editable = U.experimental.use_override_new_fully_editable;
|
||||
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
space_outliner,
|
||||
id_override_library_create_hierarchy_pre_process_fn,
|
||||
&override_data);
|
||||
outliner_do_libdata_operation(
|
||||
C, op->reports, scene, space_outliner, id_override_library_create_fn, &override_data);
|
||||
id_override_library_create_hierarchy_post_process(C, &override_data);
|
||||
|
||||
id_override_library_create_hierarchy_process(C, op->reports, override_data);
|
||||
|
||||
ED_undo_push(C, "Overridden Data Hierarchy");
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue