Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/library_override.c')
-rw-r--r--source/blender/blenkernel/intern/library_override.c117
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) {