diff options
Diffstat (limited to 'source/blender/blenkernel/intern/library_override.c')
-rw-r--r-- | source/blender/blenkernel/intern/library_override.c | 117 |
1 files changed, 90 insertions, 27 deletions
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c index ce368575492..4f10a5bca6b 100644 --- a/source/blender/blenkernel/intern/library_override.c +++ b/source/blender/blenkernel/intern/library_override.c @@ -57,7 +57,7 @@ static void bke_override_property_operation_clear(IDOverrideLibraryPropertyOpera /* Temp, for until library override is ready and tested enough to go 'public', * we hide it by default in UI and such. */ -static bool _override_library_enabled = false; +static bool _override_library_enabled = true; void BKE_override_library_enable(const bool do_enable) { @@ -111,11 +111,11 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id) if (dst_id->override_library != NULL) { if (src_id->override_library == NULL) { - BKE_override_library_free(&dst_id->override_library); + BKE_override_library_free(&dst_id->override_library, true); return; } else { - BKE_override_library_clear(dst_id->override_library); + BKE_override_library_clear(dst_id->override_library, true); } } else if (src_id->override_library == NULL) { @@ -144,7 +144,7 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id) } /** Clear any overriding data from given \a override. */ -void BKE_override_library_clear(IDOverrideLibrary *override) +void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_user) { BLI_assert(override != NULL); @@ -153,16 +153,18 @@ void BKE_override_library_clear(IDOverrideLibrary *override) } BLI_freelistN(&override->properties); - id_us_min(override->reference); - /* override->storage should never be refcounted... */ + if (do_id_user) { + id_us_min(override->reference); + /* override->storage should never be refcounted... */ + } } /** Free given \a override. */ -void BKE_override_library_free(struct IDOverrideLibrary **override) +void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user) { BLI_assert(*override != NULL); - BKE_override_library_clear(*override); + BKE_override_library_clear(*override, do_id_user); MEM_freeN(*override); *override = NULL; } @@ -183,19 +185,28 @@ static ID *override_library_create_from(Main *bmain, ID *reference_id) } /** Create an overridden local copy of linked reference. */ -ID *BKE_override_library_create_from_id(Main *bmain, ID *reference_id) +ID *BKE_override_library_create_from_id(Main *bmain, ID *reference_id, const bool do_tagged_remap) { BLI_assert(reference_id != NULL); BLI_assert(reference_id->lib != NULL); ID *local_id = override_library_create_from(bmain, reference_id); - /* Remapping, we obviously only want to affect local data - * (and not our own reference pointer to overridden ID). */ - BKE_libblock_remap(bmain, - reference_id, - local_id, - ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY); + if (do_tagged_remap) { + ID *other_id; + FOREACH_MAIN_ID_BEGIN (bmain, other_id) { + if ((other_id->tag & LIB_TAG_DOIT) != 0 && other_id->lib == NULL) { + /* Note that using ID_REMAP_SKIP_INDIRECT_USAGE below is superfluous, as we only remap + * local IDs usages anyway... */ + BKE_libblock_relink_ex(bmain, + other_id, + reference_id, + local_id, + ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY); + } + } + FOREACH_MAIN_ID_END; + } return local_id; } @@ -205,6 +216,11 @@ ID *BKE_override_library_create_from_id(Main *bmain, ID *reference_id) * \note Set id->newid of overridden libs with newly created overrides, * caller is responsible to clean those pointers before/after usage as needed. * + * \note By default, it will only remap newly created local overriding data-blocks between + * themselves, to avoid 'enforcing' those overrides into all other usages of the linked data in + * main. You can add more local IDs to be remapped to use new overriding ones by setting their + * LIB_TAG_DOIT tag. + * * \return \a true on success, \a false otherwise. */ bool BKE_override_library_create_from_tag(Main *bmain) @@ -212,26 +228,59 @@ bool BKE_override_library_create_from_tag(Main *bmain) ID *reference_id; bool ret = true; + ListBase todo_ids = {NULL}; + LinkData *todo_id_iter; + + /* Get all IDs we want to override. */ FOREACH_MAIN_ID_BEGIN (bmain, reference_id) { if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL) { - if ((reference_id->newid = override_library_create_from(bmain, reference_id)) == NULL) { - ret = false; - } + todo_id_iter = MEM_callocN(sizeof(*todo_id_iter), __func__); + todo_id_iter->data = reference_id; + BLI_addtail(&todo_ids, todo_id_iter); } } FOREACH_MAIN_ID_END; - FOREACH_MAIN_ID_BEGIN (bmain, reference_id) { - if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL && - reference_id->newid != NULL) { - ID *local_id = reference_id->newid; - BKE_libblock_remap(bmain, - reference_id, - local_id, - ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY); + /* Override the IDs. */ + for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) { + reference_id = todo_id_iter->data; + if ((reference_id->newid = override_library_create_from(bmain, reference_id)) == NULL) { + ret = false; + } + else { + /* We also tag the new IDs so that in next step we can remap their pointers too. */ + reference_id->newid->tag |= LIB_TAG_DOIT; } } - FOREACH_MAIN_ID_END; + + /* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole + * existing linked IDs usages. */ + for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) { + ID *other_id; + reference_id = todo_id_iter->data; + + if (reference_id->newid == NULL) { + continue; + } + + /* Still checking the whole Main, that way we can tag other local IDs as needing to be remapped + * to use newly created overriding IDs, if needed. */ + FOREACH_MAIN_ID_BEGIN (bmain, other_id) { + if ((other_id->tag & LIB_TAG_DOIT) != 0 && other_id->lib == NULL) { + ID *local_id = reference_id->newid; + /* Note that using ID_REMAP_SKIP_INDIRECT_USAGE below is superfluous, as we only remap + * local IDs usages anyway... */ + BKE_libblock_relink_ex(bmain, + other_id, + reference_id, + local_id, + ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY); + } + } + FOREACH_MAIN_ID_END; + } + + BLI_freelistN(&todo_ids); return ret; } @@ -592,6 +641,13 @@ bool BKE_override_library_operations_create(Main *bmain, ID *local, const bool f bool ret = false; if (!is_template && (force_auto || local->override_library->flag & OVERRIDE_LIBRARY_AUTO)) { + /* Do not attempt to generate overriding rules from an empty place-holder generated by link + * code when it cannot find to actual library/ID. Much better to keep the local datablock as + * is in the file in that case, until broken lib is fixed. */ + if (ID_MISSING(local->override_library->reference)) { + return ret; + } + PointerRNA rnaptr_local, rnaptr_reference; RNA_id_pointer_create(local, &rnaptr_local); RNA_id_pointer_create(local->override_library->reference, &rnaptr_reference); @@ -644,6 +700,13 @@ void BKE_override_library_update(Main *bmain, ID *local) return; } + /* Do not attempt to apply overriding rules over an empty place-holder generated by link code + * when it cannot find to actual library/ID. Much better to keep the local datablock as loaded + * from the file in that case, until broken lib is fixed. */ + if (ID_MISSING(local->override_library->reference)) { + return; + } + /* Recursively do 'ancestors' overrides first, if any. */ if (local->override_library->reference->override_library && (local->override_library->reference->tag & LIB_TAG_OVERRIDE_LIBRARY_REFOK) == 0) { |