Blender V4.3
lib_override.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdlib>
10#include <cstring>
11#include <iostream>
12#include <map>
13#include <queue>
14
15#include "CLG_log.h"
16
17#include "MEM_guardedalloc.h"
18
19#include "DNA_ID.h"
21#include "DNA_key_types.h"
22#include "DNA_object_types.h"
23#include "DNA_scene_types.h"
24
25#include "DEG_depsgraph.hh"
27
28#include "BKE_anim_data.hh"
29#include "BKE_armature.hh"
30#include "BKE_blender.hh"
31#include "BKE_collection.hh"
32#include "BKE_fcurve.hh"
33#include "BKE_global.hh"
34#include "BKE_idtype.hh"
35#include "BKE_key.hh"
36#include "BKE_layer.hh"
37#include "BKE_lib_id.hh"
38#include "BKE_lib_override.hh"
39#include "BKE_lib_query.hh"
40#include "BKE_lib_remap.hh"
41#include "BKE_main.hh"
42#include "BKE_main_namemap.hh"
43#include "BKE_node.hh"
44#include "BKE_report.hh"
45#include "BKE_scene.hh"
46
47#include "BLO_readfile.hh"
48
49#include "BLI_ghash.h"
50#include "BLI_linklist.h"
51#include "BLI_listbase.h"
52#include "BLI_memarena.h"
53#include "BLI_set.hh"
54#include "BLI_string.h"
55#include "BLI_task.h"
56#include "BLI_time.h"
57#include "BLI_utildefines.h"
58#include "BLI_vector.hh"
59
60#include "RNA_access.hh"
61#include "RNA_path.hh"
62#include "RNA_prototypes.hh"
63#include "RNA_types.hh"
64
65#include "atomic_ops.h"
66
67#include "lib_intern.hh"
68
69// #define DEBUG_OVERRIDE_TIMEIT
70
71#ifdef DEBUG_OVERRIDE_TIMEIT
72# include "BLI_time_utildefines.h"
73#endif
74
75using namespace blender::bke;
76
77static CLG_LogRef LOG = {"bke.liboverride"};
78static CLG_LogRef LOG_RESYNC = {"bke.liboverride_resync"};
79
84
88
90 IDOverrideLibrary *liboverride)
91{
92 if (liboverride->runtime == nullptr) {
93 liboverride->runtime = MEM_cnew<IDOverrideLibraryRuntime>(__func__);
94 }
95 return liboverride->runtime;
96}
97
104{
105 if (GS(id_src->name) == ID_OB && GS(id_dst->name) == ID_OB) {
106 Object *ob_src = reinterpret_cast<Object *>(id_src);
107 Object *ob_dst = reinterpret_cast<Object *>(id_dst);
108 if (ob_src->type == OB_ARMATURE && (ob_src->mode & OB_MODE_POSE) != 0) {
109 ob_dst->restore_mode = ob_dst->mode;
110 ob_dst->mode |= OB_MODE_POSE;
111 }
112 }
113}
114
117 const ID *id,
118 const ID * /*owner_id_hint*/,
119 const ID **r_owner_id)
120{
121 if (id->flag & ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE) {
122 const ID *owner_id = BKE_id_owner_get(const_cast<ID *>(id));
123 BLI_assert_msg(owner_id != nullptr, "Liboverride-embedded ID with no owner");
124 if (r_owner_id != nullptr) {
125 *r_owner_id = owner_id;
126 }
127 return owner_id->override_library;
128 }
129
130 if (r_owner_id != nullptr) {
131 *r_owner_id = id;
132 }
133 return id->override_library;
134}
135
137 ID *id,
138 ID *owner_id_hint,
139 ID **r_owner_id)
140{
141 /* Reuse the implementation of the const access function, which does not change the arguments.
142 * Add const explicitly to make it clear to the compiler to avoid just calling this function. */
143 return const_cast<IDOverrideLibrary *>(
144 BKE_lib_override_library_get(const_cast<const Main *>(bmain),
145 const_cast<const ID *>(id),
146 const_cast<const ID *>(owner_id_hint),
147 const_cast<const ID **>(r_owner_id)));
148}
149
151{
152 /* The `reference_id` *must* be linked data. */
153 BLI_assert(!reference_id || ID_IS_LINKED(reference_id));
154 BLI_assert(local_id->override_library == nullptr);
155
156 /* Else, generate new empty override. */
157 local_id->override_library = MEM_cnew<IDOverrideLibrary>(__func__);
158 local_id->override_library->reference = reference_id;
159 if (reference_id) {
161 }
162 local_id->tag &= ~ID_TAG_LIBOVERRIDE_REFOK;
163 /* By default initialized liboverrides are 'system overrides', higher-level code is responsible
164 * to unset this flag for specific IDs. */
166 /* TODO: do we want to add tag or flag to referee to mark it as such? */
167 return local_id->override_library;
168}
169
170void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_full_copy)
171{
173
174 if (dst_id->override_library != nullptr) {
175 if (src_id->override_library == nullptr) {
177 return;
178 }
179
181 }
182 else if (src_id->override_library == nullptr) {
183 /* Virtual overrides of embedded data does not require any extra work. */
184 return;
185 }
186 else {
187 BKE_lib_override_library_init(dst_id, nullptr);
188 }
189
190 /* Reuse the source's reference for destination ID. */
193
195 dst_id->override_library->flag = src_id->override_library->flag;
196
197 if (do_full_copy) {
199 &src_id->override_library->properties);
200 for (IDOverrideLibraryProperty *op_dst = static_cast<IDOverrideLibraryProperty *>(
202 *op_src = static_cast<IDOverrideLibraryProperty *>(
204 op_dst;
205 op_dst = op_dst->next, op_src = op_src->next)
206 {
208 }
209 }
210
211 dst_id->tag &= ~ID_TAG_LIBOVERRIDE_REFOK;
212}
213
214void BKE_lib_override_library_clear(IDOverrideLibrary *liboverride, const bool do_id_user)
215{
216 BLI_assert(liboverride != nullptr);
217
218 if (!ELEM(nullptr, liboverride->runtime, liboverride->runtime->rna_path_to_override_properties))
219 {
220 BLI_ghash_clear(liboverride->runtime->rna_path_to_override_properties, nullptr, nullptr);
221 }
222
225 }
226 BLI_freelistN(&liboverride->properties);
227
228 if (do_id_user) {
229 id_us_min(liboverride->reference);
230 /* override->storage should never be refcounted... */
231 }
232}
233
234void BKE_lib_override_library_free(IDOverrideLibrary **liboverride, const bool do_id_user)
235{
236 BLI_assert(*liboverride != nullptr);
237
238 if ((*liboverride)->runtime != nullptr) {
239 if ((*liboverride)->runtime->rna_path_to_override_properties != nullptr) {
240 BLI_ghash_free((*liboverride)->runtime->rna_path_to_override_properties, nullptr, nullptr);
241 }
242 MEM_SAFE_FREE((*liboverride)->runtime);
243 }
244
245 BKE_lib_override_library_clear(*liboverride, do_id_user);
246 MEM_freeN(*liboverride);
247 *liboverride = nullptr;
248}
249
251 Library *owner_library,
252 ID *reference_id,
253 const int lib_id_copy_flags)
254{
255 /* NOTE: do not copy possible override data from the reference here. */
256 ID *local_id = BKE_id_copy_in_lib(
257 bmain,
258 owner_library,
259 reference_id,
260 nullptr,
261 nullptr,
262 (LIB_ID_COPY_DEFAULT | LIB_ID_COPY_NO_LIB_OVERRIDE | lib_id_copy_flags));
263 if (local_id == nullptr) {
264 return nullptr;
265 }
266 BLI_assert(local_id->lib == owner_library);
267 id_us_min(local_id);
268
269 /* In case we could not get an override ID with the exact same name as its linked reference,
270 * ensure we at least get a uniquely named override ID over the whole current Main data, to
271 * reduce potential name collisions with other reference IDs.
272 *
273 * While in normal cases this would not be an issue, when files start to get heavily broken and
274 * not sound, such conflicts can become a source of problems. */
275 if (!STREQ(local_id->name + 2, reference_id->name + 2)) {
276 BLI_strncpy(local_id->name + 2, reference_id->name + 2, MAX_ID_NAME - 2);
277 BKE_main_namemap_get_name(bmain, local_id, local_id->name + 2, true);
278 id_sort_by_name(which_libbase(bmain, GS(local_id->name)), local_id, nullptr);
279 }
280
281 /* In `NO_MAIN` case, generic `BKE_id_copy` code won't call this.
282 * In liboverride resync case however, the currently not-in-Main new IDs will be added back to
283 * Main later, so ensure that their linked dependencies and paths are properly handled here.
284 *
285 * NOTE: This is likely not the best place to do this. Ideally, #BKE_libblock_management_main_add
286 * e.g. should take care of this. But for the time being, this works and has been battle-proofed.
287 */
288 if ((lib_id_copy_flags & LIB_ID_CREATE_NO_MAIN) != 0 && !ID_IS_LINKED(local_id)) {
289 lib_id_copy_ensure_local(bmain, reference_id, local_id, 0);
290 }
291
292 BKE_lib_override_library_init(local_id, reference_id);
293
294 /* NOTE: From liboverride perspective (and RNA one), shape keys are considered as local embedded
295 * data-blocks, just like root node trees or master collections. Therefore, we never need to
296 * create overrides for them. We need a way to mark them as overrides though. */
297 Key *reference_key;
298 if ((reference_key = BKE_key_from_id(reference_id)) != nullptr) {
299 Key *local_key = BKE_key_from_id(local_id);
300 BLI_assert(local_key != nullptr);
302 }
303
304 return local_id;
305}
306
308{
309 /* TODO: This could be simplified by storing a flag in #IDOverrideLibrary
310 * during the diffing process? */
311
312 if (!ID_IS_OVERRIDE_LIBRARY(id)) {
313 return false;
314 }
315
316 /* A bit weird, but those embedded IDs are handled by their owner ID anyway, so we can just
317 * assume they are never user-edited, actual proper detection will happen from their owner check.
318 */
320 return false;
321 }
322
323 LISTBASE_FOREACH (const IDOverrideLibraryProperty *, op, &id->override_library->properties) {
324 LISTBASE_FOREACH (const IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
325 if ((opop->flag & LIBOVERRIDE_OP_FLAG_IDPOINTER_MATCH_REFERENCE) != 0) {
326 continue;
327 }
328 if (opop->operation == LIBOVERRIDE_OP_NOOP) {
329 continue;
330 }
331 /* If an operation does not match the filters above, it is considered as a user-editing one,
332 * therefore this override is user-edited. */
333 return true;
334 }
335 }
336 return false;
337}
338
340{
341 if (ID_IS_OVERRIDE_LIBRARY(id)) {
342 const ID *override_owner_id;
343 BKE_lib_override_library_get(bmain, id, nullptr, &override_owner_id);
344 return (override_owner_id->override_library->flag & LIBOVERRIDE_FLAG_SYSTEM_DEFINED) != 0;
345 }
346 return false;
347}
348
350 const ID *id,
351 const IDOverrideLibraryProperty *liboverride_prop,
352 const PropertyRNA *override_rna_prop,
353 const int rnaprop_index)
354{
355 AnimData *anim_data = BKE_animdata_from_id(id);
356 if (anim_data != nullptr) {
357 FCurve *fcurve;
358 char *index_token_start = const_cast<char *>(
359 RNA_path_array_index_token_find(liboverride_prop->rna_path, override_rna_prop));
360 if (index_token_start != nullptr) {
361 const char index_token_start_backup = *index_token_start;
362 *index_token_start = '\0';
364 anim_data, liboverride_prop->rna_path, rnaprop_index, nullptr, nullptr);
365 *index_token_start = index_token_start_backup;
366 }
367 else {
369 anim_data, liboverride_prop->rna_path, 0, nullptr, nullptr);
370 }
371 if (fcurve != nullptr) {
372 return true;
373 }
374 }
375 return false;
376}
377
379{
380 ID *id_owner = cb_data->owner_id;
381 ID *id = *cb_data->id_pointer;
382 bool *is_leaf = static_cast<bool *>(cb_data->user_data);
383
384 if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
385 return IDWALK_RET_NOP;
386 }
387
388 if (id != nullptr && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
389 id->override_library->hierarchy_root == id_owner->override_library->hierarchy_root)
390 {
391 *is_leaf = false;
393 }
394 return IDWALK_RET_NOP;
395}
396
398{
400 bool is_leaf = true;
403 return is_leaf;
404 }
405
406 return false;
407}
408
410{
411 /* Only local liboverrides need to be tagged for refresh, linked ones should not be editable. */
412 if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY(id)) {
413 return;
414 }
415 /* NOTE: Valid relationships between IDs here (especially the beloved ObData <-> ShapeKey special
416 * case) cannot be always expected when ID get tagged. So now, embedded IDs and similar also get
417 * tagged, and the 'liboverride refresh' code is responsible to properly propagate the update to
418 * the owner ID when needed (see #BKE_lib_override_library_main_operations_create). */
420}
421
423 ID *reference_id,
424 const bool do_tagged_remap)
425{
426 BLI_assert(reference_id != nullptr);
427 BLI_assert(ID_IS_LINKED(reference_id));
428
429 ID *local_id = lib_override_library_create_from(bmain, nullptr, reference_id, 0);
430 /* We cannot allow automatic hierarchy resync on this ID, it is highly likely to generate a giant
431 * mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies.
432 * Ref #94650. */
434 local_id->override_library->flag &= ~LIBOVERRIDE_FLAG_SYSTEM_DEFINED;
435 local_id->override_library->hierarchy_root = local_id;
436
437 if (do_tagged_remap) {
438 Key *reference_key, *local_key = nullptr;
439 if ((reference_key = BKE_key_from_id(reference_id)) != nullptr) {
440 local_key = BKE_key_from_id(local_id);
441 BLI_assert(local_key != nullptr);
442 }
443
444 ID *other_id;
445 FOREACH_MAIN_ID_BEGIN (bmain, other_id) {
446 if ((other_id->tag & ID_TAG_DOIT) != 0 && !ID_IS_LINKED(other_id)) {
447 /* Note that using ID_REMAP_SKIP_INDIRECT_USAGE below is superfluous, as we only remap
448 * local IDs usages anyway. */
450 other_id,
451 reference_id,
452 local_id,
454 if (reference_key != nullptr) {
456 other_id,
457 &reference_key->id,
458 &local_key->id,
460 }
461 }
462 }
464 }
465
466 /* Cleanup global namemap, to avoid extra processing with regular ID name management. Better to
467 * re-create the global namemap on demand. */
469
470 return local_id;
471}
472
473static void lib_override_prefill_newid_from_existing_overrides(Main *bmain, ID *id_hierarchy_root)
474{
475 ID *id_iter;
476 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
477 ID *id = id_iter;
478 if (GS(id_iter->name) == ID_KE) {
479 id = reinterpret_cast<Key *>(id_iter)->from;
480 BLI_assert(id != nullptr);
481 }
483 id->override_library->hierarchy_root == id_hierarchy_root)
484 {
485 id->override_library->reference->newid = id;
486 if (GS(id_iter->name) == ID_KE) {
487 Key *reference_key = BKE_key_from_id(id->override_library->reference);
488 if (reference_key != nullptr) {
489 reference_key->id.newid = id_iter;
490 }
491 }
492 }
493 }
495}
496
498 ID *reference_id,
499 ID *local_id)
500{
501 id_remapper.add(reference_id, local_id);
502
503 Key *reference_key, *local_key = nullptr;
504 if ((reference_key = BKE_key_from_id(reference_id)) != nullptr) {
505 if (reference_id->newid != nullptr) {
506 local_key = BKE_key_from_id(reference_id->newid);
507 BLI_assert(local_key != nullptr);
508 }
509
510 id_remapper.add(&reference_key->id, &local_key->id);
511 }
512}
513
515 Library *owner_library,
516 const ID *id_root_reference,
517 ID *id_hierarchy_root,
518 const ID *id_hierarchy_root_reference,
519 const bool do_no_main,
520 const bool do_fully_editable)
521{
522 /* TODO: Make this static local function instead?
523 * API is becoming complex, and it's not used outside of this file anyway. */
524
525 BLI_assert(id_root_reference != nullptr && ID_IS_LINKED(id_root_reference));
526 /* If we do not have any hierarchy root given, then the root reference must be tagged for
527 * override. */
528 BLI_assert(id_hierarchy_root != nullptr || id_hierarchy_root_reference != nullptr ||
529 (id_root_reference->tag & ID_TAG_DOIT) != 0);
530 /* At least one of the hierarchy root pointers must be nullptr, passing both is useless and can
531 * create confusion. */
532 BLI_assert(ELEM(nullptr, id_hierarchy_root, id_hierarchy_root_reference));
533
534 if (id_hierarchy_root != nullptr) {
535 /* If the hierarchy root is given, it must be a valid existing override (used during partial
536 * resync process mainly). */
537 BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) &&
538 id_hierarchy_root->override_library->reference->lib == id_root_reference->lib);
539
540 if (!do_no_main) {
541 /* When processing within Main, set existing overrides in given hierarchy as 'newid' of their
542 * linked reference. This allows to re-use existing overrides instead of creating new ones in
543 * partial override cases. */
545 }
546 }
547 if (!ELEM(id_hierarchy_root_reference, nullptr, id_root_reference)) {
548 /* If the reference hierarchy root is given, it must be from the same library as the reference
549 * root, and also tagged for override. */
550 BLI_assert(id_hierarchy_root_reference->lib == id_root_reference->lib &&
551 (id_hierarchy_root_reference->tag & ID_TAG_DOIT) != 0);
552 }
553
554 const Library *reference_library = id_root_reference->lib;
555
556 ID *reference_id;
557 bool success = true;
558
559 ListBase todo_ids = {nullptr};
560 LinkData *todo_id_iter;
561
562 /* Get all IDs we want to override. */
563 FOREACH_MAIN_ID_BEGIN (bmain, reference_id) {
564 if ((reference_id->tag & ID_TAG_DOIT) != 0 && reference_id->lib == reference_library &&
565 BKE_idtype_idcode_is_linkable(GS(reference_id->name)))
566 {
567 todo_id_iter = MEM_cnew<LinkData>(__func__);
568 todo_id_iter->data = reference_id;
569 BLI_addtail(&todo_ids, todo_id_iter);
570 }
571 }
573
574 /* Override the IDs. */
575 for (todo_id_iter = static_cast<LinkData *>(todo_ids.first); todo_id_iter != nullptr;
576 todo_id_iter = todo_id_iter->next)
577 {
578 reference_id = static_cast<ID *>(todo_id_iter->data);
579
580 /* If `newid` is already set, assume it has been handled by calling code.
581 * Only current use case: re-using proxy ID when converting to liboverride. */
582 if (reference_id->newid == nullptr) {
583 /* NOTE: `no main` case is used during resync procedure, to support recursive resync.
584 * This requires extra care further down the resync process,
585 * see: #BKE_lib_override_library_resync. */
587 bmain, owner_library, reference_id, do_no_main ? LIB_ID_CREATE_NO_MAIN : 0);
588 if (reference_id->newid == nullptr) {
589 success = false;
590 break;
591 }
592 if (do_fully_editable) {
593 reference_id->newid->override_library->flag &= ~LIBOVERRIDE_FLAG_SYSTEM_DEFINED;
594 }
595 }
596 /* We also tag the new IDs so that in next step we can remap their pointers too. */
597 reference_id->newid->tag |= ID_TAG_DOIT;
598
599 Key *reference_key;
600 if ((reference_key = BKE_key_from_id(reference_id)) != nullptr) {
601 reference_key->id.tag |= ID_TAG_DOIT;
602
603 Key *local_key = BKE_key_from_id(reference_id->newid);
604 BLI_assert(local_key != nullptr);
605 reference_key->id.newid = &local_key->id;
606 /* We also tag the new IDs so that in next step we can remap their pointers too. */
607 local_key->id.tag |= ID_TAG_DOIT;
608 }
609 }
610
611 /* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole
612 * existing linked IDs usages. */
613 if (success) {
614 /* If a valid liboverride hierarchy root was given, only remap non-liboverride data and
615 * liboverrides belonging to that hierarchy. Avoids having other liboverride hierarchies of
616 * the same reference data also remapped to the newly created liboverride. */
617 const bool do_remap_liboverride_hierarchy_only = (id_hierarchy_root != nullptr && !do_no_main);
618
619 if (id_hierarchy_root_reference != nullptr) {
620 id_hierarchy_root = id_hierarchy_root_reference->newid;
621 }
622 else if (id_root_reference->newid != nullptr &&
623 (id_hierarchy_root == nullptr ||
624 id_hierarchy_root->override_library->reference == id_root_reference))
625 {
626 id_hierarchy_root = id_root_reference->newid;
627 }
628 BLI_assert(id_hierarchy_root != nullptr);
629
630 blender::Vector<ID *> relinked_ids;
631 id::IDRemapper id_remapper;
632 /* Still checking the whole Main, that way we can tag other local IDs as needing to be
633 * remapped to use newly created overriding IDs, if needed. */
634 ID *id;
635 FOREACH_MAIN_ID_BEGIN (bmain, id) {
636 ID *other_id;
637 /* In case we created new overrides as 'no main', they are not accessible directly in this
638 * loop, but we can get to them through their reference's `newid` pointer. */
639 if (do_no_main && id->lib == id_root_reference->lib && id->newid != nullptr) {
640 other_id = id->newid;
641 /* Otherwise we cannot properly distinguish between IDs that are actually from the
642 * linked library (and should not be remapped), and IDs that are overrides re-generated
643 * from the reference from the linked library, and must therefore be remapped.
644 *
645 * This is reset afterwards at the end of this loop. */
646 other_id->lib = nullptr;
647 }
648 else {
649 other_id = id;
650 }
651
652 /* If other ID is a linked one, but not from the same library as our reference, then we
653 * consider we should also relink it, as part of recursive resync. */
654 if ((other_id->tag & ID_TAG_DOIT) != 0 && other_id->lib != id_root_reference->lib) {
655 ID *owner_id;
656 BKE_lib_override_library_get(bmain, other_id, nullptr, &owner_id);
657
658 /* When the root of the current liboverride hierarchy is known, only remap liboverrides if
659 * they belong to that hierarchy. */
660 if (!do_remap_liboverride_hierarchy_only ||
661 (!ID_IS_OVERRIDE_LIBRARY_REAL(owner_id) ||
662 owner_id->override_library->hierarchy_root == id_hierarchy_root))
663 {
664 relinked_ids.append(other_id);
665 }
666
667 if (ID_IS_OVERRIDE_LIBRARY_REAL(other_id) &&
668 other_id->override_library->hierarchy_root == id_hierarchy_root)
669 {
670 reference_id = other_id->override_library->reference;
671 ID *local_id = reference_id->newid;
672 if (other_id == local_id) {
673 lib_override_remapper_overrides_add(id_remapper, reference_id, local_id);
674 }
675 }
676 }
677 if (other_id != id) {
678 other_id->lib = id_root_reference->lib;
679 }
680 }
682
683 for (todo_id_iter = static_cast<LinkData *>(todo_ids.first); todo_id_iter != nullptr;
684 todo_id_iter = todo_id_iter->next)
685 {
686 reference_id = static_cast<ID *>(todo_id_iter->data);
687 ID *local_id = reference_id->newid;
688
689 if (local_id == nullptr) {
690 continue;
691 }
692
693 local_id->override_library->hierarchy_root = id_hierarchy_root;
694
695 lib_override_remapper_overrides_add(id_remapper, reference_id, local_id);
696 }
697
699 relinked_ids,
701 id_remapper,
703
704 relinked_ids.clear();
705 }
706 else {
707 /* We need to cleanup potentially already created data. */
708 for (todo_id_iter = static_cast<LinkData *>(todo_ids.first); todo_id_iter != nullptr;
709 todo_id_iter = todo_id_iter->next)
710 {
711 reference_id = static_cast<ID *>(todo_id_iter->data);
712 BKE_id_delete(bmain, reference_id->newid);
713 reference_id->newid = nullptr;
714 }
715 }
716
717 BLI_freelistN(&todo_ids);
718
719 return success;
720}
721
725
729
733
740
745 void root_set(ID *id_root)
746 {
747 if (is_override) {
748 id_root_override = id_root;
749 }
750 else {
751 id_root_reference = id_root;
752 }
753 }
758 void hierarchy_root_set(ID *hierarchy_root_id)
759 {
760 if (is_override) {
761 hierarchy_root_id_override = hierarchy_root_id;
762 }
763 else {
764 hierarchy_root_id_reference = hierarchy_root_id;
765 }
766 }
767
770
774
783
788 bool id_tag_set(ID *id, const bool is_missing)
789 {
792 }
793 else if (is_missing) {
794 id->tag |= missing_tag;
795 }
796 else {
797 id->tag |= tag;
798 }
799 return is_missing;
800 }
801 bool id_tag_clear(ID *id, const bool is_missing)
802 {
805 }
806 else if (is_missing) {
807 id->tag &= ~missing_tag;
808 }
809 else {
810 id->tag &= ~tag;
811 }
812 return is_missing;
813 }
814
815 /* Mapping linked objects to all their instantiating collections (as a linked list).
816 * Avoids calling #BKE_collection_object_find over and over, this function is very expansive. */
819
820 void clear()
821 {
825
826 bmain = nullptr;
827 scene = nullptr;
828 id_root_reference = nullptr;
830 id_root_override = nullptr;
832 tag = 0;
833 missing_tag = 0;
834 is_override = false;
835 is_resync = false;
836 }
837};
838
840 LibOverrideGroupTagData *data, Collection *collection)
841{
842 LISTBASE_FOREACH (CollectionObject *, collection_object, &collection->gobject) {
843 Object *ob = collection_object->ob;
844 if (!ID_IS_LINKED(ob)) {
845 continue;
846 }
847
848 LinkNodePair **collections_linkedlist_p;
849 if (!BLI_ghash_ensure_p(data->linked_object_to_instantiating_collections,
850 ob,
851 reinterpret_cast<void ***>(&collections_linkedlist_p)))
852 {
853 *collections_linkedlist_p = static_cast<LinkNodePair *>(
854 BLI_memarena_calloc(data->mem_arena, sizeof(**collections_linkedlist_p)));
855 }
856 BLI_linklist_append_arena(*collections_linkedlist_p, collection, data->mem_arena);
857 }
858}
859
860/* Initialize complex data, `data` is expected to be already initialized with basic pointers and
861 * other simple data.
862 *
863 * NOTE: Currently creates a mapping from linked object to all of their instantiating collections
864 * (as returned by #BKE_collection_object_find). */
866{
867 data->mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
868
869 data->linked_object_to_instantiating_collections = BLI_ghash_new(
871 if (data->scene != nullptr) {
873 data, data->scene->master_collection);
874 }
875 LISTBASE_FOREACH (Collection *, collection, &data->bmain->collections) {
877 }
878}
879
880/* Checks that can decide to skip the ID based only on the matching #MainIDRelationsEntryItem data
881 * representing the relationship of that ID with its owner ID. */
883 MainIDRelationsEntryItem *relation_id_entry)
884{
885 /* Skip all relationships that should never be taken into account to define a liboverride
886 * hierarchy ('from', 'parents', 'owner' etc. pointers). */
887 if ((relation_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
888 return true;
889 }
890 return false;
891}
892
893/* Checks that can decide to skip the ID based on some of its data and the one from its owner. */
895 ID *other_id,
896 const bool check_override)
897{
898 /* Skip relationships to null pointer, or to itself. */
899 if (ELEM(other_id, nullptr, owner_id)) {
900 return true;
901 }
902 /* Skip any relationships to data from another library. */
903 if (other_id->lib != owner_id->lib) {
904 return true;
905 }
906 /* Skip relationships to non-override data if requested. */
907 if (check_override) {
909 ID_IS_OVERRIDE_LIBRARY(owner_id),
910 "When processing liboverrides, the owner ID should always be a liboverride too here.");
911 if (!ID_IS_OVERRIDE_LIBRARY(other_id)) {
912 return true;
913 }
914 }
915 /* Skip relationships to IDs that should not be involved in liboverrides currently.
916 * NOTE: The Scene case is a bit specific:
917 * - While not officially supported, API allow to create liboverrides of whole Scene.
918 * - However, when creating liboverrides from other type of data (e.g. collections or
919 * objects), scenes should really not be considered as part of a hierarchy. If there
920 * are dependencies from other overridden IDs to a scene, this is considered as not
921 * supported (see also #121410). */
922#define HIERARCHY_BREAKING_ID_TYPES ID_SCE, ID_LI, ID_SCR, ID_WM, ID_WS
923 if (ELEM(GS(other_id->name), HIERARCHY_BREAKING_ID_TYPES) &&
925 {
926 return true;
927 }
928#undef HIERARCHY_BREAKING_ID_TYPES
929
930 return false;
931}
932
934{
935 Main *bmain = data->bmain;
936 ID *id = data->root_get();
937 const bool is_override = data->is_override;
938
939 if ((*reinterpret_cast<uint *>(&id->tag) & data->tag) == 0) {
940 /* This ID is not tagged, no reason to proceed further to its parents. */
941 return;
942 }
943
944 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
946 BLI_assert(entry != nullptr);
947
949 /* This ID has already been processed. */
950 return;
951 }
952 /* This way we won't process again that ID, should we encounter it again through another
953 * relationship hierarchy. */
955
956 for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != nullptr;
957 from_id_entry = from_id_entry->next)
958 {
960 continue;
961 }
962 ID *from_id = from_id_entry->id_pointer.from;
963 if (lib_override_hierarchy_dependencies_skip_check(id, from_id, is_override)) {
964 continue;
965 }
966
967 from_id->tag |= data->tag;
968 data->root_set(from_id);
970 }
971 data->root_set(id);
972}
973
974/* Tag all IDs in dependency relationships within an override hierarchy/group.
975 *
976 * Requires existing `Main.relations`.
977 *
978 * NOTE: This is typically called to complete #lib_override_linked_group_tag.
979 */
981{
982 Main *bmain = data->bmain;
983 ID *id = data->root_get();
984 const bool is_override = data->is_override;
985 const bool is_resync = data->is_resync;
986
987 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
989 BLI_assert(entry != nullptr);
990
992 /* This ID has already been processed. */
993 return (*reinterpret_cast<uint *>(&id->tag) & data->tag) != 0;
994 }
995 /* This way we won't process again that ID, should we encounter it again through another
996 * relationship hierarchy. */
998
999 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
1000 to_id_entry = to_id_entry->next)
1001 {
1003 continue;
1004 }
1005 ID *to_id = *to_id_entry->id_pointer.to;
1006 if (lib_override_hierarchy_dependencies_skip_check(id, to_id, is_override)) {
1007 continue;
1008 }
1009
1010 data->root_set(to_id);
1012 id->tag |= data->tag;
1013 }
1014 }
1015 data->root_set(id);
1016
1017 /* If the current ID is/has been tagged for override above, then check its reversed dependencies
1018 * (i.e. IDs that depend on the current one).
1019 *
1020 * This will cover e.g. the case where user override an armature, and would expect the mesh
1021 * object deformed by that armature to also be overridden. */
1022 if ((*reinterpret_cast<uint *>(&id->tag) & data->tag) != 0 && !is_resync) {
1024 }
1025
1026 return (*reinterpret_cast<uint *>(&id->tag) & data->tag) != 0;
1027}
1028
1030{
1031 Main *bmain = data->bmain;
1032 ID *id_owner = data->root_get();
1033 BLI_assert(ID_IS_LINKED(id_owner));
1034 BLI_assert(!data->is_override);
1035
1036 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
1038 BLI_assert(entry != nullptr);
1039
1041 /* This ID has already been processed. */
1042 return;
1043 }
1044 /* This way we won't process again that ID, should we encounter it again through another
1045 * relationship hierarchy. */
1047
1048 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
1049 to_id_entry = to_id_entry->next)
1050 {
1052 continue;
1053 }
1054 ID *to_id = *to_id_entry->id_pointer.to;
1055 BLI_assert(ID_IS_LINKED(to_id));
1056 if (lib_override_hierarchy_dependencies_skip_check(id_owner, to_id, false)) {
1057 continue;
1058 }
1059
1060 /* Only tag ID if their usages is tagged as requiring liboverride by default, and the owner is
1061 * already tagged for liboverride.
1062 *
1063 * NOTE: 'in-between' IDs are handled as a separate step, typically by calling
1064 * #lib_override_hierarchy_dependencies_recursive_tag.
1065 * NOTE: missing IDs (aka placeholders) are never overridden. */
1066 if ((to_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_HIERARCHY_DEFAULT) != 0 ||
1067 data->linked_ids_hierarchy_default_override.contains(to_id))
1068 {
1069 if (!data->id_tag_set(to_id, bool(to_id->tag & ID_TAG_MISSING))) {
1070 /* Only recursively process the dependencies if the owner is tagged for liboverride. */
1071 data->root_set(to_id);
1073 }
1074 }
1075 }
1076 data->root_set(id_owner);
1077}
1078
1080 LibOverrideGroupTagData *data, Collection *collection)
1081{
1082 /* NOTE: Collection's object cache (using bases, as returned by #BKE_collection_object_cache_get)
1083 * is not usable here, as it may have become invalid from some previous operation and it should
1084 * not be updated here. So instead only use collections' reliable 'raw' data to check if some
1085 * object in the hierarchy of the given collection is still tagged for override. */
1086 for (CollectionObject *collection_object =
1087 static_cast<CollectionObject *>(collection->gobject.first);
1088 collection_object != nullptr;
1089 collection_object = collection_object->next)
1090 {
1091 Object *object = collection_object->ob;
1092 if (object == nullptr) {
1093 continue;
1094 }
1095 if ((object->id.tag & data->tag) != 0 ||
1096 data->linked_ids_hierarchy_default_override.contains(&object->id))
1097 {
1098 return true;
1099 }
1100 }
1101
1102 for (CollectionChild *collection_child =
1103 static_cast<CollectionChild *>(collection->children.first);
1104 collection_child != nullptr;
1105 collection_child = collection_child->next)
1106 {
1108 data, collection_child->collection))
1109 {
1110 return true;
1111 }
1112 }
1113
1114 return false;
1115}
1116
1118{
1119 Main *bmain = data->bmain;
1120 ID *id_root = data->root_get();
1121
1122 /* Remove (untag) bone shape objects, they shall never need to be to directly/explicitly
1123 * overridden. */
1124 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
1125 if (ob->id.lib != id_root->lib) {
1126 continue;
1127 }
1128 if (ob->type == OB_ARMATURE && ob->pose != nullptr &&
1129 ((ob->id.tag & data->tag) ||
1130 data->linked_ids_hierarchy_default_override.contains(&ob->id)))
1131 {
1132 for (bPoseChannel *pchan = static_cast<bPoseChannel *>(ob->pose->chanbase.first);
1133 pchan != nullptr;
1134 pchan = pchan->next)
1135 {
1136 if (pchan->custom != nullptr && &pchan->custom->id != id_root) {
1137 data->id_tag_clear(&pchan->custom->id, bool(pchan->custom->id.tag & ID_TAG_MISSING));
1138 }
1139 }
1140 }
1141 }
1142
1143 /* Remove (untag) collections if they do not own any tagged object (either themselves, or in
1144 * their children collections). */
1145 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
1146 if (!((collection->id.tag & data->tag) != 0 ||
1147 data->linked_ids_hierarchy_default_override.contains(&collection->id)) ||
1148 &collection->id == id_root || collection->id.lib != id_root->lib)
1149 {
1150 continue;
1151 }
1152
1154 data->id_tag_clear(&collection->id, bool(collection->id.tag & ID_TAG_MISSING));
1155 }
1156 }
1157}
1158
1159/* This will tag at least all 'boundary' linked IDs for a potential override group.
1160 *
1161 * Requires existing `Main.relations`.
1162 *
1163 * Note that you will then need to call #lib_override_hierarchy_dependencies_recursive_tag to
1164 * complete tagging of all dependencies within the override group.
1165 *
1166 * We currently only consider IDs which usages are marked as to be overridden by default (i.e.
1167 * tagged with #IDWALK_CB_OVERRIDE_LIBRARY_HIERARCHY_DEFAULT) as valid boundary IDs to define an
1168 * override group.
1169 */
1171{
1172 Main *bmain = data->bmain;
1173 ID *id_root = data->root_get();
1174 ID *hierarchy_root_id = data->hierarchy_root_get();
1175 const bool is_resync = data->is_resync;
1176 BLI_assert(!data->is_override);
1177
1178 if (id_root->tag & ID_TAG_MISSING) {
1179 id_root->tag |= data->missing_tag;
1180 return;
1181 }
1182
1183 /* In case this code only process part of the whole hierarchy, it first needs to process the
1184 * whole linked hierarchy to know which IDs should be overridden anyway, even though in the more
1185 * limited sub-hierarchy scope they would not be. This is critical for partial resync to work
1186 * properly.
1187 *
1188 * NOTE: Regenerating that Set for every processed sub-hierarchy is not optimal. This is done
1189 * that way for now to limit the scope of these changes. Better handling is considered a TODO for
1190 * later (as part of a general refactoring/modernization of this whole code area). */
1191
1192 const bool use_linked_overrides_set = hierarchy_root_id &&
1193 hierarchy_root_id->lib == id_root->lib &&
1194 hierarchy_root_id != id_root;
1195
1196 BLI_assert(data->do_create_linked_overrides_set == false);
1197 if (use_linked_overrides_set) {
1198 BLI_assert(data->linked_ids_hierarchy_default_override.is_empty());
1199 data->linked_ids_hierarchy_default_override.add(id_root);
1200 data->linked_ids_hierarchy_default_override.add(hierarchy_root_id);
1201 data->do_create_linked_overrides_set = true;
1202
1203 /* Store recursively all IDs in the hierarchy which should be liboverridden by default. */
1204 data->root_set(hierarchy_root_id);
1206
1207 /* Do not override objects used as bone shapes, nor their collections if possible. */
1209
1211 data->root_set(id_root);
1212 data->do_create_linked_overrides_set = false;
1213 }
1214
1215 /* Tag recursively all IDs in the hierarchy which should be liboverridden by default. */
1216 id_root->tag |= data->tag;
1218
1219 /* Do not override objects used as bone shapes, nor their collections if possible. */
1221
1222 if (use_linked_overrides_set) {
1223 data->linked_ids_hierarchy_default_override.clear();
1224 }
1225
1226 /* For each object tagged for override, ensure we get at least one local or liboverride
1227 * collection to host it. Avoids getting a bunch of random object in the scene's master
1228 * collection when all objects' dependencies are not properly 'packed' into a single root
1229 * collection.
1230 *
1231 * NOTE: In resync case, we do not handle this at all, since:
1232 * - In normal, valid cases nothing would be needed anyway (resync process takes care
1233 * of tagging needed 'owner' collection then).
1234 * - Partial resync makes it extremely difficult to properly handle such extra
1235 * collection 'tagging for override' (since one would need to know if the new object
1236 * is actually going to replace an already existing override [most common case], or
1237 * if it is actually a real new 'orphan' one).
1238 * - While not ideal, having objects dangling around is less critical than both points
1239 * above.
1240 * So if users add new objects to their library override hierarchy in an invalid way, so
1241 * be it. Trying to find a collection to override and host this new object would most
1242 * likely make existing override very unclean anyway. */
1243 if (is_resync) {
1244 return;
1245 }
1246 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
1247 if (ID_IS_LINKED(ob) && (ob->id.tag & data->tag) != 0) {
1248 Collection *instantiating_collection = nullptr;
1249 Collection *instantiating_collection_override_candidate = nullptr;
1250 /* Loop over all collections instantiating the object, if we already have a 'locale' one we
1251 * have nothing to do, otherwise try to find a 'linked' one that we can override too. */
1252 LinkNodePair *instantiating_collection_linklist = static_cast<LinkNodePair *>(
1253 BLI_ghash_lookup(data->linked_object_to_instantiating_collections, ob));
1254 if (instantiating_collection_linklist != nullptr) {
1255 for (LinkNode *instantiating_collection_linknode = instantiating_collection_linklist->list;
1256 instantiating_collection_linknode != nullptr;
1257 instantiating_collection_linknode = instantiating_collection_linknode->next)
1258 {
1259 instantiating_collection = static_cast<Collection *>(
1260 instantiating_collection_linknode->link);
1261 if (!ID_IS_LINKED(instantiating_collection)) {
1262 /* There is a local collection instantiating the linked object to override, nothing
1263 * else to be done here. */
1264 break;
1265 }
1266 if (instantiating_collection->id.tag & data->tag ||
1267 data->linked_ids_hierarchy_default_override.contains(&instantiating_collection->id))
1268 {
1269 /* There is a linked collection instantiating the linked object to override,
1270 * already tagged to be overridden, nothing else to be done here. */
1271 break;
1272 }
1273 instantiating_collection_override_candidate = instantiating_collection;
1274 instantiating_collection = nullptr;
1275 }
1276 }
1277
1278 if (instantiating_collection == nullptr &&
1279 instantiating_collection_override_candidate != nullptr)
1280 {
1281 data->id_tag_set(
1282 &instantiating_collection_override_candidate->id,
1283 bool(instantiating_collection_override_candidate->id.tag & ID_TAG_MISSING));
1284 }
1285 }
1286 }
1287}
1288
1290{
1291 Main *bmain = data->bmain;
1292 ID *id_owner = data->root_get();
1294 BLI_assert(data->is_override);
1295 BLI_assert(data->do_create_linked_overrides_set == false);
1296
1297 ID *id_hierarchy_root = data->hierarchy_root_get();
1298
1299 if (ID_IS_OVERRIDE_LIBRARY_REAL(id_owner) &&
1301 {
1302 return;
1303 }
1304
1305 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
1307 BLI_assert(entry != nullptr);
1308
1310 /* This ID has already been processed. */
1311 return;
1312 }
1313 /* This way we won't process again that ID, should we encounter it again through another
1314 * relationship hierarchy. */
1316
1317 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
1318 to_id_entry = to_id_entry->next)
1319 {
1321 continue;
1322 }
1323 ID *to_id = *to_id_entry->id_pointer.to;
1324 if (lib_override_hierarchy_dependencies_skip_check(id_owner, to_id, true)) {
1325 continue;
1326 }
1327
1328 /* Different hierarchy roots are break points in override hierarchies. */
1329 if (ID_IS_OVERRIDE_LIBRARY_REAL(to_id) &&
1330 to_id->override_library->hierarchy_root != id_hierarchy_root)
1331 {
1332 continue;
1333 }
1334
1335 const Library *reference_lib =
1336 BKE_lib_override_library_get(bmain, id_owner, nullptr, nullptr)->reference->lib;
1337 const ID *to_id_reference =
1338 BKE_lib_override_library_get(bmain, to_id, nullptr, nullptr)->reference;
1339 if (to_id_reference->lib != reference_lib) {
1340 /* We do not override data-blocks from other libraries, nor do we process them. */
1341 continue;
1342 }
1343
1344 data->id_tag_set(to_id, bool(to_id_reference->tag & ID_TAG_MISSING));
1345
1346 /* Recursively process the dependencies. */
1347 data->root_set(to_id);
1349 }
1350 data->root_set(id_owner);
1351}
1352
1353/* This will tag all override IDs of an override group defined by the given `id_root`. */
1355{
1356 ID *id_root = data->root_get();
1358 BLI_assert(data->is_override);
1359 BLI_assert(data->do_create_linked_overrides_set == false);
1360
1361 ID *id_hierarchy_root = data->hierarchy_root_get();
1362 BLI_assert(id_hierarchy_root != nullptr);
1363 BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root));
1364 UNUSED_VARS_NDEBUG(id_hierarchy_root);
1365
1366 data->id_tag_set(id_root, bool(id_root->override_library->reference->tag & ID_TAG_MISSING));
1367
1368 /* Tag all local overrides in id_root's group. */
1370}
1371
1373 Scene *scene,
1374 Library *owner_library,
1375 ID *id_root_reference,
1376 ID *id_hierarchy_root_reference,
1377 const bool do_fully_editable)
1378{
1379 BKE_main_relations_create(bmain, 0);
1381 data.bmain = bmain;
1382 data.scene = scene;
1383 data.tag = ID_TAG_DOIT;
1384 data.missing_tag = ID_TAG_MISSING;
1385 data.is_override = false;
1386 data.is_resync = false;
1387
1388 data.root_set(id_root_reference);
1389 data.hierarchy_root_set(id_hierarchy_root_reference);
1390
1393
1396
1397 /* In case the operation is on an already partially overridden hierarchy, all existing overrides
1398 * in that hierarchy need to be tagged for remapping from linked reference ID usages to newly
1399 * created overrides ones. */
1400 if (id_hierarchy_root_reference->lib != id_root_reference->lib) {
1401 BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root_reference));
1402 BLI_assert(id_hierarchy_root_reference->override_library->reference->lib ==
1403 id_root_reference->lib);
1404
1406 data.is_override = true;
1407 data.root_set(id_hierarchy_root_reference);
1408 data.hierarchy_root_set(id_hierarchy_root_reference);
1410 }
1411
1413 data.clear();
1414
1415 bool success = false;
1416 if (id_hierarchy_root_reference->lib != id_root_reference->lib) {
1418 owner_library,
1419 id_root_reference,
1420 id_hierarchy_root_reference,
1421 nullptr,
1422 false,
1423 do_fully_editable);
1424 }
1425 else {
1427 owner_library,
1428 id_root_reference,
1429 nullptr,
1430 id_hierarchy_root_reference,
1431 false,
1432 do_fully_editable);
1433 }
1434
1435 /* Cleanup global namemap, to avoid extra processing with regular ID name management. Better to
1436 * re-create the global namemap on demand. */
1438
1439 return success;
1440}
1441
1443 Scene *scene,
1444 ViewLayer *view_layer,
1445 const Library *owner_library,
1446 ID *id_root,
1447 ID *id_instance_hint,
1448 Collection *residual_storage,
1449 const Object *old_active_object,
1450 const bool is_resync)
1451{
1452 /* If there is an old active object, there should also always be a given view layer. */
1453 BLI_assert(old_active_object == nullptr || view_layer != nullptr);
1454
1455 /* NOTE: We only care about local IDs here, if a linked object is not instantiated in any way we
1456 * do not do anything about it. */
1457
1458 /* We need to use the `_remap` version here as we prevented any LayerCollection resync during the
1459 * whole liboverride resyncing, which involves a lot of ID remapping.
1460 *
1461 * Otherwise, cached Base GHash e.g. can contain invalid stale data. */
1463
1464 /* We create a set of all objects referenced into the scene by its hierarchy of collections.
1465 * NOTE: This is different that the list of bases, since objects in excluded collections etc.
1466 * won't have a base, but are still considered as instanced from our point of view. */
1467 GSet *all_objects_in_scene = BKE_scene_objects_as_gset(scene, nullptr);
1468
1469 if (is_resync || id_root == nullptr || id_root->newid == nullptr) {
1470 /* Instantiating the root collection or object should never be needed in resync case, since the
1471 * old override would be remapped to the new one. */
1472 }
1473 else if (ID_IS_LINKED(id_root->newid) && id_root->newid->lib != owner_library) {
1474 /* No instantiation in case the root override is linked data, unless it is part of the given
1475 * owner library.
1476 *
1477 * NOTE: that last case should never happen actually in current code? Since non-null owner
1478 * library should only happen in case of recursive resync, which is already excluded by the
1479 * previous condition. */
1480 }
1481 else if ((id_root->newid->override_library->flag & LIBOVERRIDE_FLAG_NO_HIERARCHY) == 0 &&
1482 id_root->newid->override_library->hierarchy_root != id_root->newid)
1483 {
1484 /* No instantiation in case this is not a hierarchy root, as it can be assumed already handled
1485 * as part of hierarchy processing. */
1486 }
1487 else {
1488 switch (GS(id_root->name)) {
1489 case ID_GR: {
1490 Object *ob_reference = id_instance_hint != nullptr && GS(id_instance_hint->name) == ID_OB ?
1491 reinterpret_cast<Object *>(id_instance_hint) :
1492 nullptr;
1493 Collection *collection_new = (reinterpret_cast<Collection *>(id_root->newid));
1494 if (is_resync && BKE_collection_is_in_scene(collection_new)) {
1495 break;
1496 }
1497 if (ob_reference != nullptr) {
1498 BKE_collection_add_from_object(bmain, scene, ob_reference, collection_new);
1499 }
1500 else if (id_instance_hint != nullptr) {
1501 BLI_assert(GS(id_instance_hint->name) == ID_GR);
1503 bmain, scene, (reinterpret_cast<Collection *>(id_instance_hint)), collection_new);
1504 }
1505 else {
1507 bmain, scene, (reinterpret_cast<Collection *>(id_root)), collection_new);
1508 }
1509
1510 BLI_assert(BKE_collection_is_in_scene(collection_new));
1511
1512 all_objects_in_scene = BKE_scene_objects_as_gset(scene, all_objects_in_scene);
1513 break;
1514 }
1515 case ID_OB: {
1516 Object *ob_new = reinterpret_cast<Object *>(id_root->newid);
1517 if (BLI_gset_lookup(all_objects_in_scene, ob_new) == nullptr) {
1519 bmain, scene, reinterpret_cast<Object *>(id_root), ob_new);
1520 all_objects_in_scene = BKE_scene_objects_as_gset(scene, all_objects_in_scene);
1521 }
1522 break;
1523 }
1524 default:
1525 break;
1526 }
1527 }
1528
1529 if (view_layer != nullptr) {
1530 BKE_view_layer_synced_ensure(scene, view_layer);
1531 }
1532 else {
1534 }
1535
1536 /* We need to ensure all new overrides of objects are properly instantiated. */
1537 Collection *default_instantiating_collection = residual_storage;
1538 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
1539 Object *ob_new = reinterpret_cast<Object *>(ob->id.newid);
1540 if (ob_new == nullptr || (ID_IS_LINKED(ob_new) && ob_new->id.lib != owner_library)) {
1541 continue;
1542 }
1543
1544 BLI_assert(ob_new->id.override_library != nullptr &&
1545 ob_new->id.override_library->reference == &ob->id);
1546
1547 if (old_active_object == ob) {
1548 BLI_assert(view_layer);
1549 /* May have been tagged as dirty again in a previous iteration of this loop, e.g. if adding a
1550 * liboverride object to a collection. */
1551 BKE_view_layer_synced_ensure(scene, view_layer);
1552 Base *basact = BKE_view_layer_base_find(view_layer, ob_new);
1553 if (basact != nullptr) {
1554 view_layer->basact = basact;
1555 }
1557 }
1558
1559 if (BLI_gset_lookup(all_objects_in_scene, ob_new) == nullptr) {
1560 if (id_root != nullptr && default_instantiating_collection == nullptr) {
1561 ID *id_ref = id_root->newid != nullptr ? id_root->newid : id_root;
1562 switch (GS(id_ref->name)) {
1563 case ID_GR: {
1564 /* Adding the object to a specific collection outside of the root overridden one is a
1565 * fairly bad idea (it breaks the override hierarchy concept). But there is no other
1566 * way to do this currently (we cannot add new collections to overridden root one,
1567 * this is not currently supported).
1568 * Since that will be fairly annoying and noisy, only do that in case the override
1569 * object is not part of any existing collection (i.e. its user count is 0). In
1570 * practice this should never happen I think. */
1571 if (ID_REAL_USERS(ob_new) != 0) {
1572 continue;
1573 }
1574 default_instantiating_collection = static_cast<Collection *>(
1575 BKE_id_new(bmain, ID_GR, "OVERRIDE_HIDDEN"));
1576 id_us_min(&default_instantiating_collection->id);
1577 /* Hide the collection from viewport and render. */
1578 default_instantiating_collection->flag |= COLLECTION_HIDE_VIEWPORT |
1580 break;
1581 }
1582 case ID_OB: {
1583 /* Add the other objects to one of the collections instantiating the
1584 * root object, or scene's master collection if none found. */
1585 Object *ob_ref = reinterpret_cast<Object *>(id_ref);
1586 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
1587 if (BKE_collection_has_object(collection, ob_ref) &&
1588 (view_layer != nullptr ?
1589 BKE_view_layer_has_collection(view_layer, collection) :
1590 BKE_collection_has_collection(scene->master_collection, collection)) &&
1591 !ID_IS_LINKED(collection) && !ID_IS_OVERRIDE_LIBRARY(collection))
1592 {
1593 default_instantiating_collection = collection;
1594 }
1595 }
1596 break;
1597 }
1598 default:
1599 break;
1600 }
1601 }
1602 if (default_instantiating_collection == nullptr) {
1603 default_instantiating_collection = scene->master_collection;
1604 }
1605
1606 BKE_collection_object_add(bmain, default_instantiating_collection, ob_new);
1608 }
1609 }
1610
1611 if (id_root != nullptr &&
1612 !ELEM(default_instantiating_collection, nullptr, scene->master_collection))
1613 {
1614 ID *id_ref = id_root->newid != nullptr ? id_root->newid : id_root;
1615 switch (GS(id_ref->name)) {
1616 case ID_GR:
1618 scene,
1619 reinterpret_cast<Collection *>(id_ref),
1620 default_instantiating_collection);
1621 break;
1622 default:
1623 /* Add to master collection. */
1625 bmain, scene, nullptr, default_instantiating_collection);
1626 break;
1627 }
1628 }
1629
1630 BLI_gset_free(all_objects_in_scene, nullptr);
1631}
1632
1634 Scene *scene,
1635 ViewLayer *view_layer,
1636 Library *owner_library,
1637 ID *id_root_reference,
1638 ID *id_hierarchy_root_reference,
1639 ID *id_instance_hint,
1640 ID **r_id_root_override,
1641 const bool do_fully_editable)
1642{
1643 if (r_id_root_override != nullptr) {
1644 *r_id_root_override = nullptr;
1645 }
1646
1647 if (id_hierarchy_root_reference == nullptr) {
1648 id_hierarchy_root_reference = id_root_reference;
1649 }
1650
1651 /* While in theory it _should_ be enough to ensure sync of given view-layer (if any), or at least
1652 * of given scene, think for now it's better to get a fully synced Main at this point, this code
1653 * may do some very wide remapping/data access in some cases. */
1655 const Object *old_active_object = (view_layer != nullptr) ?
1657 nullptr;
1658
1659 const bool success = lib_override_library_create_do(bmain,
1660 scene,
1661 owner_library,
1662 id_root_reference,
1663 id_hierarchy_root_reference,
1664 do_fully_editable);
1665
1666 if (!success) {
1667 return success;
1668 }
1669
1670 if (r_id_root_override != nullptr) {
1671 *r_id_root_override = id_root_reference->newid;
1672 }
1673
1675 scene,
1676 view_layer,
1677 owner_library,
1678 id_root_reference,
1679 id_instance_hint,
1680 nullptr,
1681 old_active_object,
1682 false);
1683
1684 /* Cleanup. */
1686 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
1687
1688 /* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
1690
1691 return success;
1692}
1693
1694static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int *r_best_level)
1695{
1696 if (curr_level > 1000) {
1697 CLOG_ERROR(&LOG,
1698 "Levels of dependency relationships between library overrides IDs is way too high, "
1699 "skipping further processing loops (involves at least '%s')",
1700 id->name);
1701 return nullptr;
1702 }
1703
1704 if (!ID_IS_OVERRIDE_LIBRARY(id)) {
1706 return nullptr;
1707 }
1708
1709 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
1711 BLI_assert(entry != nullptr);
1712
1715 /* This ID has already been processed. */
1716 *r_best_level = curr_level;
1717 return id->override_library->hierarchy_root;
1718 }
1719
1721 ID *id_owner;
1722 int best_level_placeholder = 0;
1723 BKE_lib_override_library_get(bmain, id, nullptr, &id_owner);
1724 return lib_override_root_find(bmain, id_owner, curr_level + 1, &best_level_placeholder);
1725 }
1726
1728 /* Re-processing an entry already being processed higher in the call-graph (re-entry caused by
1729 * a dependency loops). Just do nothing, there is no more useful info to provide here. */
1730 return nullptr;
1731 }
1732 /* Flag this entry to avoid re-processing it in case some dependency loop leads to it again
1733 * downwards in the call-stack. */
1735
1736 int best_level_candidate = curr_level;
1737 ID *best_root_id_candidate = id;
1738
1739 for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != nullptr;
1740 from_id_entry = from_id_entry->next)
1741 {
1743 continue;
1744 }
1745 ID *from_id = from_id_entry->id_pointer.from;
1746 if (lib_override_hierarchy_dependencies_skip_check(id, from_id, true)) {
1747 continue;
1748 }
1749
1750 int level_candidate = curr_level + 1;
1751 /* Recursively process the parent. */
1752 ID *root_id_candidate = lib_override_root_find(
1753 bmain, from_id, curr_level + 1, &level_candidate);
1754 if (level_candidate > best_level_candidate && root_id_candidate != nullptr) {
1755 best_root_id_candidate = root_id_candidate;
1756 best_level_candidate = level_candidate;
1757 }
1758 }
1759
1760 if (!ID_IS_OVERRIDE_LIBRARY_REAL(best_root_id_candidate)) {
1762 ID *id_owner;
1763 int best_level_placeholder = 0;
1764 BKE_lib_override_library_get(bmain, best_root_id_candidate, nullptr, &id_owner);
1765 best_root_id_candidate = lib_override_root_find(
1766 bmain, id_owner, curr_level + 1, &best_level_placeholder);
1767 }
1768
1769 BLI_assert(best_root_id_candidate != nullptr);
1770 BLI_assert((best_root_id_candidate->flag & ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE) == 0);
1771
1772 /* This way this ID won't be processed again, should it be encountered again through another
1773 * relationship hierarchy. */
1774 entry->tags &= ~MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS;
1776
1777 *r_best_level = best_level_candidate;
1778 return best_root_id_candidate;
1779}
1780
1782 Main *bmain, ID *id_root, ID *id, ID *id_from, blender::Set<ID *> &processed_ids)
1783{
1784 if (processed_ids.contains(id)) {
1785 /* This ID has already been checked as having a valid hierarchy root, do not attempt to replace
1786 * it with another one just because it is also used by another liboverride hierarchy. */
1787 return;
1788 }
1790 if (id->override_library->hierarchy_root == id_root) {
1791 /* Already set, nothing else to do here, sub-hierarchy is also assumed to be properly set
1792 * then. */
1793 return;
1794 }
1795
1796 /* Hierarchy root already set, and not matching currently proposed one, try to find which is
1797 * best. */
1798 if (id->override_library->hierarchy_root != nullptr) {
1799 /* Check if given `id_from` matches with the hierarchy of the linked reference ID, in which
1800 * case we assume that the given hierarchy root is the 'real' one.
1801 *
1802 * NOTE: This can fail if user mixed dependencies between several overrides of a same
1803 * reference linked hierarchy. Not much to be done in that case, it's virtually impossible to
1804 * fix this automatically in a reliable way. */
1805 if (id_from == nullptr || !ID_IS_OVERRIDE_LIBRARY_REAL(id_from)) {
1806 /* Too complicated to deal with for now. */
1807 CLOG_WARN(&LOG,
1808 "Inconsistency in library override hierarchy of ID '%s'.\n"
1809 "\tNot enough data to verify validity of current proposed root '%s', assuming "
1810 "already set one '%s' is valid.",
1811 id->name,
1812 id_root->name,
1813 id->override_library->hierarchy_root->name);
1814 return;
1815 }
1816
1817 ID *id_from_ref = id_from->override_library->reference;
1819 bmain->relations->relations_from_pointers, id->override_library->reference));
1820 BLI_assert(entry != nullptr);
1821
1822 /* Enforce replacing hierarchy root if the current one is invalid. */
1823 bool do_replace_root = (!id->override_library->hierarchy_root ||
1824 !ID_IS_OVERRIDE_LIBRARY_REAL(id->override_library->hierarchy_root) ||
1825 id->override_library->hierarchy_root->lib != id->lib);
1826 for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != nullptr;
1827 from_id_entry = from_id_entry->next)
1828 {
1829 if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
1830 /* Never consider non-overridable relationships as actual dependencies. */
1831 continue;
1832 }
1833
1834 if (id_from_ref == from_id_entry->id_pointer.from) {
1835 /* A matching parent was found in reference linked data, assume given hierarchy root is
1836 * the valid one. */
1837 do_replace_root = true;
1838 CLOG_WARN(
1839 &LOG,
1840 "Inconsistency in library override hierarchy of ID '%s'.\n"
1841 "\tCurrent proposed root '%s' detected as valid, will replace already set one '%s'.",
1842 id->name,
1843 id_root->name,
1844 id->override_library->hierarchy_root->name);
1845 break;
1846 }
1847 }
1848
1849 if (!do_replace_root) {
1850 CLOG_WARN(
1851 &LOG,
1852 "Inconsistency in library override hierarchy of ID '%s'.\n"
1853 "\tCurrent proposed root '%s' not detected as valid, keeping already set one '%s'.",
1854 id->name,
1855 id_root->name,
1856 id->override_library->hierarchy_root->name);
1857 return;
1858 }
1859 }
1860
1861 CLOG_INFO(&LOG,
1862 3,
1863 "Modifying library override hierarchy of ID '%s'.\n"
1864 "\tFrom old root '%s' to new root '%s'.",
1865 id->name,
1866 id->override_library->hierarchy_root ? id->override_library->hierarchy_root->name :
1867 "<NONE>",
1868 id_root->name);
1869
1870 id->override_library->hierarchy_root = id_root;
1871 }
1872
1873 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
1875 BLI_assert(entry != nullptr);
1876
1877 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
1878 to_id_entry = to_id_entry->next)
1879 {
1881 continue;
1882 }
1883 ID *to_id = *to_id_entry->id_pointer.to;
1885 continue;
1886 }
1887
1888 /* Recursively process the sub-hierarchy. */
1889 lib_override_root_hierarchy_set(bmain, id_root, to_id, id, processed_ids);
1890 }
1891}
1892
1894{
1895 ID *id;
1896
1897 BKE_main_relations_create(bmain, 0);
1898 blender::Set<ID *> processed_ids;
1899
1900 FOREACH_MAIN_ID_BEGIN (bmain, id) {
1901 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
1902 processed_ids.add(id);
1903 continue;
1904 }
1905 if (id->override_library->hierarchy_root != nullptr) {
1906 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id->override_library->hierarchy_root) ||
1907 id->override_library->hierarchy_root->lib != id->lib)
1908 {
1909 CLOG_ERROR(
1910 &LOG,
1911 "Existing override hierarchy root ('%s') for ID '%s' is invalid, will try to find a "
1912 "new valid one",
1913 id->override_library->hierarchy_root != nullptr ?
1914 id->override_library->hierarchy_root->name :
1915 "<NONE>",
1916 id->name);
1917 id->override_library->hierarchy_root = nullptr;
1918 }
1919 else {
1920 /* This ID is considered as having a valid hierarchy root. */
1921 processed_ids.add(id);
1922 continue;
1923 }
1924 }
1925
1928
1929 int best_level = 0;
1930 ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
1931
1932 if (!ELEM(id->override_library->hierarchy_root, id_root, nullptr)) {
1933 /* In case the detected hierarchy root does not match with the currently defined one, this is
1934 * likely an issue and is worth a warning. */
1935 CLOG_WARN(&LOG,
1936 "Potential inconsistency in library override hierarchy of ID '%s' (current root "
1937 "%s), detected as part of the hierarchy of '%s' (current root '%s')",
1938 id->name,
1939 id->override_library->hierarchy_root != nullptr ?
1940 id->override_library->hierarchy_root->name :
1941 "<NONE>",
1942 id_root->name,
1943 id_root->override_library->hierarchy_root != nullptr ?
1945 "<NONE>");
1946 processed_ids.add(id);
1947 continue;
1948 }
1949
1950 lib_override_root_hierarchy_set(bmain, id_root, id, nullptr, processed_ids);
1951
1952 BLI_assert(id->override_library->hierarchy_root != nullptr);
1953 }
1955
1957}
1958
1960 Main *bmain,
1961 const ID *id_root_reference,
1962 blender::Vector<std::pair<ID *, ID *>> &references_and_new_overrides,
1963 GHash *linkedref_to_old_override)
1964{
1965 id::IDRemapper remapper_overrides_old_to_new;
1966 blender::Vector<ID *> nomain_ids;
1967 blender::Vector<ID *> new_overrides;
1968
1969 /* Used to ensure that newly created overrides have all of their 'linked id' pointers remapped to
1970 * the matching override if it exists. Necessary because in partial resync case, some existing
1971 * liboverride may be used by the resynced ones, yet they would not be part of the resynced
1972 * partial hierarchy, so #BKE_lib_override_library_create_from_tag cannot find them and handle
1973 * their remapping. */
1974 id::IDRemapper remapper_overrides_reference_to_old;
1975
1976 /* Add remapping from old to new overrides. */
1977 for (auto [id_reference, id_override_new] : references_and_new_overrides) {
1978 new_overrides.append(id_override_new);
1979 ID *id_override_old = static_cast<ID *>(
1980 BLI_ghash_lookup(linkedref_to_old_override, id_reference));
1981 if (id_override_old == nullptr) {
1982 continue;
1983 }
1984 remapper_overrides_old_to_new.add(id_override_old, id_override_new);
1985 }
1986
1987 GHashIterator linkedref_to_old_override_iter;
1988 GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) {
1989 /* Remap no-main override IDs we just created too. */
1990 ID *id_override_old_iter = static_cast<ID *>(
1991 BLI_ghashIterator_getValue(&linkedref_to_old_override_iter));
1992 if ((id_override_old_iter->tag & ID_TAG_NO_MAIN) != 0) {
1993 nomain_ids.append(id_override_old_iter);
1994 }
1995 /* And remap linked data to old (existing, unchanged) overrides, when no new one was created.
1996 */
1997 ID *id_reference_iter = static_cast<ID *>(
1998 BLI_ghashIterator_getKey(&linkedref_to_old_override_iter));
1999 BLI_assert(id_reference_iter->lib == id_root_reference->lib);
2000 UNUSED_VARS_NDEBUG(id_root_reference);
2001 if (!id_reference_iter->newid) {
2002 remapper_overrides_reference_to_old.add(id_reference_iter, id_override_old_iter);
2003 }
2004 }
2005
2006 /* Remap all IDs to use the new override. */
2007 BKE_libblock_remap_multiple(bmain, remapper_overrides_old_to_new, 0);
2009 nomain_ids,
2011 remapper_overrides_old_to_new,
2013 /* In new overrides, remap linked ID to their matching already existing overrides. */
2015 new_overrides,
2017 remapper_overrides_reference_to_old,
2019}
2020
2041using LibOverrideMissingIDsData_Key = const std::pair<std::string, Library *>;
2042using LibOverrideMissingIDsData_Value = std::deque<ID *>;
2044 std::map<LibOverrideMissingIDsData_Key, LibOverrideMissingIDsData_Value>;
2045
2046/* Return a key suitable for the missing IDs mapping, i.e. a pair of
2047 * `<full ID name (including first two ID type chars) without a potential numeric extension,
2048 * ID library>`.
2049 *
2050 * So e.g. returns `<"OBMyObject", lib>` for ID from `lib` with names like `"OBMyObject"`,
2051 * `"OBMyObject.002"`, `"OBMyObject.12345"`, and so on, but _not_ for e.g. `"OBMyObject.12.002"`.
2052 */
2054{
2055 std::string id_name_key(id->name);
2056 const size_t last_key_index = id_name_key.find_last_not_of("0123456789");
2057
2058 BLI_assert(last_key_index != std::string::npos);
2059
2060 if (id_name_key[last_key_index] == '.') {
2061 id_name_key.resize(last_key_index);
2062 }
2063
2064 return LibOverrideMissingIDsData_Key(id_name_key, id->lib);
2065}
2066
2068{
2069 LibOverrideMissingIDsData missing_ids;
2070 ID *id_iter;
2071 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2072 if (!ID_IS_LINKED(id_iter)) {
2073 continue;
2074 }
2075 const int required_tags = (ID_TAG_MISSING | ID_TAG_LIBOVERRIDE_NEED_RESYNC);
2076 if ((id_iter->tag & required_tags) != required_tags) {
2077 continue;
2078 }
2079
2081 std::pair<LibOverrideMissingIDsData::iterator, bool> value = missing_ids.try_emplace(
2083 value.first->second.push_back(id_iter);
2084 }
2086
2087 return missing_ids;
2088}
2089
2091 LibOverrideMissingIDsData &missing_ids, ID *id_override)
2092{
2094 const LibOverrideMissingIDsData::iterator value = missing_ids.find(key);
2095 if (value == missing_ids.end()) {
2096 return nullptr;
2097 }
2098 if (value->second.empty()) {
2099 return nullptr;
2100 }
2101 ID *match_id = value->second.front();
2102 value->second.pop_front();
2103 return match_id;
2104}
2105
2107 Scene *scene,
2108 ViewLayer *view_layer,
2109 ID *id_root,
2110 LinkNode *id_resync_roots,
2111 ListBase *no_main_ids_list,
2112 Collection *override_resync_residual_storage,
2113 const bool do_hierarchy_enforce,
2114 const bool do_post_process,
2115 BlendFileReadReport *reports)
2116{
2118
2119 ID *id_root_reference = id_root->override_library->reference;
2120 ID *id;
2121
2122 const Object *old_active_object = nullptr;
2123 if (view_layer) {
2124 BKE_view_layer_synced_ensure(scene, view_layer);
2125 old_active_object = BKE_view_layer_active_object_get(view_layer);
2126 }
2127 else {
2129 }
2130
2131 if (id_root_reference->tag & ID_TAG_MISSING) {
2132 BKE_reportf(reports != nullptr ? reports->reports : nullptr,
2133 RPT_ERROR,
2134 "Impossible to resync data-block %s and its dependencies, as its linked reference "
2135 "is missing",
2136 id_root->name + 2);
2137 return false;
2138 }
2139
2140 BKE_main_relations_create(bmain, 0);
2142 data.bmain = bmain;
2143 data.scene = scene;
2144 data.tag = ID_TAG_DOIT;
2145 data.missing_tag = ID_TAG_MISSING;
2146 data.is_override = true;
2147 data.is_resync = true;
2148
2149 data.root_set(id_root);
2150 data.hierarchy_root_set(id_root->override_library->hierarchy_root);
2151
2153
2154 /* Mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, populated from
2155 * each sub-tree that actually needs to be resynced. */
2156 GHash *linkedref_to_old_override = BLI_ghash_new(
2158
2159 /* Only tag linked IDs from related linked reference hierarchy that are actually part of
2160 * the sub-trees of each detected sub-roots needing resync. */
2161 for (LinkNode *resync_root_link = id_resync_roots; resync_root_link != nullptr;
2162 resync_root_link = resync_root_link->next)
2163 {
2164 ID *id_resync_root = static_cast<ID *>(resync_root_link->link);
2165 BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_resync_root));
2166
2167 if ((id_resync_root->tag & ID_TAG_NO_MAIN) != 0) {
2169 "While dealing with root '%s', resync root ID '%s' (%p) found to be alreaady "
2170 "resynced.\n",
2171 id_root->name,
2172 id_resync_root->name,
2173 id_resync_root);
2174 }
2175 // if (no_main_ids_list && BLI_findindex(no_main_ids_list, id_resync_root) != -1) {
2176 // CLOG_ERROR(
2177 // &LOG,
2178 // "While dealing with root '%s', resync root ID '%s' found to be alreaady
2179 // resynced.\n", id_root->name, id_resync_root->name);
2180 // }
2181
2182 ID *id_resync_root_reference = id_resync_root->override_library->reference;
2183
2184 if (id_resync_root_reference->tag & ID_TAG_MISSING) {
2186 reports != nullptr ? reports->reports : nullptr,
2187 RPT_ERROR,
2188 "Impossible to resync data-block %s and its dependencies, as its linked reference "
2189 "is missing",
2190 id_root->name + 2);
2191 BLI_ghash_free(linkedref_to_old_override, nullptr, nullptr);
2193 data.clear();
2194 return false;
2195 }
2196
2197 /* Tag local overrides of the current resync sub-hierarchy. */
2199 data.is_override = true;
2200 data.root_set(id_resync_root);
2202
2203 /* Tag reference data matching the current resync sub-hierarchy. */
2205 data.is_override = false;
2206 data.root_set(id_resync_root->override_library->reference);
2207 data.hierarchy_root_set(
2210
2213
2214 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2215 if ((id->lib != id_root->lib) || !ID_IS_OVERRIDE_LIBRARY(id)) {
2216 continue;
2217 }
2218
2219 /* IDs that get fully removed from linked data remain as local overrides (using place-holder
2220 * linked IDs as reference), but they are often not reachable from any current valid local
2221 * override hierarchy anymore. This will ensure they get properly deleted at the end of this
2222 * function. */
2223 if (!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
2224 (id->override_library->reference->tag & ID_TAG_MISSING) != 0 &&
2225 /* Unfortunately deleting obdata means deleting their objects too. Since there is no
2226 * guarantee that a valid override object using an obsolete override obdata gets properly
2227 * updated, we ignore those here for now. In practice this should not be a big issue. */
2228 !OB_DATA_SUPPORT_ID(GS(id->name)))
2229 {
2230 id->tag |= ID_TAG_MISSING;
2231 }
2232
2233 /* While this should not happen in typical cases (and won't be properly supported here),
2234 * user is free to do all kind of very bad things, including having different local
2235 * overrides of a same linked ID in a same hierarchy. */
2236 IDOverrideLibrary *id_override_library = BKE_lib_override_library_get(
2237 bmain, id, nullptr, nullptr);
2238
2239 if (id_override_library->hierarchy_root != id_root->override_library->hierarchy_root) {
2240 continue;
2241 }
2242
2243 ID *reference_id = id_override_library->reference;
2244 if (GS(reference_id->name) != GS(id->name)) {
2245 switch (GS(id->name)) {
2246 case ID_KE:
2247 reference_id = reinterpret_cast<ID *>(BKE_key_from_id(reference_id));
2248 break;
2249 case ID_GR:
2250 BLI_assert(GS(reference_id->name) == ID_SCE);
2251 reference_id = reinterpret_cast<ID *>(
2252 reinterpret_cast<Scene *>(reference_id)->master_collection);
2253 break;
2254 case ID_NT:
2255 reference_id = reinterpret_cast<ID *>(blender::bke::node_tree_from_id(id));
2256 break;
2257 default:
2258 break;
2259 }
2260 }
2261 if (reference_id == nullptr) {
2262 /* Can happen e.g. when there is a local override of a shape-key, but the matching linked
2263 * obdata (mesh etc.) does not have any shape-key anymore. */
2264 continue;
2265 }
2266 BLI_assert(GS(reference_id->name) == GS(id->name));
2267
2268 if (!BLI_ghash_haskey(linkedref_to_old_override, reference_id)) {
2269 BLI_ghash_insert(linkedref_to_old_override, reference_id, id);
2270 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || (id->tag & ID_TAG_DOIT) == 0) {
2271 continue;
2272 }
2273 if ((id->override_library->reference->tag & ID_TAG_DOIT) == 0) {
2274 /* We have an override, but now it does not seem to be necessary to override that ID
2275 * anymore. Check if there are some actual overrides from the user, otherwise assume
2276 * that we can get rid of this local override. */
2278 id->override_library->reference->tag |= ID_TAG_DOIT;
2279 }
2280 }
2281 }
2282 }
2284
2285 /* Code above may have added some tags, we need to update this too. */
2288 }
2289
2290 /* Tag all local overrides of the current hierarchy. */
2292 data.is_override = true;
2293 data.root_set(id_root);
2294 data.hierarchy_root_set(id_root->override_library->hierarchy_root);
2296
2298 data.clear();
2299
2300 /* Make new override from linked data. */
2301 /* Note that this call also remaps all pointers of tagged IDs from old override IDs to new
2302 * override IDs (including within the old overrides themselves, since those are tagged too
2303 * above). */
2304 const bool success = BKE_lib_override_library_create_from_tag(
2305 bmain,
2306 nullptr,
2307 id_root_reference,
2309 nullptr,
2310 true,
2311 false);
2312
2313 if (!success) {
2314 BLI_ghash_free(linkedref_to_old_override, nullptr, nullptr);
2315 return success;
2316 }
2317
2318 /* Get a mapping of all missing linked IDs that were liboverrides, to search for 'old
2319 * liboverrides' for newly created ones that do not already have one, in next step. */
2321 bmain);
2322 /* Vector of pairs of reference IDs, and their new override IDs. */
2323 blender::Vector<std::pair<ID *, ID *>> references_and_new_overrides;
2324
2325 ListBase *lb;
2326 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
2327 ID *id_reference_iter;
2328 FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_reference_iter) {
2329 if ((id_reference_iter->tag & ID_TAG_DOIT) == 0 || id_reference_iter->newid == nullptr ||
2330 id_reference_iter->lib != id_root_reference->lib)
2331 {
2332 continue;
2333 }
2334 ID *id_override_new = id_reference_iter->newid;
2335 references_and_new_overrides.append(std::make_pair(id_reference_iter, id_override_new));
2336
2337 ID *id_override_old = static_cast<ID *>(
2338 BLI_ghash_lookup(linkedref_to_old_override, id_reference_iter));
2339
2340 BLI_assert((id_override_new->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0);
2341
2342 /* We need to 'move back' newly created override into its proper library (since it was
2343 * duplicated from the reference ID with 'no main' option, it should currently be the same
2344 * as the reference ID one). */
2345 BLI_assert( id_override_new->lib ==
2346 id_reference_iter->lib);
2347 BLI_assert(id_override_old == nullptr || id_override_old->lib == id_root->lib);
2348 id_override_new->lib = id_root->lib;
2349
2350 /* The old override may have been created as linked data and then referenced by local data
2351 * during a previous Blender session, in which case it became directly linked and a reference
2352 * to it was stored in the local .blend file. however, since that linked liboverride ID does
2353 * not actually exist in the original library file, on next file read it is lost and marked
2354 * as missing ID. */
2355 if (id_override_old == nullptr && ID_IS_LINKED(id_override_new)) {
2356 id_override_old = lib_override_library_resync_search_missing_ids_data(missing_ids_data,
2357 id_override_new);
2358 BLI_assert(id_override_old == nullptr || id_override_old->lib == id_override_new->lib);
2359 if (id_override_old != nullptr) {
2360 BLI_ghash_insert(linkedref_to_old_override, id_reference_iter, id_override_old);
2362 2,
2363 "Found missing linked old override best-match %s for new linked override %s",
2364 id_override_old->name,
2365 id_override_new->name);
2366 }
2367 }
2368
2369 /* Remap step below will tag directly linked ones properly as needed. */
2370 if (ID_IS_LINKED(id_override_new)) {
2371 id_override_new->tag |= ID_TAG_INDIRECT;
2372 }
2373
2374 if (id_override_old != nullptr) {
2375 /* Swap the names between old override ID and new one. */
2376 char id_name_buf[MAX_ID_NAME];
2377 memcpy(id_name_buf, id_override_old->name, sizeof(id_name_buf));
2378 memcpy(id_override_old->name, id_override_new->name, sizeof(id_override_old->name));
2379 memcpy(id_override_new->name, id_name_buf, sizeof(id_override_new->name));
2380
2381 BLI_insertlinkreplace(lb, id_override_old, id_override_new);
2382 id_override_old->tag |= ID_TAG_NO_MAIN;
2383 id_override_new->tag &= ~ID_TAG_NO_MAIN;
2384
2385 lib_override_object_posemode_transfer(id_override_new, id_override_old);
2386
2387 /* Missing old liboverrides cannot transfer their override rules to new liboverride.
2388 * This is fine though, since these are expected to only be 'virtual' linked overrides
2389 * generated by resync of linked overrides. So nothing is expected to be overridden here.
2390 */
2391 if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new) &&
2392 (id_override_old->tag & ID_TAG_MISSING) == 0)
2393 {
2394 BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old));
2395
2396 id_override_new->override_library->flag = id_override_old->override_library->flag;
2397
2398 /* NOTE: Since `runtime.tag` is not copied from old to new liboverride, the potential
2399 * `LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT` is kept on the old, to-be-freed
2400 * liboverride, and the new one is assumed to be properly part of its hierarchy again. */
2401
2402 /* Copy over overrides rules from old override ID to new one. */
2404 &id_override_old->override_library->properties);
2406 id_override_new->override_library->properties.first);
2408 id_override_old->override_library->properties.first);
2409 for (; op_new; op_new = op_new->next, op_old = op_old->next) {
2410 lib_override_library_property_copy(op_new, op_old);
2411 }
2412 }
2413
2414 BLI_addtail(no_main_ids_list, id_override_old);
2415 }
2416 else {
2417 /* Add to proper main list, ensure unique name for local ID, sort, and clear relevant
2418 * tags. */
2419 BKE_libblock_management_main_add(bmain, id_override_new);
2420 }
2421 }
2423 }
2425
2426 /* We remap old to new override usages in a separate step, after all new overrides have
2427 * been added to Main.
2428 *
2429 * This function also ensures that newly created overrides get all their linked ID pointers
2430 * remapped to a valid override one, whether new or already existing. In partial resync case,
2431 * #BKE_lib_override_library_create_from_tag cannot reliably discover _all_ valid existing
2432 * overrides used by the newly resynced ones, since the local resynced hierarchy may not contain
2433 * them. */
2435 bmain, id_root_reference, references_and_new_overrides, linkedref_to_old_override);
2436
2438
2439 blender::Vector<ID *> id_override_old_vector;
2440
2441 /* We need to apply override rules in a separate loop, after all ID pointers have been properly
2442 * remapped, and all new local override IDs have gotten their proper original names, otherwise
2443 * override operations based on those ID names would fail. */
2444 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2445 if ((id->tag & ID_TAG_DOIT) == 0 || id->newid == nullptr || id->lib != id_root_reference->lib)
2446 {
2447 continue;
2448 }
2449
2450 ID *id_override_new = id->newid;
2451 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) {
2452 continue;
2453 }
2454
2455 ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id));
2456 if (id_override_old == nullptr) {
2457 continue;
2458 }
2459
2460 if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old)) {
2461 /* The remapping from old to new liboverrides above has a sad side effect on ShapeKeys. Since
2462 * old liboverrides are also remapped, it means that the old liboverride owner of the shape
2463 * key is also now pointing to the new liboverride shape key, not the old one. Since shape
2464 * keys do not own their liboverride data, the old liboverride shape key user has to be
2465 * restored to use the old liboverride shape-key, otherwise applying shape key override
2466 * operations will be useless (would apply using the new, from linked data, liboverride,
2467 * being effectively a no-op). */
2468 Key **key_override_old_p = BKE_key_from_id_p(id_override_old);
2469 if (key_override_old_p != nullptr && *key_override_old_p != nullptr) {
2470 Key *key_linked_reference = BKE_key_from_id(id_override_new->override_library->reference);
2471 BLI_assert(key_linked_reference != nullptr);
2472 BLI_assert(key_linked_reference->id.newid == &(*key_override_old_p)->id);
2473
2474 Key *key_override_old = static_cast<Key *>(
2475 BLI_ghash_lookup(linkedref_to_old_override, &key_linked_reference->id));
2476 BLI_assert(key_override_old != nullptr);
2477 *key_override_old_p = key_override_old;
2478 }
2479
2480 /* Apply rules on new override ID using old one as 'source' data. */
2481 /* Note that since we already remapped ID pointers in old override IDs to new ones, we
2482 * can also apply ID pointer override rules safely here. */
2483 PointerRNA rnaptr_src = RNA_id_pointer_create(id_override_old);
2484 PointerRNA rnaptr_dst = RNA_id_pointer_create(id_override_new);
2485
2486 /* In case the parent of the liboverride object matches hierarchy-wise the parent of its
2487 * linked reference, also enforce clearing any override of the other related parenting
2488 * settings.
2489 *
2490 * While this may break some rare use-cases, in almost all situations the best behavior here
2491 * is to follow the values from the reference data (especially when it comes to the invert
2492 * parent matrix). */
2493 bool do_clear_parenting_override = false;
2494 if (GS(id_override_new->name) == ID_OB) {
2495 Object *ob_old = reinterpret_cast<Object *>(id_override_old);
2496 Object *ob_new = reinterpret_cast<Object *>(id_override_new);
2497 if (ob_new->parent && ob_new->parent != ob_old->parent &&
2498 /* Parent is not a liboverride. */
2499 (ob_new->parent ==
2500 reinterpret_cast<Object *>(ob_new->id.override_library->reference)->parent ||
2501 /* Parent is a hierarchy-matching liboverride. */
2503 reinterpret_cast<Object *>(ob_new->parent->id.override_library->reference) ==
2504 reinterpret_cast<Object *>(ob_new->id.override_library->reference)->parent)))
2505 {
2506 do_clear_parenting_override = true;
2507 }
2508 }
2509
2510 /* We remove any operation tagged with `LIBOVERRIDE_OP_FLAG_IDPOINTER_MATCH_REFERENCE`,
2511 * that way the potentially new pointer will be properly kept, when old one is still valid
2512 * too (typical case: assigning new ID to some usage, while old one remains used elsewhere
2513 * in the override hierarchy). */
2515 IDOverrideLibraryProperty *, op, &id_override_new->override_library->properties)
2516 {
2520 BLI_freelinkN(&op->operations, opop);
2521 }
2522 }
2523 if (BLI_listbase_is_empty(&op->operations)) {
2525 }
2526 else if (do_clear_parenting_override) {
2527 if (strstr(op->rna_path, "matrix_parent_inverse") ||
2528 strstr(op->rna_path, "parent_type") || strstr(op->rna_path, "parent_bone") ||
2529 strstr(op->rna_path, "parent_vertices"))
2530 {
2532 2,
2533 "Deleting liboverride property '%s' from object %s, as its parent pointer "
2534 "matches the reference data hierarchy wise",
2535 id_override_new->name + 2,
2536 op->rna_path);
2538 }
2539 }
2540 }
2541
2543 &rnaptr_dst,
2544 &rnaptr_src,
2545 nullptr,
2546 id_override_new->override_library,
2547 do_hierarchy_enforce ? RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS :
2549
2550 /* Clear the old shape key pointer again, otherwise it won't make ID management code happy
2551 * when freeing (at least from user count side of things). */
2552 if (key_override_old_p != nullptr) {
2553 *key_override_old_p = nullptr;
2554 }
2555 }
2556
2557 id_override_old_vector.append(id_override_old);
2558 }
2560
2561 /* Once overrides have been properly 'transferred' from old to new ID, we can clear ID usages
2562 * of the old one.
2563 * This is necessary in case said old ID is not in Main anymore. */
2564 id::IDRemapper id_remapper;
2566 id_override_old_vector,
2568 id_remapper,
2570 for (ID *id_override_old : id_override_old_vector) {
2571 id_override_old->tag |= ID_TAG_NO_USER_REFCOUNT;
2572 }
2573 id_override_old_vector.clear();
2574
2575 /* Delete old override IDs.
2576 * Note that we have to use tagged group deletion here, since ID deletion also uses
2577 * ID_TAG_DOIT. This improves performances anyway, so everything is fine. */
2578 int user_edited_overrides_deletion_count = 0;
2579 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2580 if (id->tag & ID_TAG_DOIT) {
2581 /* Since this code can also be called on linked liboverride now (during recursive resync),
2582 * order of processing cannot guarantee anymore that the old liboverride won't be tagged for
2583 * deletion before being processed by this loop (which would then untag it again).
2584 *
2585 * So instead store old liboverrides in Main into a temp list again, and do the tagging
2586 * separately once this loop over all IDs in main is done. */
2587 if (id->newid != nullptr && id->lib == id_root_reference->lib) {
2588 ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id));
2589
2590 if (id_override_old != nullptr) {
2591 id->newid->tag &= ~ID_TAG_DOIT;
2592 if (id_override_old->tag & ID_TAG_NO_MAIN) {
2593 id_override_old->tag |= ID_TAG_DOIT;
2594 BLI_assert(BLI_findindex(no_main_ids_list, id_override_old) != -1);
2595 }
2596 else {
2597 /* Defer tagging. */
2598 id_override_old_vector.append(id_override_old);
2599 }
2600 }
2601 }
2602 id->tag &= ~ID_TAG_DOIT;
2603 }
2604 /* Also deal with old overrides that went missing in new linked data - only for real local
2605 * overrides for now, not those who are linked. */
2606 else if (id->tag & ID_TAG_MISSING && !ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
2607 bool do_delete;
2608 ID *hierarchy_root = id->override_library->hierarchy_root;
2609 if (id->override_library->reference->lib->id.tag & ID_TAG_MISSING) {
2610 /* Do not delete overrides which reference is missing because the library itself is missing
2611 * (ref. #100586). */
2612 do_delete = false;
2613 }
2614 else if (hierarchy_root != nullptr &&
2615 hierarchy_root->override_library->reference->tag & ID_TAG_MISSING)
2616 {
2617 /* Do not delete overrides which root hierarchy reference is missing. This would typically
2618 * cause more harm than good. */
2619 do_delete = false;
2620 }
2622 /* If user never edited them, we can delete them. */
2623 do_delete = true;
2624 CLOG_INFO(&LOG_RESYNC, 2, "Old override %s is being deleted", id->name);
2625 }
2626#if 0
2627 else {
2628 /* Otherwise, keep them, user needs to decide whether what to do with them. */
2629 BLI_assert((id->tag & ID_TAG_DOIT) == 0);
2630 do_delete = false;
2631 id_fake_user_set(id);
2634 2,
2635 "Old override %s is being kept around as it was user-edited",
2636 id->name);
2637 }
2638#else
2639 else {
2640 /* Delete them nevertheless, with fat warning, user needs to decide whether they want to
2641 * save that version of the file (and accept the loss), or not. */
2642 do_delete = true;
2644 "Old override %s is being deleted even though it was user-edited",
2645 id->name);
2646 user_edited_overrides_deletion_count++;
2647 }
2648#endif
2649 if (do_delete) {
2650 id->tag |= ID_TAG_DOIT;
2651 id->tag &= ~ID_TAG_MISSING;
2652 }
2653 else if (id->override_library->runtime != nullptr) {
2654 /* Cleanup of this temporary tag, since that somewhat broken liboverride is explicitly
2655 * kept for now. */
2656 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
2657 }
2658 }
2659 }
2661
2662 /* Finalize tagging old liboverrides for deletion. */
2663 for (ID *id_override_old : id_override_old_vector) {
2664 id_override_old->tag |= ID_TAG_DOIT;
2665 }
2666 id_override_old_vector.clear();
2667
2668 /* Cleanup, many pointers in this GHash are already invalid now. */
2669 BLI_ghash_free(linkedref_to_old_override, nullptr, nullptr);
2670
2672
2673 /* At this point, `id_root` may have been resynced, therefore deleted. In that case we need to
2674 * update it to its new version.
2675 */
2676 if (id_root_reference->newid != nullptr) {
2677 id_root = id_root_reference->newid;
2678 }
2679
2680 if (user_edited_overrides_deletion_count > 0) {
2681 BKE_reportf(reports != nullptr ? reports->reports : nullptr,
2683 "During resync of data-block %s, %d obsolete overrides were deleted, that had "
2684 "local changes defined by user",
2685 id_root->name + 2,
2686 user_edited_overrides_deletion_count);
2687 }
2688
2689 if (do_post_process) {
2690 /* Essentially ensures that potentially new overrides of new objects will be instantiated. */
2691 /* NOTE: Here 'reference' collection and 'newly added' collection are the same, which is fine
2692 * since we already relinked old root override collection to new resync'ed one above. So this
2693 * call is not expected to instantiate this new resync'ed collection anywhere, just to ensure
2694 * that we do not have any stray objects. */
2696 scene,
2697 view_layer,
2698 nullptr,
2699 id_root_reference,
2700 id_root,
2701 override_resync_residual_storage,
2702 old_active_object,
2703 true);
2704 }
2705
2706 /* Cleanup. */
2708 /* That one should not be needed in fact, as #BKE_id_multi_tagged_delete call above should have
2709 * deleted all tagged IDs. */
2710 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2711
2712 return success;
2713}
2714
2717{
2719 parameters.do_local_ids = true;
2720 parameters.do_linked_ids = true;
2721 parameters.do_recursive = true;
2722 parameters.filter_fn = [](const ID *id) -> bool {
2723 if (ID_IS_LINKED(id) && (id->tag & ID_TAG_MISSING) != 0) {
2724 return true;
2725 }
2726 /* This is a fairly complex case.
2727 *
2728 * LibOverride resync process takes care of removing 'no more valid' liboverrides (see at the
2729 * end of #lib_override_library_main_resync_on_library_indirect_level). However, since it does
2730 * not resync data which linked reference is missing (see
2731 * #lib_override_library_main_resync_id_skip_check), these are kept 'as is'. Indeed,
2732 * liboverride resync code cannot know if a specific liboverride data is only part of its
2733 * hierarchy, or if it is also used by some other data (in which case it should be preserved if
2734 * the linked reference goes missing).
2735 *
2736 * So instead, we consider these cases as also valid candidates for deletion here, since the
2737 * whole recursive process in `BKE_lib_query_unused_ids_tag` will ensure that if there is still
2738 * any valid user of these, they won't get tagged for deletion.
2739 *
2740 * Also, do not delete 'orphaned' liboverrides if it's a hierarchy root, or if its hierarchy
2741 * root's reference is missing, since this is much more likely a case of actual missing data,
2742 * rather than changes in the liboverride's hierarchy in the linked data.
2743 */
2744 if (ID_IS_OVERRIDE_LIBRARY(id)) {
2745 const IDOverrideLibrary *override_library = BKE_lib_override_library_get(
2746 nullptr, id, nullptr, nullptr);
2747 const ID *root = override_library->hierarchy_root;
2748 if (root == id || (root->override_library->reference->tag & ID_TAG_MISSING) != 0) {
2749 return false;
2750 }
2751 return ((override_library->reference->tag & ID_TAG_MISSING) != 0);
2752 }
2753 return false;
2754 };
2757 2,
2758 "Deleting %d unused linked missing IDs and their unused liboverrides (including %d "
2759 "local ones)\n",
2760 parameters.num_total[INDEX_ID_NULL],
2761 parameters.num_local[INDEX_ID_NULL]);
2763}
2764
2766 Scene *scene,
2767 ViewLayer *view_layer,
2768 ID *id_root,
2769 Collection *override_resync_residual_storage,
2770 const bool do_hierarchy_enforce,
2771 BlendFileReadReport *reports)
2772{
2773 ListBase no_main_ids_list = {nullptr};
2774 LinkNode id_resync_roots{};
2775 id_resync_roots.link = id_root;
2776 id_resync_roots.next = nullptr;
2777
2778 const bool success = lib_override_library_resync(bmain,
2779 scene,
2780 view_layer,
2781 id_root,
2782 &id_resync_roots,
2783 &no_main_ids_list,
2784 override_resync_residual_storage,
2785 do_hierarchy_enforce,
2786 true,
2787 reports);
2788
2789 LISTBASE_FOREACH_MUTABLE (ID *, id_iter, &no_main_ids_list) {
2790 BKE_id_free(bmain, id_iter);
2791 }
2792
2793 /* Cleanup global namemap, to avoid extra processing with regular ID name management. Better to
2794 * re-create the global namemap on demand. */
2796
2798
2799 return success;
2800}
2801
2803 const int library_indirect_level,
2804 const bool do_strict_equal)
2805{
2806 const int id_lib_level = (ID_IS_LINKED(id) ? id->lib->runtime.temp_index : 0);
2807 return do_strict_equal ? id_lib_level == library_indirect_level :
2808 id_lib_level <= library_indirect_level;
2809}
2810
2811/* Check ancestors overrides for resync, to ensure all IDs in-between two tagged-for-resync ones
2812 * are also properly tagged.
2813 *
2814 * WARNING: Expects `bmain` to have valid relation data.
2815 *
2816 * Returns `true` if it finds an ancestor within the current liboverride hierarchy also tagged as
2817 * needing resync, `false` otherwise.
2818 *
2819 * NOTE: If `check_only` is true, it only does the check and returns, without any modification to
2820 * the data.
2821 */
2823 ID *id_root,
2824 ID *id_from,
2825 const int library_indirect_level,
2826 bool is_in_partial_resync_hierarchy)
2827{
2829 BLI_assert(id_root->override_library->hierarchy_root != nullptr);
2830
2831 if (!lib_override_resync_id_lib_level_is_valid(id_root, library_indirect_level, false)) {
2832 CLOG_ERROR(
2833 &LOG,
2834 "While processing indirect level %d, ID %s from lib %s of indirect level %d detected "
2835 "as needing resync, skipping",
2836 library_indirect_level,
2837 id_root->name,
2838 id_root->lib ? id_root->lib->filepath : "<LOCAL>",
2839 id_root->lib ? id_root->lib->runtime.temp_index : 0);
2840 id_root->tag &= ~ID_TAG_LIBOVERRIDE_NEED_RESYNC;
2841 return;
2842 }
2843
2844 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
2846 BLI_assert(entry != nullptr);
2847
2848 bool is_reprocessing_current_entry = false;
2850 /* This ID is already being processed, this indicates a dependency loop. */
2852
2853 if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
2854 /* This ID is already tagged for resync, then the loop leading back to it is also fully
2855 * tagged for resync, nothing else to do. */
2856 BLI_assert(is_in_partial_resync_hierarchy);
2857 return;
2858 }
2859 if (!is_in_partial_resync_hierarchy) {
2860 /* This ID is not tagged for resync, and is part of a loop where none of the other IDs are
2861 * tagged for resync, nothing else to do. */
2862 return;
2863 }
2864 /* This ID is not yet tagged for resync, but is part of a loop which is (partially) tagged
2865 * for resync.
2866 * The whole loop needs to be processed a second time to ensure all of its members are properly
2867 * tagged for resync then. */
2868 is_reprocessing_current_entry = true;
2869
2870 CLOG_INFO(&LOG,
2871 4,
2872 "ID %s (%p) is detected as part of a hierarchy dependency loop requiring resync, it "
2873 "is now being re-processed to ensure proper tagging of the whole loop",
2874 id_root->name,
2875 id_root->lib);
2876 }
2877 else if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
2878 /* This ID has already been processed. */
2880
2881 /* If it was already detected as needing resync, then its whole sub-tree should also be fully
2882 * processed. Only need to ensure that it is not tagged as potential partial resync root
2883 * anymore, if now processed as part of another partial resync hierarchy. */
2884 if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
2885 if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_DOIT && is_in_partial_resync_hierarchy) {
2886 CLOG_INFO(
2887 &LOG,
2888 4,
2889 "ID %s (%p) was marked as a potential root for partial resync, but it is used by "
2890 "%s (%p), which is also tagged for resync, so it is not a root after all",
2891 id_root->name,
2892 id_root->lib,
2893 id_from->name,
2894 id_from->lib);
2895
2896 entry->tags &= ~MAINIDRELATIONS_ENTRY_TAGS_DOIT;
2897 }
2898 return;
2899 }
2900 /* Else, if it is not being processed as part of a resync hierarchy, nothing more to do either,
2901 * its current status and the one of its whole dependency tree is also assumed valid. */
2902 if (!is_in_partial_resync_hierarchy) {
2903 return;
2904 }
2905
2906 /* Else, this ID was processed before and not detected as needing resync, but it now needs
2907 * resync, so its whole sub-tree needs to be re-processed to be properly tagged as needing
2908 * resync. */
2909 entry->tags &= ~MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
2910 }
2911
2912 if (is_in_partial_resync_hierarchy) {
2913 BLI_assert(id_from != nullptr);
2914
2915 if ((id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0) {
2916 CLOG_INFO(&LOG,
2917 4,
2918 "ID %s (%p) now tagged as needing resync because they are used by %s (%p) "
2919 "that needs to be resynced",
2920 id_root->name,
2921 id_root->lib,
2922 id_from->name,
2923 id_from->lib);
2925 }
2926 }
2927 else if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
2928 /* Not yet within a partial resync hierarchy, and this ID is tagged for resync, it is a
2929 * potential partial resync root. */
2930 is_in_partial_resync_hierarchy = true;
2931 }
2932
2933 /* Temporary tag to help manage dependency loops. */
2934 if (!is_reprocessing_current_entry) {
2937
2938 /* Since this ID is reached from the hierarchy root, it is not isolated from it. */
2939 if (id_root->override_library->hierarchy_root != id_root &&
2940 id_root->override_library->runtime != nullptr)
2941 {
2942 id_root->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
2943 }
2944 }
2945
2946 /* Check the whole sub-tree hierarchy of this ID. */
2947 for (MainIDRelationsEntryItem *entry_item = entry->to_ids; entry_item != nullptr;
2948 entry_item = entry_item->next)
2949 {
2951 continue;
2952 }
2953 ID *id_to = *(entry_item->id_pointer.to);
2954 /* Ensure the 'real' override is processed, in case `id_to` is e.g. an embedded ID, get its
2955 * owner instead. */
2956 BKE_lib_override_library_get(bmain, id_to, nullptr, &id_to);
2957
2958 if (lib_override_hierarchy_dependencies_skip_check(id_root, id_to, true)) {
2959 continue;
2960 }
2962 "Check above ensured `id_to` is a liboverride, so it should be a real one (not "
2963 "an embedded one)");
2964
2965 /* Non-matching hierarchy root IDs mean this is not the same liboverride hierarchy anymore. */
2967 continue;
2968 }
2969
2971 bmain, id_to, id_root, library_indirect_level, is_in_partial_resync_hierarchy);
2972
2973 /* Call above may have changed that status in case of dependency loop, update it for the next
2974 * dependency processing. */
2975 is_in_partial_resync_hierarchy = (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) != 0;
2976 }
2977
2978 if (!is_reprocessing_current_entry) {
2981
2982 entry->tags &= ~MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS;
2984
2985 if (is_in_partial_resync_hierarchy &&
2986 (id_from == nullptr || (id_from->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0))
2987 {
2988 /* This ID (and its whole sub-tree of dependencies) is now considered as processed. If it is
2989 * tagged for resync, but its 'calling parent' is not, it is a potential partial resync root.
2990 */
2992 4,
2993 "Potential root for partial resync: %s (%p)",
2994 id_root->name,
2995 id_root->lib);
2997 }
2998 }
2999}
3000
3001/* Return true if the ID should be skipped for resync given current context. */
3003 const int library_indirect_level)
3004{
3005 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
3006 return true;
3007 }
3008
3009 if (!lib_override_resync_id_lib_level_is_valid(id, library_indirect_level, true)) {
3010 return true;
3011 }
3012
3013 /* Do not attempt to resync from missing data. */
3014 if (((id->tag | id->override_library->reference->tag) & ID_TAG_MISSING) != 0) {
3015 return true;
3016 }
3017
3018 if (id->override_library->flag & LIBOVERRIDE_FLAG_NO_HIERARCHY) {
3019 /* This ID is not part of an override hierarchy. */
3021 return true;
3022 }
3023
3024 /* Do not attempt to resync when hierarchy root is missing, this would usually do more harm
3025 * than good. */
3026 ID *hierarchy_root = id->override_library->hierarchy_root;
3027 if (hierarchy_root == nullptr ||
3028 ((hierarchy_root->tag | hierarchy_root->override_library->reference->tag) &
3029 ID_TAG_MISSING) != 0)
3030 {
3031 return true;
3032 }
3033
3034 return false;
3035}
3036
3049 Main *bmain, ID *id, const int library_indirect_level)
3050{
3051 BLI_assert(!lib_override_library_main_resync_id_skip_check(id, library_indirect_level));
3052
3053 if (id->override_library->hierarchy_root == id ||
3054 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT) == 0)
3055 {
3056 BLI_assert(
3057 id->override_library->hierarchy_root != id || id->override_library->runtime == nullptr ||
3058 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT) == 0);
3059 return true;
3060 }
3061
3062 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3064 BLI_assert(entry != nullptr);
3065
3067 /* This ID has already been processed, since 'true' conditions have already been checked above,
3068 * it is validated as an isolated liboverride. */
3069 return false;
3070 }
3071 /* This way we won't process again that ID, should we encounter it again through another
3072 * relationship hierarchy. */
3074
3075 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
3076 to_id_entry = to_id_entry->next)
3077 {
3079 continue;
3080 }
3081 ID *to_id = *(to_id_entry->id_pointer.to);
3082 if (lib_override_library_main_resync_id_skip_check(to_id, library_indirect_level)) {
3083 continue;
3084 }
3085
3087 bmain, to_id, library_indirect_level))
3088 {
3089 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
3090 return true;
3091 }
3092 }
3093
3094 return false;
3095}
3096
3097/* Once all IDs needing resync have been tagged, partial ID roots can be found by processing each
3098 * tagged-for-resync IDs' ancestors within their liboverride hierarchy. */
3100 GHash *id_roots,
3101 const int library_indirect_level)
3102{
3103 ID *id_iter;
3104
3105 /* Tag all IDs to be processed, which are real liboverrides part of a hierarchy, and not the
3106 * root of their hierarchy, as potentially isolated from their hierarchy root. */
3107 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3108 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3109 continue;
3110 }
3111
3112 if (!ELEM(id_iter->override_library->hierarchy_root, id_iter, nullptr)) {
3115 }
3116 }
3118
3119 /* Finalize all IDs needing tagging for resync, and tag partial resync roots. Will also clear the
3120 * 'isolated' tag from all processed IDs. */
3121 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3122 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3123 continue;
3124 }
3125
3126 /* Only process hierarchy root IDs here. */
3127 if (id_iter->override_library->hierarchy_root != id_iter) {
3128 continue;
3129 }
3130
3132 bmain, id_iter, nullptr, library_indirect_level, false);
3133 }
3135
3136#ifndef NDEBUG
3137 /* Validation loop to ensure all entries have been processed as expected by
3138 * `lib_override_resync_tagging_finalize_recurse`, in above loop. */
3139 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3140 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3141 continue;
3142 }
3143 if ((id_iter->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0) {
3144 continue;
3145 }
3146
3147 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3149 BLI_assert(entry != nullptr);
3151
3152 if ((entry->tags & MAINIDRELATIONS_ENTRY_TAGS_DOIT) == 0) {
3153 continue;
3154 }
3155
3157 }
3159#endif
3160
3162
3163 /* Process above cleared all IDs actually still in relation with their root from the tag.
3164 *
3165 * The only exception being IDs only in relation with their root through a 'reversed' from
3166 * pointer (typical case: armature object is the hierarchy root, its child mesh object is only
3167 * related to it through its own 'parent' pointer, the armature one has no 'to' relationships to
3168 * its deformed mesh object.
3169 *
3170 * Remaining ones are in a limbo, typically they could have been removed or moved around in the
3171 * hierarchy (e.g. an object moved into another sub-collection). Tag them as needing resync,
3172 * actual resyncing code will handle them as needed. */
3173 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3174 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3175 continue;
3176 }
3177
3178 if (!ELEM(id_iter->override_library->hierarchy_root, id_iter, nullptr) &&
3180 {
3181 /* Check and clear 'isolated' tags from cases like child objects of a hierarchy root object.
3182 * Sigh. */
3184 bmain, id_iter, library_indirect_level))
3185 {
3189 4,
3190 "ID %s (%p) detected as only related to its hierarchy root by 'reversed' "
3191 "relationship(s) (e.g. object parenting), tagging it as needing "
3192 "resync",
3193 id_iter->name,
3194 id_iter->lib);
3195 }
3196 else {
3197 CLOG_INFO(
3198 &LOG_RESYNC,
3199 4,
3200 "ID %s (%p) detected as 'isolated' from its hierarchy root, tagging it as needing "
3201 "resync",
3202 id_iter->name,
3203 id_iter->lib);
3204 }
3206 }
3207 }
3209
3211
3212 /* If no tagged-for-resync ancestor was found, but the iterated ID is tagged for resync, then it
3213 * is a root of a resync sub-tree. Find the root of the whole override hierarchy and add the
3214 * iterated ID as one of its resync sub-tree roots. */
3215 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3216 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3217 continue;
3218 }
3219 if ((id_iter->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0) {
3220 continue;
3221 }
3222
3223 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3225 BLI_assert(entry != nullptr);
3226
3227 if ((entry->tags & MAINIDRELATIONS_ENTRY_TAGS_DOIT) == 0) {
3228 continue;
3229 }
3230
3231 ID *hierarchy_root = id_iter->override_library->hierarchy_root;
3232 BLI_assert(hierarchy_root->lib == id_iter->lib);
3233
3234 if (id_iter != hierarchy_root) {
3236 4,
3237 "Found root ID '%s' for partial resync root ID '%s'",
3238 hierarchy_root->name,
3239 id_iter->name);
3240
3241 BLI_assert(hierarchy_root->override_library != nullptr);
3242
3245 }
3246
3247 LinkNodePair **id_resync_roots_p;
3248 if (!BLI_ghash_ensure_p(
3249 id_roots, hierarchy_root, reinterpret_cast<void ***>(&id_resync_roots_p)))
3250 {
3251 *id_resync_roots_p = MEM_cnew<LinkNodePair>(__func__);
3252 }
3253 BLI_linklist_append(*id_resync_roots_p, id_iter);
3254 }
3256
3258 bmain,
3262 false);
3263}
3264
3265/* Ensure resync of all overrides at one level of indirect usage.
3266 *
3267 * We need to handle each level independently, since an override at level n may be affected by
3268 * other overrides from level n + 1 etc. (i.e. from linked overrides it may use).
3269 */
3271 Main *bmain,
3272 Scene *scene,
3273 ViewLayer *view_layer,
3274 Collection *override_resync_residual_storage,
3275 const int library_indirect_level,
3276 BlendFileReadReport *reports)
3277{
3278 const bool do_reports_recursive_resync_timing = (library_indirect_level != 0);
3279 const double init_time = do_reports_recursive_resync_timing ? BLI_time_now_seconds() : 0.0;
3280
3281 BKE_main_relations_create(bmain, 0);
3282 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3283
3284 /* NOTE: in code below, the order in which `FOREACH_MAIN_ID_BEGIN` processes ID types ensures
3285 * that we always process 'higher-level' overrides first (i.e. scenes, then collections, then
3286 * objects, then other types). */
3287
3288 /* Detect all linked data that would need to be overridden if we had to create an override from
3289 * those used by current existing overrides. */
3290 LibOverrideGroupTagData data = {};
3291 data.bmain = bmain;
3292 data.scene = scene;
3293 data.tag = ID_TAG_DOIT;
3294 data.missing_tag = ID_TAG_MISSING;
3295 data.is_override = false;
3296 data.is_resync = true;
3298 ID *id;
3299 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3300 if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
3301 continue;
3302 }
3303
3304 if (id->tag & (ID_TAG_DOIT | ID_TAG_MISSING)) {
3305 /* We already processed that ID as part of another ID's hierarchy. */
3306 continue;
3307 }
3308
3309 data.root_set(id->override_library->reference);
3314 }
3316 data.clear();
3317
3318 GHash *id_roots = BLI_ghash_ptr_new(__func__);
3319
3320 /* Now check existing overrides, those needing resync will be the one either already tagged as
3321 * such, or the one using linked data that is now tagged as needing override. */
3322 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3323 if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
3324 continue;
3325 }
3326
3327 if (id->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
3328 CLOG_INFO(
3329 &LOG_RESYNC, 4, "ID %s (%p) was already tagged as needing resync", id->name, id->lib);
3331 override_library_runtime_ensure(id->override_library)->tag |=
3333 }
3334 continue;
3335 }
3336
3337 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3339 BLI_assert(entry != nullptr);
3340
3341 for (MainIDRelationsEntryItem *entry_item = entry->to_ids; entry_item != nullptr;
3342 entry_item = entry_item->next)
3343 {
3345 continue;
3346 }
3347 ID *id_to = *entry_item->id_pointer.to;
3348
3349 /* Case where this ID pointer was to a linked ID, that now needs to be overridden. */
3350 if (ID_IS_LINKED(id_to) && (id_to->lib != id->lib) && (id_to->tag & ID_TAG_DOIT) != 0) {
3352 3,
3353 "ID %s (%p) now tagged as needing resync because they use linked %s (%p) that "
3354 "now needs to be overridden",
3355 id->name,
3356 id->lib,
3357 id_to->name,
3358 id_to->lib);
3360 break;
3361 }
3362 }
3363 }
3365
3366 /* Handling hierarchy relations for final tagging needs to happen after all IDs in a given
3367 * hierarchy have been tagged for resync in previous loop above. Otherwise, some resync roots may
3368 * be missing. */
3369 lib_override_resync_tagging_finalize(bmain, id_roots, library_indirect_level);
3370
3371#ifndef NDEBUG
3372 /* Check for validity/integrity of the computed set of root IDs, and their sub-branches defined
3373 * by their resync root IDs. */
3374 {
3376 GHashIterator *id_roots_iter = BLI_ghashIterator_new(id_roots);
3377 while (!BLI_ghashIterator_done(id_roots_iter)) {
3378 ID *id_root = static_cast<ID *>(BLI_ghashIterator_getKey(id_roots_iter));
3379 LinkNodePair *id_resync_roots = static_cast<LinkNodePair *>(
3380 BLI_ghashIterator_getValue(id_roots_iter));
3382 2,
3383 "Checking validity of computed TODO data for root '%s'... \n",
3384 id_root->name);
3385
3386 if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
3387 LinkNode *id_resync_root_iter = id_resync_roots->list;
3388 ID *id_resync_root = static_cast<ID *>(id_resync_root_iter->link);
3389
3390 if (id_resync_roots->list != id_resync_roots->last_node || id_resync_root != id_root) {
3392 "Hierarchy root ID is tagged for resync, yet it is not the only partial "
3393 "resync roots, this should not happen."
3394 "\n\tRoot ID: %s"
3395 "\n\tFirst Resync root ID: %s"
3396 "\n\tLast Resync root ID: %s",
3397 id_root->name,
3398 static_cast<ID *>(id_resync_roots->list->link)->name,
3399 static_cast<ID *>(id_resync_roots->last_node->link)->name);
3400 }
3401 }
3402 for (LinkNode *id_resync_root_iter = id_resync_roots->list; id_resync_root_iter != nullptr;
3403 id_resync_root_iter = id_resync_root_iter->next)
3404 {
3405 ID *id_resync_root = static_cast<ID *>(id_resync_root_iter->link);
3406 BLI_assert(id_resync_root == id_root || !BLI_ghash_haskey(id_roots, id_resync_root));
3407 if (id_resync_root == id_root) {
3408 if (id_resync_root_iter != id_resync_roots->list ||
3409 id_resync_root_iter != id_resync_roots->last_node)
3410 {
3412 "Resync root ID is same as root ID of the override hierarchy, yet other "
3413 "resync root IDs are also defined, this should not happen at this point."
3414 "\n\tRoot ID: %s"
3415 "\n\tFirst Resync root ID: %s"
3416 "\n\tLast Resync root ID: %s",
3417 id_root->name,
3418 static_cast<ID *>(id_resync_roots->list->link)->name,
3419 static_cast<ID *>(id_resync_roots->last_node->link)->name);
3420 }
3421 }
3422 }
3423 BLI_ghashIterator_step(id_roots_iter);
3424 }
3425 BLI_ghashIterator_free(id_roots_iter);
3426 }
3427#endif
3428
3430 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3431
3432 ListBase no_main_ids_list = {nullptr};
3433
3434 GHashIterator *id_roots_iter = BLI_ghashIterator_new(id_roots);
3435 while (!BLI_ghashIterator_done(id_roots_iter)) {
3436 ID *id_root = static_cast<ID *>(BLI_ghashIterator_getKey(id_roots_iter));
3437 Library *library = id_root->lib;
3438 LinkNodePair *id_resync_roots = static_cast<LinkNodePair *>(
3439 BLI_ghashIterator_getValue(id_roots_iter));
3440
3441 if (ID_IS_LINKED(id_root)) {
3443 }
3444
3446 2,
3447 "Resyncing all dependencies under root %s (%p), first one being '%s'...",
3448 id_root->name,
3449 reinterpret_cast<void *>(library),
3450 reinterpret_cast<ID *>(id_resync_roots->list->link)->name);
3451 const bool success = lib_override_library_resync(bmain,
3452 scene,
3453 view_layer,
3454 id_root,
3455 id_resync_roots->list,
3456 &no_main_ids_list,
3457 override_resync_residual_storage,
3458 false,
3459 false,
3460 reports);
3461 CLOG_INFO(&LOG_RESYNC, 2, "\tSuccess: %d", success);
3462 if (success) {
3463 reports->count.resynced_lib_overrides++;
3464 if (library_indirect_level > 0 && reports->do_resynced_lib_overrides_libraries_list &&
3466 {
3469 }
3470 }
3471
3472 BLI_linklist_free(id_resync_roots->list, nullptr);
3473 BLI_ghashIterator_step(id_roots_iter);
3474 }
3475 BLI_ghashIterator_free(id_roots_iter);
3476
3477 LISTBASE_FOREACH_MUTABLE (ID *, id_iter, &no_main_ids_list) {
3478 BKE_id_free(bmain, id_iter);
3479 }
3480 BLI_listbase_clear(&no_main_ids_list);
3481
3482 /* Just in case, should not be needed in theory, since #lib_override_library_resync should have
3483 * already cleared them all. */
3484 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3485
3486 /* Check there are no left-over IDs needing resync from the current (or higher) level of indirect
3487 * library level. */
3488 bool process_lib_level_again = false;
3489
3490 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3491 if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
3492 continue;
3493 }
3494
3495 const bool need_resync = (id->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) != 0;
3496 const bool need_reseync_original = (id->override_library->runtime != nullptr &&
3497 (id->override_library->runtime->tag &
3499 const bool is_isolated_from_root = (id->override_library->runtime != nullptr &&
3500 (id->override_library->runtime->tag &
3502
3503 if (need_resync && is_isolated_from_root) {
3505 CLOG_WARN(
3506 &LOG_RESYNC,
3507 "Deleting unused ID override %s from library level %d, still found as needing "
3508 "resync, and being isolated from its hierarchy root. This can happen when its "
3509 "otherwise unchanged linked reference was moved around in the library file (e.g. if "
3510 "an object was moved into another sub-collection of the same hierarchy).",
3511 id->name,
3512 ID_IS_LINKED(id) ? id->lib->runtime.temp_index : 0);
3513 id->tag |= ID_TAG_DOIT;
3514 }
3515 else {
3516 CLOG_WARN(
3517 &LOG_RESYNC,
3518 "Keeping user-edited ID override %s from library level %d still found as "
3519 "needing resync, and being isolated from its hierarchy root. This can happen when its "
3520 "otherwise unchanged linked reference was moved around in the library file (e.g. if "
3521 "an object was moved into another sub-collection of the same hierarchy).",
3522 id->name,
3523 ID_IS_LINKED(id) ? id->lib->runtime.temp_index : 0);
3524 id->tag &= ~ID_TAG_LIBOVERRIDE_NEED_RESYNC;
3525 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
3526 }
3527 }
3528 else if (need_resync) {
3529 if (need_reseync_original) {
3531 2,
3532 "ID override %s from library level %d still found as needing resync after "
3533 "tackling library level %d. Since it was originally tagged as such by "
3534 "RNA/liboverride apply code, this whole level of library needs to be processed "
3535 "another time.",
3536 id->name,
3537 ID_IS_LINKED(id) ? id->lib->runtime.temp_index : 0,
3538 library_indirect_level);
3539 process_lib_level_again = true;
3540 /* Cleanup tag for now, will be re-set by next iteration of this function. */
3541 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEED_RESYNC_ORIGINAL;
3542 }
3543 else {
3544 /* If it was only tagged for resync as part of resync process itself, it means it was
3545 * originally inside of a resync hierarchy, but not in the matching reference hierarchy
3546 * anymore. So it did not actually need to be resynced, simply clear the tag. */
3548 4,
3549 "ID override %s from library level %d still found as needing resync after "
3550 "tackling library level %d. However, it was not tagged as such by "
3551 "RNA/liboverride apply code, so ignoring it",
3552 id->name,
3553 ID_IS_LINKED(id) ? id->lib->runtime.temp_index : 0,
3554 library_indirect_level);
3555 id->tag &= ~ID_TAG_LIBOVERRIDE_NEED_RESYNC;
3556 }
3557 }
3558 else if (need_reseync_original) {
3559 /* Just cleanup of temporary tag, the ID has been resynced successfully. */
3560 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEED_RESYNC_ORIGINAL;
3561 }
3562 else if (is_isolated_from_root) {
3563 CLOG_ERROR(
3564 &LOG_RESYNC,
3565 "ID override %s from library level %d still tagged as isolated from its hierarchy root, "
3566 "it should have been either properly resynced or removed at that point.",
3567 id->name,
3568 ID_IS_LINKED(id) ? id->lib->runtime.temp_index : 0);
3569 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
3570 }
3571 }
3573
3574 /* Delete 'isolated from root' remaining IDs tagged in above check loop. */
3576 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3577
3578 BLI_ghash_free(id_roots, nullptr, MEM_freeN);
3579
3580 /* In some fairly rare (and degenerate) cases, some root ID from other liboverrides may have been
3581 * freed, and therefore set to nullptr. Attempt to fix this as best as possible. */
3583
3584 if (do_reports_recursive_resync_timing) {
3586 }
3587
3588 return process_lib_level_again;
3589}
3590
3592{
3593 if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
3594 return IDWALK_RET_NOP;
3595 }
3596 ID *id_owner = cb_data->owner_id;
3597 ID *id = *cb_data->id_pointer;
3598 if (id != nullptr && ID_IS_LINKED(id) && id->lib != id_owner->lib) {
3599 const int owner_library_indirect_level = ID_IS_LINKED(id_owner) ?
3600 id_owner->lib->runtime.temp_index :
3601 0;
3602 if (owner_library_indirect_level > 100) {
3604 "Levels of indirect usages of libraries is way too high, there are most likely "
3605 "dependency loops, skipping further building loops (involves at least '%s' from "
3606 "'%s' and '%s' from '%s')",
3607 id_owner->name,
3608 id_owner->lib->filepath,
3609 id->name,
3610 id->lib->filepath);
3611 return IDWALK_RET_NOP;
3612 }
3613 if (owner_library_indirect_level > 90) {
3614 CLOG_WARN(
3615 &LOG_RESYNC,
3616 "Levels of indirect usages of libraries is suspiciously too high, there are most likely "
3617 "dependency loops (involves at least '%s' from '%s' and '%s' from '%s')",
3618 id_owner->name,
3619 id_owner->lib->filepath,
3620 id->name,
3621 id->lib->filepath);
3622 }
3623
3624 if (owner_library_indirect_level >= id->lib->runtime.temp_index) {
3625 id->lib->runtime.temp_index = owner_library_indirect_level + 1;
3626 *reinterpret_cast<bool *>(cb_data->user_data) = true;
3627 }
3628 }
3629 return IDWALK_RET_NOP;
3630}
3631
3639{
3640 LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
3641 /* index 0 is reserved for local data. */
3642 library->runtime.temp_index = 1;
3643 }
3644 bool do_continue = true;
3645 while (do_continue) {
3646 do_continue = false;
3647 ID *id;
3648 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3649 /* NOTE: In theory all non-liboverride IDs could be skipped here. This does not gives any
3650 * performances boost though, so for now keep it as is (i.e. also consider non-liboverride
3651 * relationships to establish libraries hierarchy). */
3653 bmain, id, lib_override_sort_libraries_func, &do_continue, IDWALK_READONLY);
3654 }
3656 }
3657
3658 int library_indirect_level_max = 0;
3659 LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
3660 if (library->runtime.temp_index > library_indirect_level_max) {
3661 library_indirect_level_max = library->runtime.temp_index;
3662 }
3663 }
3664 return library_indirect_level_max;
3665}
3666
3668 Scene *scene,
3669 ViewLayer *view_layer,
3670 BlendFileReadReport *reports)
3671{
3672 /* We use a specific collection to gather/store all 'orphaned' override collections and objects
3673 * generated by re-sync-process. This avoids putting them in scene's master collection. */
3674#define OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME "OVERRIDE_RESYNC_LEFTOVERS"
3675 Collection *override_resync_residual_storage = static_cast<Collection *>(BLI_findstring(
3677 if (override_resync_residual_storage != nullptr &&
3678 ID_IS_LINKED(override_resync_residual_storage))
3679 {
3680 override_resync_residual_storage = nullptr;
3681 }
3682 if (override_resync_residual_storage == nullptr) {
3683 override_resync_residual_storage = BKE_collection_add(
3684 bmain, scene->master_collection, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME);
3685 /* Hide the collection from viewport and render. */
3686 override_resync_residual_storage->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER;
3687 }
3688 /* BKE_collection_add above could have tagged the view_layer out of sync. */
3689 BKE_view_layer_synced_ensure(scene, view_layer);
3690 const Object *old_active_object = BKE_view_layer_active_object_get(view_layer);
3691
3692 /* Necessary to improve performances, and prevent layers matching override sub-collections to be
3693 * lost when re-syncing the parent override collection.
3694 * Ref. #73411. */
3696
3697 int library_indirect_level = lib_override_libraries_index_define(bmain);
3698 while (library_indirect_level >= 0) {
3699 int level_reprocess_count = 0;
3700 /* Update overrides from each indirect level separately.
3701 *
3702 * About the looping here: It may happen that some sub-hierarchies of liboverride are moved
3703 * around (the hierarchy in reference data does not match anymore the existing one in
3704 * liboverride data). In some cases, these sub-hierarchies won't be resynced then. If some IDs
3705 * in these sub-hierarchies actually do need resync, then the whole process needs to be applied
3706 * again, until all cases are fully processed.
3707 *
3708 * In practice, even in very complex and 'dirty'/outdated production files, typically less than
3709 * ten reprocesses are enough to cover all cases (in the vast majority of cases, no reprocess
3710 * is needed at all). */
3712 bmain,
3713 scene,
3714 view_layer,
3715 override_resync_residual_storage,
3716 library_indirect_level,
3717 reports))
3718 {
3719 level_reprocess_count++;
3720 if (level_reprocess_count > 100) {
3721 CLOG_WARN(
3722 &LOG_RESYNC,
3723 "Need to reprocess resync for library level %d more than %d times, aborting. This is "
3724 "either caused by extremely complex liboverride hierarchies, or a bug",
3725 library_indirect_level,
3726 level_reprocess_count);
3727 break;
3728 }
3730 4,
3731 "Applying reprocess %d for resyncing at library level %d",
3732 level_reprocess_count,
3733 library_indirect_level);
3734 }
3735 library_indirect_level--;
3736 }
3737
3739
3740 /* Essentially ensures that potentially new overrides of new objects will be instantiated. */
3742 scene,
3743 view_layer,
3744 nullptr,
3745 nullptr,
3746 nullptr,
3747 override_resync_residual_storage,
3748 old_active_object,
3749 true);
3750
3751 if (BKE_collection_is_empty(override_resync_residual_storage)) {
3752 BKE_collection_delete(bmain, override_resync_residual_storage, true);
3753 }
3754
3755 LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
3756 if (library->runtime.tag & LIBRARY_TAG_RESYNC_REQUIRED) {
3758 2,
3759 "library '%s' contains some linked overrides that required recursive resync, "
3760 "consider updating it",
3761 library->filepath);
3762 }
3763 }
3764
3765 /* Cleanup global namemap, to avoid extra processing with regular ID name management. Better to
3766 * re-create the global namemap on demand. */
3768
3770
3772}
3773
3775{
3777
3778 /* Tag all library overrides in the chains of dependencies from the given root one. */
3779 BKE_main_relations_create(bmain, 0);
3781 data.bmain = bmain;
3782 data.scene = nullptr;
3783 data.tag = ID_TAG_DOIT;
3784 data.missing_tag = ID_TAG_MISSING;
3785 data.is_override = true;
3786 data.is_resync = false;
3787
3788 data.root_set(id_root);
3789 data.hierarchy_root_set(id_root->override_library->hierarchy_root);
3790
3793
3795 data.clear();
3796
3797 ID *id;
3798 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3799 if (id->tag & ID_TAG_DOIT) {
3801 ID *id_override_reference = id->override_library->reference;
3802
3803 /* Remap the whole local IDs to use the linked data. */
3804 BKE_libblock_remap(bmain, id, id_override_reference, ID_REMAP_SKIP_INDIRECT_USAGE);
3805 }
3806 }
3807 }
3809
3810 /* Delete the override IDs. */
3812
3813 /* Should not actually be needed here. */
3814 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3815}
3816
3818{
3819 if (!ID_IS_OVERRIDE_LIBRARY(id)) {
3820 return;
3821 }
3823 /* We should never directly 'make local' virtual overrides (aka shape keys). */
3825 id->flag &= ~ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE;
3826 return;
3827 }
3828
3829 BKE_lib_override_library_free(&id->override_library, true);
3830
3831 Key *shape_key = BKE_key_from_id(id);
3832 if (shape_key != nullptr) {
3833 shape_key->id.flag &= ~ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE;
3834 }
3835
3836 if (GS(id->name) == ID_SCE) {
3837 Collection *master_collection = reinterpret_cast<Scene *>(id)->master_collection;
3838 if (master_collection != nullptr) {
3839 master_collection->id.flag &= ~ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE;
3840 }
3841 }
3842
3844 if (node_tree != nullptr) {
3845 node_tree->id.flag &= ~ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE;
3846 }
3847
3848 /* In case a liboverride hierarchy root is 'made local', i.e. is not a liboverride anymore, all
3849 * hierarchy roots of all liboverrides need to be validated/re-generated again.
3850 * Only in case `bmain` is given, otherwise caller is responsible to do this. */
3851 if (bmain) {
3853 }
3854}
3855
3856/* We only build override GHash on request. */
3858{
3859 IDOverrideLibraryRuntime *liboverride_runtime = override_library_runtime_ensure(liboverride);
3860 if (liboverride_runtime->rna_path_to_override_properties == nullptr) {
3861 liboverride_runtime->rna_path_to_override_properties = BLI_ghash_new(
3863 for (IDOverrideLibraryProperty *op =
3864 static_cast<IDOverrideLibraryProperty *>(liboverride->properties.first);
3865 op != nullptr;
3866 op = op->next)
3867 {
3868 BLI_ghash_insert(liboverride_runtime->rna_path_to_override_properties, op->rna_path, op);
3869 }
3870 }
3871
3872 return liboverride_runtime->rna_path_to_override_properties;
3873}
3874
3876 const char *rna_path)
3877{
3878 GHash *liboverride_runtime = override_library_rna_path_mapping_ensure(liboverride);
3879 return static_cast<IDOverrideLibraryProperty *>(BLI_ghash_lookup(liboverride_runtime, rna_path));
3880}
3881
3883 const char *rna_path,
3884 bool *r_created)
3885{
3887
3888 if (op == nullptr) {
3889 op = MEM_cnew<IDOverrideLibraryProperty>(__func__);
3890 op->rna_path = BLI_strdup(rna_path);
3891 BLI_addtail(&liboverride->properties, op);
3892
3893 GHash *liboverride_runtime = override_library_rna_path_mapping_ensure(liboverride);
3894 BLI_ghash_insert(liboverride_runtime, op->rna_path, op);
3895
3896 if (r_created) {
3897 *r_created = true;
3898 }
3899 }
3900 else if (r_created) {
3901 *r_created = false;
3902 }
3903
3904 return op;
3905}
3906
3908 const IDOverrideLibraryProperty *library_prop,
3909 PointerRNA *r_override_poin,
3910 PropertyRNA **r_override_prop,
3911 int *r_index)
3912{
3915 idpoin, library_prop->rna_path, r_override_poin, r_override_prop, r_index);
3916}
3917
3920{
3921 op_dst->rna_path = BLI_strdup(op_src->rna_path);
3922 BLI_duplicatelist(&op_dst->operations, &op_src->operations);
3923
3925 opop_dst = static_cast<IDOverrideLibraryPropertyOperation *>(op_dst->operations.first),
3926 *opop_src = static_cast<IDOverrideLibraryPropertyOperation *>(op_src->operations.first);
3927 opop_dst;
3928 opop_dst = opop_dst->next, opop_src = opop_src->next)
3929 {
3931 }
3932}
3933
3945
3947 const char *old_rna_path,
3948 const char *new_rna_path)
3949{
3950 /* Find the override property by its old RNA path. */
3951 GHash *liboverride_runtime = override_library_rna_path_mapping_ensure(liboverride);
3952 IDOverrideLibraryProperty *liboverride_property = static_cast<IDOverrideLibraryProperty *>(
3953 BLI_ghash_popkey(liboverride_runtime, old_rna_path, nullptr));
3954
3955 if (liboverride_property == nullptr) {
3956 return false;
3957 }
3958
3959 /* Switch over the RNA path. */
3960 MEM_SAFE_FREE(liboverride_property->rna_path);
3961 liboverride_property->rna_path = BLI_strdup(new_rna_path);
3962
3963 /* Put property back into the lookup mapping, using the new RNA path. */
3964 BLI_ghash_insert(liboverride_runtime, liboverride_property->rna_path, liboverride_property);
3965
3966 return true;
3967}
3968
3970 IDOverrideLibraryProperty *liboverride_property,
3971 const bool do_runtime_updates)
3972{
3973 if (do_runtime_updates &&
3974 !ELEM(nullptr, liboverride->runtime, liboverride->runtime->rna_path_to_override_properties))
3975 {
3977 liboverride_property->rna_path,
3978 nullptr,
3979 nullptr);
3980 }
3981 lib_override_library_property_clear(liboverride_property);
3982 BLI_freelinkN(&liboverride->properties, liboverride_property);
3983}
3984
3986 const char *rna_path)
3987{
3988 /* Find the override property by its old RNA path. */
3989 GHash *liboverride_runtime = override_library_rna_path_mapping_ensure(liboverride);
3990 IDOverrideLibraryProperty *liboverride_property = static_cast<IDOverrideLibraryProperty *>(
3991 BLI_ghash_popkey(liboverride_runtime, rna_path, nullptr));
3992
3993 if (liboverride_property == nullptr) {
3994 return false;
3995 }
3996
3997 /* The key (rna_path) was already popped out of the runtime mapping above. */
3998 lib_override_library_property_delete(liboverride, liboverride_property, false);
3999 return true;
4000}
4001
4003 IDOverrideLibraryProperty *liboverride_property)
4004{
4005 lib_override_library_property_delete(liboverride, liboverride_property, true);
4006}
4007
4009 ListBase *liboverride_operations,
4010 const char *subitem_main_name,
4011 const char *subitem_other_name,
4012 const std::optional<const ID *> &subitem_main_id,
4013 const std::optional<const ID *> &subitem_other_id,
4014 const size_t offesetof_opop_main_name,
4015 const size_t offesetof_opop_other_name,
4016 const size_t offesetof_opop_main_id,
4017 const size_t offesetof_opop_other_id)
4018{
4019 const bool do_ids(subitem_main_id);
4021 for (opop = static_cast<IDOverrideLibraryPropertyOperation *>(BLI_findstring_ptr(
4022 liboverride_operations, subitem_main_name, int(offesetof_opop_main_name)));
4023 opop;
4025 reinterpret_cast<Link *>(opop), subitem_main_name, int(offesetof_opop_main_name))))
4026 {
4027 const char *opop_other_name = *reinterpret_cast<const char **>(reinterpret_cast<char *>(opop) +
4028 offesetof_opop_other_name);
4029 const bool opop_use_id = (opop->flag & LIBOVERRIDE_OP_FLAG_IDPOINTER_ITEM_USE_ID) != 0;
4030
4031 if (do_ids && opop_use_id) {
4032 /* Skip if ID pointers are expected valid and they do not exactly match. */
4033 const ID *opop_main_id = *reinterpret_cast<const ID **>(reinterpret_cast<char *>(opop) +
4034 offesetof_opop_main_id);
4035 if (*subitem_main_id != opop_main_id) {
4036 continue;
4037 }
4038 const ID *opop_other_id = *reinterpret_cast<const ID **>(reinterpret_cast<char *>(opop) +
4039 offesetof_opop_other_id);
4040 if (*subitem_other_id != opop_other_id) {
4041 continue;
4042 }
4043 }
4044
4045 /* Only check other name if ID handling is matching between given search parameters and
4046 * current liboverride operation (i.e. if both have valid ID pointers, or both have none). */
4047 if ((do_ids && opop_use_id) || (!do_ids && !opop_use_id)) {
4048 if (!subitem_other_name && !opop_other_name) {
4049 return opop;
4050 }
4051 if (subitem_other_name && opop_other_name && STREQ(subitem_other_name, opop_other_name)) {
4052 return opop;
4053 }
4054 }
4055
4056 /* No exact match found, keep checking the rest of the list of operations. */
4057 }
4058
4059 return nullptr;
4060}
4061
4063 IDOverrideLibraryProperty *liboverride_property,
4064 const char *subitem_refname,
4065 const char *subitem_locname,
4066 const std::optional<const ID *> &subitem_refid,
4067 const std::optional<const ID *> &subitem_locid,
4068 const int subitem_refindex,
4069 const int subitem_locindex,
4070 const bool strict,
4071 bool *r_strict)
4072{
4073 BLI_assert(!subitem_refid == !subitem_locid);
4074
4076 const int subitem_defindex = -1;
4077
4078 if (r_strict) {
4079 *r_strict = true;
4080 }
4081
4082 if (subitem_locname != nullptr) {
4084 &liboverride_property->operations,
4085 subitem_locname,
4086 subitem_refname,
4087 subitem_locid,
4088 subitem_refid,
4089 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_name),
4090 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_name),
4092 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_id));
4093
4094 if (opop != nullptr) {
4095 return opop;
4096 }
4097 }
4098
4099 if (subitem_refname != nullptr) {
4101 &liboverride_property->operations,
4102 subitem_refname,
4103 subitem_locname,
4104 subitem_refid,
4105 subitem_locid,
4106 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_name),
4107 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_name),
4108 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_id),
4109 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_id));
4110
4111 if (opop != nullptr) {
4112 return opop;
4113 }
4114 }
4115
4117 &liboverride_property->operations,
4118 &subitem_locindex,
4119 sizeof(subitem_locindex),
4120 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_index)))))
4121 {
4122 return ELEM(subitem_refindex, -1, opop->subitem_reference_index) ? opop : nullptr;
4123 }
4124
4126 &liboverride_property->operations,
4127 &subitem_refindex,
4128 sizeof(subitem_refindex),
4129 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_index)))))
4130 {
4131 return ELEM(subitem_locindex, -1, opop->subitem_local_index) ? opop : nullptr;
4132 }
4133
4134 /* `index == -1` means all indices, that is a valid fallback in case we requested specific index.
4135 */
4136 if (!strict && (subitem_locindex != subitem_defindex) &&
4138 &liboverride_property->operations,
4139 &subitem_defindex,
4140 sizeof(subitem_defindex),
4141 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_index)))))
4142 {
4143 if (r_strict) {
4144 *r_strict = false;
4145 }
4146 return opop;
4147 }
4148
4149 return nullptr;
4150}
4151
4153 IDOverrideLibraryProperty *liboverride_property,
4154 const short operation,
4155 const char *subitem_refname,
4156 const char *subitem_locname,
4157 const std::optional<ID *> &subitem_refid,
4158 const std::optional<ID *> &subitem_locid,
4159 const int subitem_refindex,
4160 const int subitem_locindex,
4161 const bool strict,
4162 bool *r_strict,
4163 bool *r_created)
4164{
4165 BLI_assert(!subitem_refid == !subitem_locid);
4166
4168 liboverride_property,
4169 subitem_refname,
4170 subitem_locname,
4171 subitem_refid,
4172 subitem_locid,
4173 subitem_refindex,
4174 subitem_locindex,
4175 strict,
4176 r_strict);
4177
4178 if (opop == nullptr) {
4179 opop = MEM_cnew<IDOverrideLibraryPropertyOperation>(__func__);
4180 opop->operation = operation;
4181 if (subitem_locname) {
4182 opop->subitem_local_name = BLI_strdup(subitem_locname);
4183 }
4184 if (subitem_refname) {
4185 opop->subitem_reference_name = BLI_strdup(subitem_refname);
4186 }
4187 opop->subitem_local_index = subitem_locindex;
4188 opop->subitem_reference_index = subitem_refindex;
4189
4190 if (subitem_refid) {
4191 opop->subitem_reference_id = *subitem_refid;
4192 opop->subitem_local_id = *subitem_locid;
4194 }
4195
4196 BLI_addtail(&liboverride_property->operations, opop);
4197
4198 if (r_created) {
4199 *r_created = true;
4200 }
4201 }
4202 else if (r_created) {
4203 *r_created = false;
4204 }
4205
4206 return opop;
4207}
4208
4219
4229
4231 IDOverrideLibraryProperty *liboverride_property,
4232 IDOverrideLibraryPropertyOperation *liboverride_property_operation)
4233{
4234 lib_override_library_property_operation_clear(liboverride_property_operation);
4235 BLI_freelinkN(&liboverride_property->operations, liboverride_property_operation);
4236}
4237
4239 IDOverrideLibraryPropertyOperation *liboverride_property_operation,
4240 PointerRNA *ptr_dst,
4241 PointerRNA *ptr_src,
4242 PointerRNA *ptr_storage,
4243 PropertyRNA *prop_dst,
4244 PropertyRNA *prop_src,
4245 PropertyRNA *prop_storage)
4246{
4247 switch (liboverride_property_operation->operation) {
4249 return true;
4250 case LIBOVERRIDE_OP_ADD:
4255 if (ptr_storage == nullptr || ptr_storage->data == nullptr || prop_storage == nullptr) {
4256 BLI_assert_msg(0, "Missing data to apply differential override operation.");
4257 return false;
4258 }
4265 if ((ptr_dst == nullptr || ptr_dst->data == nullptr || prop_dst == nullptr) ||
4266 (ptr_src == nullptr || ptr_src->data == nullptr || prop_src == nullptr))
4267 {
4268 BLI_assert_msg(0, "Missing data to apply override operation.");
4269 return false;
4270 }
4271 }
4272
4273 return true;
4274}
4275
4276static bool override_library_is_valid(const ID &id,
4277 const IDOverrideLibrary &liboverride,
4278 ReportList *reports)
4279{
4280 if (liboverride.reference == nullptr) {
4281 /* This (probably) used to be a template ID, could be linked or local, not an override. */
4282 BKE_reportf(reports,
4284 "Library override templates have been removed: removing all override data from "
4285 "the data-block '%s'",
4286 id.name);
4287 return false;
4288 }
4289 if (liboverride.reference == &id) {
4290 /* Very serious data corruption, cannot do much about it besides removing the liboverride data.
4291 */
4292 BKE_reportf(reports,
4293 RPT_ERROR,
4294 "Data corruption: data-block '%s' is using itself as library override reference, "
4295 "removing all override data",
4296 id.name);
4297 return false;
4298 }
4299 if (!ID_IS_LINKED(liboverride.reference)) {
4300 /* Very serious data corruption, cannot do much about it besides removing the liboverride data.
4301 */
4302 BKE_reportf(reports,
4303 RPT_ERROR,
4304 "Data corruption: data-block '%s' is using another local data-block ('%s') as "
4305 "library override reference, removing all override data",
4306 id.name,
4307 liboverride.reference->name);
4308 return false;
4309 }
4310 return true;
4311}
4312
4314{
4315 /* Do NOT use `ID_IS_OVERRIDE_LIBRARY` here, since this code also needs to fix broken cases (like
4316 * null reference pointer), which would be skipped by that macro. */
4317 if (id->override_library == nullptr && !ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
4318 return;
4319 }
4320
4321 ID *liboverride_id = id;
4322 IDOverrideLibrary *liboverride = id->override_library;
4324 liboverride = BKE_lib_override_library_get(bmain, id, nullptr, &liboverride_id);
4325 if (!liboverride || !override_library_is_valid(*liboverride_id, *liboverride, reports)) {
4326 /* Happens in case the given ID is a liboverride-embedded one (actual embedded ID like
4327 * NodeTree or master collection, or shape-keys), used by a totally not-liboverride owner ID.
4328 * Just clear the relevant ID flag.
4329 */
4330 id->flag &= ~ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE;
4331 return;
4332 }
4333 }
4334 BLI_assert(liboverride);
4335
4336 /* NOTE: In code deleting liboverride data below, #BKE_lib_override_library_make_local is used
4337 * instead of directly calling #BKE_lib_override_library_free, because the former also handles
4338 * properly 'liboverride embedded' IDs, like root node-trees, or shape-keys. */
4339 if (!override_library_is_valid(*liboverride_id, *liboverride, reports)) {
4340 BKE_lib_override_library_make_local(nullptr, liboverride_id);
4341 }
4342}
4343
4345{
4346 ID *id;
4347
4348 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4349 BKE_lib_override_library_validate(bmain, id, reports);
4350 }
4352}
4353
4355{
4357
4358 ID *reference = local->override_library->reference;
4359
4360 BLI_assert(reference);
4361 BLI_assert(GS(local->name) == GS(reference->name));
4362
4363 if (GS(local->name) == ID_OB) {
4364 /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would
4365 * ensure this is valid, but in some situations (like hidden collections etc.) this won't
4366 * be the case, so we need to take care of this ourselves. */
4367 Object *ob_local = reinterpret_cast<Object *>(local);
4368 if (ob_local->type == OB_ARMATURE) {
4369 Object *ob_reference = reinterpret_cast<Object *>(local->override_library->reference);
4370 BLI_assert(ob_local->data != nullptr);
4371 BLI_assert(ob_reference->data != nullptr);
4372 BKE_pose_ensure(bmain, ob_local, static_cast<bArmature *>(ob_local->data), true);
4373 BKE_pose_ensure(bmain, ob_reference, static_cast<bArmature *>(ob_reference->data), true);
4374 }
4375 }
4376
4377 /* Note that reference is assumed always valid, caller has to ensure that itself. */
4378
4379 PointerRNA rnaptr_local = RNA_id_pointer_create(local);
4380 PointerRNA rnaptr_reference = RNA_id_pointer_create(reference);
4381
4383 bmain,
4384 &rnaptr_local,
4385 &rnaptr_reference,
4386 nullptr,
4387 0,
4388 local->override_library,
4391 nullptr))
4392 {
4393 local->tag &= ~ID_TAG_LIBOVERRIDE_REFOK;
4394 return false;
4395 }
4396
4397 return true;
4398}
4399
4401{
4403
4404 ID *reference = local->override_library->reference;
4405
4406 BLI_assert(reference);
4407 BLI_assert(GS(local->name) == GS(reference->name));
4408
4409 if (reference->override_library && (reference->tag & ID_TAG_LIBOVERRIDE_REFOK) == 0) {
4410 if (!BKE_lib_override_library_status_check_reference(bmain, reference)) {
4411 /* If reference is also an override of another data-block, and its status is not OK,
4412 * then this override is not OK either.
4413 * Note that this should only happen when reloading libraries. */
4414 local->tag &= ~ID_TAG_LIBOVERRIDE_REFOK;
4415 return false;
4416 }
4417 }
4418
4419 if (GS(local->name) == ID_OB) {
4420 /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would
4421 * ensure this is valid, but in some situations (like hidden collections etc.) this won't
4422 * be the case, so we need to take care of this ourselves. */
4423 Object *ob_local = reinterpret_cast<Object *>(local);
4424 if (ob_local->type == OB_ARMATURE) {
4425 Object *ob_reference = reinterpret_cast<Object *>(local->override_library->reference);
4426 BLI_assert(ob_local->data != nullptr);
4427 BLI_assert(ob_reference->data != nullptr);
4428 BKE_pose_ensure(bmain, ob_local, static_cast<bArmature *>(ob_local->data), true);
4429 BKE_pose_ensure(bmain, ob_reference, static_cast<bArmature *>(ob_reference->data), true);
4430 }
4431 }
4432
4433 PointerRNA rnaptr_local = RNA_id_pointer_create(local);
4434 PointerRNA rnaptr_reference = RNA_id_pointer_create(reference);
4435
4436 if (!RNA_struct_override_matches(bmain,
4437 &rnaptr_local,
4438 &rnaptr_reference,
4439 nullptr,
4440 0,
4441 local->override_library,
4443 nullptr))
4444 {
4445 local->tag &= ~ID_TAG_LIBOVERRIDE_REFOK;
4446 return false;
4447 }
4448
4449 return true;
4450}
4451
4453 ID *local,
4454 const eRNAOverrideMatch liboverride_match_flags,
4455 eRNAOverrideMatchResult *r_report_flags)
4456{
4457 BLI_assert(!ID_IS_LINKED(local));
4459
4460 /* Do not attempt to generate overriding rules from an empty place-holder generated by link
4461 * code when it cannot find the actual library/ID. Much better to keep the local data-block as
4462 * is in the file in that case, until broken lib is fixed. */
4463 if (ID_MISSING(local->override_library->reference)) {
4464 return;
4465 }
4466
4467 if (GS(local->name) == ID_OB) {
4468 /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would
4469 * ensure this is valid, but in some situations (like hidden collections etc.) this won't
4470 * be the case, so we need to take care of this ourselves. */
4471 Object *ob_local = reinterpret_cast<Object *>(local);
4472 if (ob_local->type == OB_ARMATURE) {
4473 Object *ob_reference = reinterpret_cast<Object *>(local->override_library->reference);
4474 BLI_assert(ob_local->data != nullptr);
4475 BLI_assert(ob_reference->data != nullptr);
4476 BKE_pose_ensure(bmain, ob_local, static_cast<bArmature *>(ob_local->data), true);
4477 BKE_pose_ensure(bmain, ob_reference, static_cast<bArmature *>(ob_reference->data), true);
4478 }
4479 }
4480
4481 PointerRNA rnaptr_local = RNA_id_pointer_create(local);
4482 PointerRNA rnaptr_reference = RNA_id_pointer_create(local->override_library->reference);
4483
4486 &rnaptr_local,
4487 &rnaptr_reference,
4488 nullptr,
4489 0,
4490 local->override_library,
4491 liboverride_match_flags,
4492 &local_report_flags);
4493
4494 if (local_report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORED) {
4495 CLOG_INFO(&LOG, 2, "We did restore some properties of %s from its reference", local->name);
4496 }
4497 if (local_report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORE_TAGGED) {
4498 CLOG_INFO(&LOG,
4499 2,
4500 "We did tag some properties of %s for restoration from its reference",
4501 local->name);
4502 }
4503 if (local_report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) {
4504 CLOG_INFO(&LOG, 2, "We did generate library override rules for %s", local->name);
4505 }
4506 else {
4507 CLOG_INFO(&LOG, 2, "No new library override rules for %s", local->name);
4508 }
4509
4510 if (r_report_flags != nullptr) {
4511 *r_report_flags = static_cast<eRNAOverrideMatchResult>(*r_report_flags | local_report_flags);
4512 }
4513}
4514void BKE_lib_override_library_operations_create(Main *bmain, ID *local, int *r_report_flags)
4515{
4517 bmain,
4518 local,
4520 reinterpret_cast<eRNAOverrideMatchResult *>(r_report_flags));
4521}
4522
4523void BKE_lib_override_library_operations_restore(Main *bmain, ID *local, int *r_report_flags)
4524{
4525 if (!ID_IS_OVERRIDE_LIBRARY_REAL(local) ||
4526 (local->override_library->runtime->tag & LIBOVERRIDE_TAG_NEEDS_RESTORE) == 0)
4527 {
4528 return;
4529 }
4530
4531 PointerRNA rnaptr_src = RNA_id_pointer_create(local);
4532 PointerRNA rnaptr_dst = RNA_id_pointer_create(local->override_library->reference);
4534 bmain,
4535 &rnaptr_dst,
4536 &rnaptr_src,
4537 nullptr,
4538 local->override_library,
4541
4542 LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryProperty *, op, &local->override_library->properties)
4543 {
4544 if (op->tag & LIBOVERRIDE_PROP_TAG_NEEDS_RETORE) {
4546 if (opop->tag & LIBOVERRIDE_PROP_TAG_NEEDS_RETORE) {
4548 }
4549 }
4550 if (BLI_listbase_is_empty(&local->override_library->properties)) {
4551 BKE_lib_override_library_property_delete(local->override_library, op);
4552 }
4553 else {
4555 }
4556 }
4557 }
4558 local->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEEDS_RESTORE;
4559
4560 if (r_report_flags != nullptr) {
4561 *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED;
4562 }
4563}
4564
4569
4570static void lib_override_library_operations_create_cb(TaskPool *__restrict pool, void *taskdata)
4571{
4572 LibOverrideOpCreateData *create_data = static_cast<LibOverrideOpCreateData *>(
4574 ID *id = static_cast<ID *>(taskdata);
4575
4578 create_data->bmain,
4579 id,
4582 &report_flags);
4583 atomic_fetch_and_or_uint32(reinterpret_cast<uint32_t *>(&create_data->report_flags),
4584 report_flags);
4585}
4586
4588 const bool force_auto,
4589 int *r_report_flags)
4590{
4591 ID *id;
4592
4593#ifdef DEBUG_OVERRIDE_TIMEIT
4595#endif
4596
4597 /* When force-auto is set, we also remove all unused existing override properties & operations.
4598 */
4599 if (force_auto) {
4601 }
4602
4603 /* Usual pose bones issue, need to be done outside of the threaded process or we may run into
4604 * concurrency issues here.
4605 * Note that calling #BKE_pose_ensure again in thread in
4606 * #BKE_lib_override_library_operations_create is not a problem then. */
4607 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
4608 if (ob->type == OB_ARMATURE) {
4609 BLI_assert(ob->data != nullptr);
4610 BKE_pose_ensure(bmain, ob, static_cast<bArmature *>(ob->data), true);
4611 }
4612 }
4613
4614 LibOverrideOpCreateData create_pool_data{};
4615 create_pool_data.bmain = bmain;
4616 create_pool_data.report_flags = RNA_OVERRIDE_MATCH_RESULT_INIT;
4618
4619 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4620 if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
4621 continue;
4622 }
4623 /* Propagate potential embedded data tag to the owner ID (see also
4624 * #BKE_lib_override_id_tag_on_deg_tag_from_user). */
4625 if (Key *key = BKE_key_from_id(id)) {
4626 if (key->id.tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH) {
4627 key->id.tag &= ~ID_TAG_LIBOVERRIDE_AUTOREFRESH;
4629 }
4630 }
4631 if (bNodeTree *ntree = blender::bke::node_tree_from_id(id)) {
4632 if (ntree->id.tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH) {
4633 ntree->id.tag &= ~ID_TAG_LIBOVERRIDE_AUTOREFRESH;
4635 }
4636 }
4637 if (GS(id->name) == ID_SCE) {
4638 if (Collection *scene_collection = reinterpret_cast<Scene *>(id)->master_collection) {
4639 if (scene_collection->id.tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH) {
4640 scene_collection->id.tag &= ~ID_TAG_LIBOVERRIDE_AUTOREFRESH;
4642 }
4643 }
4644 }
4645
4646 if (force_auto || (id->tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH)) {
4647 /* Usual issue with pose, it's quiet rare but sometimes they may not be up to date when this
4648 * function is called. */
4649 if (GS(id->name) == ID_OB) {
4650 Object *ob = reinterpret_cast<Object *>(id);
4651 if (ob->type == OB_ARMATURE) {
4652 BLI_assert(ob->data != nullptr);
4653 BKE_pose_ensure(bmain, ob, static_cast<bArmature *>(ob->data), true);
4654 }
4655 }
4656 /* Only check overrides if we do have the real reference data available, and not some empty
4657 * 'placeholder' for missing data (broken links). */
4658 if ((id->override_library->reference->tag & ID_TAG_MISSING) == 0) {
4661 }
4662 else {
4664 id->override_library, LIBOVERRIDE_PROP_OP_TAG_UNUSED, false);
4665 }
4666 }
4667 else {
4668 /* Clear 'unused' tag for un-processed IDs, otherwise e.g. linked overrides will loose their
4669 * list of overridden properties. */
4671 id->override_library, LIBOVERRIDE_PROP_OP_TAG_UNUSED, false);
4672 }
4673 id->tag &= ~ID_TAG_LIBOVERRIDE_AUTOREFRESH;
4674 }
4676
4678
4680
4681 if (create_pool_data.report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORE_TAGGED) {
4683 bmain, reinterpret_cast<int *>(&create_pool_data.report_flags));
4684 create_pool_data.report_flags = static_cast<eRNAOverrideMatchResult>(
4685 (create_pool_data.report_flags & ~RNA_OVERRIDE_MATCH_RESULT_RESTORE_TAGGED));
4686 }
4687
4688 if (r_report_flags != nullptr) {
4689 *r_report_flags |= create_pool_data.report_flags;
4690 }
4691
4692 if (force_auto) {
4694 }
4695
4696#ifdef DEBUG_OVERRIDE_TIMEIT
4698#endif
4699}
4700
4702{
4703 ID *id;
4704
4705 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4706 if (!(!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) && id->override_library->runtime &&
4707 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_NEEDS_RESTORE) != 0))
4708 {
4709 continue;
4710 }
4711
4712 /* Only restore overrides if we do have the real reference data available, and not some empty
4713 * 'placeholder' for missing data (broken links). */
4714 if (id->override_library->reference->tag & ID_TAG_MISSING) {
4715 continue;
4716 }
4717
4718 BKE_lib_override_library_operations_restore(bmain, id, r_report_flags);
4719 }
4721}
4722
4724 ID *id_root,
4725 const bool do_reset_system_override)
4726{
4727 bool was_op_deleted = false;
4728
4729 if (do_reset_system_override) {
4731 }
4732
4735 {
4736 bool do_op_delete = true;
4737 const bool is_collection = op->rna_prop_type == PROP_COLLECTION;
4738 if (is_collection || op->rna_prop_type == PROP_POINTER) {
4739 PointerRNA ptr, ptr_lib;
4740 PropertyRNA *prop, *prop_lib;
4741
4742 PointerRNA ptr_root = RNA_pointer_create(id_root, &RNA_ID, id_root);
4743 PointerRNA ptr_root_lib = RNA_pointer_create(
4744 id_root->override_library->reference, &RNA_ID, id_root->override_library->reference);
4745
4746 bool prop_exists = RNA_path_resolve_property(&ptr_root, op->rna_path, &ptr, &prop);
4747 if (prop_exists) {
4748 prop_exists = RNA_path_resolve_property(&ptr_root_lib, op->rna_path, &ptr_lib, &prop_lib);
4749
4750 if (prop_exists) {
4753 if (is_collection) {
4755 ptr_lib.type = RNA_property_pointer_type(&ptr_lib, prop_lib);
4756 }
4757 else {
4759 ptr_lib = RNA_property_pointer_get(&ptr_lib, prop_lib);
4760 }
4761 if (ptr.owner_id != nullptr && ptr_lib.owner_id != nullptr) {
4762 BLI_assert(ptr.type == ptr_lib.type);
4763 do_op_delete = !(RNA_struct_is_ID(ptr.type) &&
4764 ptr.owner_id->override_library != nullptr &&
4766 }
4767 }
4768 }
4769 }
4770
4771 if (do_op_delete) {
4773 was_op_deleted = true;
4774 }
4775 }
4776
4777 if (was_op_deleted) {
4780 id_root->override_library);
4781 liboverride_runtime->tag |= LIBOVERRIDE_TAG_NEEDS_RELOAD;
4782 }
4783
4784 return was_op_deleted;
4785}
4786
4788 ID *id_root,
4789 const bool do_reset_system_override)
4790{
4791 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
4792 return;
4793 }
4794
4795 if (lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override)) {
4796 if (id_root->override_library->runtime != nullptr &&
4798 {
4799 BKE_lib_override_library_update(bmain, id_root);
4800 id_root->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEEDS_RELOAD;
4801 }
4802 }
4803}
4804
4806 ID *id_root,
4807 const bool do_reset_system_override)
4808{
4809 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
4810 return;
4811 }
4812
4813 void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id_root);
4814 if (entry_vp == nullptr) {
4815 /* This ID is not used by nor using any other ID. */
4816 lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
4817 return;
4818 }
4819
4820 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(*entry_vp);
4822 /* This ID has already been processed. */
4823 return;
4824 }
4825
4826 lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
4827
4828 /* This way we won't process again that ID, should we encounter it again through another
4829 * relationship hierarchy. */
4831
4832 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
4833 to_id_entry = to_id_entry->next)
4834 {
4836 continue;
4837 }
4838 /* We only consider IDs from the same library. */
4839 if (*to_id_entry->id_pointer.to != nullptr) {
4840 ID *to_id = *to_id_entry->id_pointer.to;
4841 if (to_id->override_library != nullptr) {
4842 lib_override_library_id_hierarchy_recursive_reset(bmain, to_id, do_reset_system_override);
4843 }
4844 }
4845 }
4846}
4847
4849 ID *id_root,
4850 const bool do_reset_system_override)
4851{
4852 BKE_main_relations_create(bmain, 0);
4853
4854 lib_override_library_id_hierarchy_recursive_reset(bmain, id_root, do_reset_system_override);
4855
4857
4858 ID *id;
4859 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4860 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || id->override_library->runtime == nullptr ||
4861 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_NEEDS_RELOAD) == 0)
4862 {
4863 continue;
4864 }
4866 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEEDS_RELOAD;
4867 }
4869}
4870
4872 const short tag,
4873 const bool do_set)
4874{
4875 if (liboverride_property != nullptr) {
4876 if (do_set) {
4877 liboverride_property->tag |= tag;
4878 }
4879 else {
4880 liboverride_property->tag &= ~tag;
4881 }
4882
4884 IDOverrideLibraryPropertyOperation *, opop, &liboverride_property->operations)
4885 {
4886 if (do_set) {
4887 opop->tag |= tag;
4888 }
4889 else {
4890 opop->tag &= ~tag;
4891 }
4892 }
4893 }
4894}
4895
4897 const short tag,
4898 const bool do_set)
4899{
4900 if (liboverride != nullptr) {
4903 }
4904 }
4905}
4906
4907void BKE_lib_override_library_main_tag(Main *bmain, const short tag, const bool do_set)
4908{
4909 ID *id;
4910
4911 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4912 if (ID_IS_OVERRIDE_LIBRARY(id)) {
4913 BKE_lib_override_library_properties_tag(id->override_library, tag, do_set);
4914 }
4915 }
4917}
4918
4920{
4921 if (ID_IS_OVERRIDE_LIBRARY_REAL(local)) {
4923 IDOverrideLibraryProperty *, op, &local->override_library->properties)
4924 {
4925 if (op->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
4926 BKE_lib_override_library_property_delete(local->override_library, op);
4927 }
4928 else {
4930 if (opop->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
4932 }
4933 }
4934 if (BLI_listbase_is_empty(&op->operations)) {
4935 BKE_lib_override_library_property_delete(local->override_library, op);
4936 }
4937 }
4938 }
4939 }
4940}
4941
4943{
4944 ID *id;
4945
4946 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4947 if (ID_IS_OVERRIDE_LIBRARY(id)) {
4949 }
4950 }
4952}
4953
4954static void lib_override_id_swap(Main *bmain, ID *id_local, ID *id_temp)
4955{
4956 /* Ensure ViewLayers are in sync in case a Scene is being swapped, and prevent any further resync
4957 * during the swapping itself. */
4958 if (GS(id_local->name) == ID_SCE) {
4959 BKE_scene_view_layers_synced_ensure(reinterpret_cast<Scene *>(id_local));
4960 BKE_scene_view_layers_synced_ensure(reinterpret_cast<Scene *>(id_temp));
4961 }
4963
4964 BKE_lib_id_swap(bmain, id_local, id_temp, true, 0);
4965 /* We need to keep these tags from temp ID into orig one.
4966 * ID swap does not swap most of ID data itself. */
4967 id_local->tag |= (id_temp->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC);
4968
4970}
4971
4973{
4974 if (!ID_IS_OVERRIDE_LIBRARY_REAL(local)) {
4975 return;
4976 }
4977
4978 /* Do not attempt to apply overriding rules over an empty place-holder generated by link code
4979 * when it cannot find the actual library/ID. Much better to keep the local data-block as loaded
4980 * from the file in that case, until broken lib is fixed. */
4981 if (ID_MISSING(local->override_library->reference)) {
4982 return;
4983 }
4984
4985 /* Recursively do 'ancestor' overrides first, if any. */
4986 if (local->override_library->reference->override_library &&
4987 (local->override_library->reference->tag & ID_TAG_LIBOVERRIDE_REFOK) == 0)
4988 {
4989 BKE_lib_override_library_update(bmain, local->override_library->reference);
4990 }
4991
4992 /* We want to avoid having to remap here, however creating up-to-date override is much simpler
4993 * if based on reference than on current override.
4994 * So we work on temp copy of reference, and 'swap' its content with local. */
4995
4996 /* XXX We need a way to get off-Main copies of IDs (similar to localized mats/texts/ etc.)!
4997 * However, this is whole bunch of code work in itself, so for now plain stupid ID copy
4998 * will do, as inefficient as it is. :/
4999 * Actually, maybe not! Since we are swapping with original ID's local content, we want to
5000 * keep user-count in correct state when freeing tmp_id
5001 * (and that user-counts of IDs used by 'new' local data also remain correct). */
5002 /* This would imply change in handling of user-count all over RNA
5003 * (and possibly all over Blender code).
5004 * Not impossible to do, but would rather see first if extra useless usual user handling
5005 * is actually a (performances) issue here. */
5006
5007 ID *tmp_id = BKE_id_copy_ex(bmain,
5008 local->override_library->reference,
5009 nullptr,
5011
5012 if (tmp_id == nullptr) {
5013 return;
5014 }
5015
5016 /* Remove the pair (idname, lib) of this temp id from the name map. */
5017 BKE_main_namemap_remove_name(bmain, tmp_id, tmp_id->name + 2);
5018
5019 tmp_id->lib = local->lib;
5020
5021 /* This ID name is problematic, since it is an 'rna name property' it should not be editable or
5022 * different from reference linked ID. But local ID names need to be unique in a given type
5023 * list of Main, so we cannot always keep it identical, which is why we need this special
5024 * manual handling here. */
5025 STRNCPY(tmp_id->name, local->name);
5026
5027 /* Those ugly loop-back pointers again. Luckily we only need to deal with the shape keys here,
5028 * collections' parents are fully runtime and reconstructed later. */
5029 Key *local_key = BKE_key_from_id(local);
5030 Key *tmp_key = BKE_key_from_id(tmp_id);
5031 if (local_key != nullptr && tmp_key != nullptr) {
5032 tmp_key->id.flag |= (local_key->id.flag & ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE);
5033 BKE_main_namemap_remove_name(bmain, &tmp_key->id, tmp_key->id.name + 2);
5034 tmp_key->id.lib = local_key->id.lib;
5035 STRNCPY(tmp_key->id.name, local_key->id.name);
5036 }
5037
5038 PointerRNA rnaptr_src = RNA_id_pointer_create(local);
5039 PointerRNA rnaptr_dst = RNA_id_pointer_create(tmp_id);
5040 PointerRNA rnaptr_storage_stack, *rnaptr_storage = nullptr;
5041 if (local->override_library->storage) {
5042 rnaptr_storage_stack = RNA_id_pointer_create(local->override_library->storage);
5043 rnaptr_storage = &rnaptr_storage_stack;
5044 }
5045
5047 &rnaptr_dst,
5048 &rnaptr_src,
5049 rnaptr_storage,
5050 local->override_library,
5052
5054
5055 /* This also transfers all pointers (memory) owned by local to tmp_id, and vice-versa.
5056 * So when we'll free tmp_id, we'll actually free old, outdated data from local. */
5057 lib_override_id_swap(bmain, local, tmp_id);
5058
5059 if (local_key != nullptr && tmp_key != nullptr) {
5060 /* This is some kind of hard-coded 'always enforced override'. */
5061 lib_override_id_swap(bmain, &local_key->id, &tmp_key->id);
5062 tmp_key->id.flag |= (local_key->id.flag & ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE);
5063 /* The swap of local and tmp_id inverted those pointers, we need to redefine proper
5064 * relationships. */
5065 *BKE_key_from_id_p(local) = local_key;
5066 *BKE_key_from_id_p(tmp_id) = tmp_key;
5067 local_key->from = local;
5068 tmp_key->from = tmp_id;
5069 }
5070
5071 /* Again, horribly inefficient in our case, we need something off-Main
5072 * (aka more generic nolib copy/free stuff).
5073 * NOTE: Do not remove this tmp_id's name from the namemap here, since this name actually still
5074 * exists in `bmain`. */
5076
5077 if (GS(local->name) == ID_AR) {
5078 /* Fun times again, thanks to bone pointers in pose data of objects. We keep same ID addresses,
5079 * but internal data has changed for sure, so we need to invalidate pose-bones caches. */
5080 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
5081 if (ob->pose != nullptr && ob->data == local) {
5082 BLI_assert(ob->type == OB_ARMATURE);
5083 ob->pose->flag |= POSE_RECALC;
5084 /* We need to clear pose bone pointers immediately, some code may access those before pose
5085 * is actually recomputed, which can lead to segfault. */
5086 BKE_pose_clear_pointers(ob->pose);
5087 }
5088 }
5089 }
5090
5091 /* NLA Tweak Mode is, in a way, an "edit mode" for certain animation data. However, contrary to
5092 * mesh/armature edit modes, it doesn't use its own runtime data, but directly changes various
5093 * DNA pointers & flags. As these need to be all consistently set for the system to behave in a
5094 * well-defined manner, and the values can come from different files (library NLA tracks/strips
5095 * vs. override-added NLA tracks/strips), they need to be checked _after_ all overrides have been
5096 * applied. */
5098
5099 if (local->override_library->storage) {
5100 /* We know this data-block is not used anywhere besides local->override->storage. */
5101 /* XXX For until we get fully shadow copies, we still need to ensure storage releases
5102 * its usage of any ID pointers it may have. */
5103 BKE_id_free_ex(bmain, local->override_library->storage, LIB_ID_FREE_NO_UI_USER, true);
5104 local->override_library->storage = nullptr;
5105 }
5106
5107 local->tag |= ID_TAG_LIBOVERRIDE_REFOK;
5108
5109 /* NOTE: Since we reload full content from linked ID here, potentially from edited local
5110 * override, we do not really have a way to know *what* is changed, so we need to rely on the
5111 * massive destruction weapon of `ID_RECALC_ALL` here. */
5112 DEG_id_tag_update_ex(bmain, local, ID_RECALC_ALL);
5113 /* For same reason as above, also assume that the relationships between IDs changed. */
5115}
5116
5118{
5119 ID *id;
5120
5121 /* This temporary swap of G_MAIN is rather ugly,
5122 * but necessary to avoid asserts checks in some RNA assignment functions,
5123 * since those always use G_MAIN when they need access to a Main database. */
5124 Main *orig_gmain = BKE_blender_globals_main_swap(bmain);
5125
5127
5128 FOREACH_MAIN_ID_BEGIN (bmain, id) {
5129 if (id->override_library != nullptr) {
5131 }
5132 }
5134
5136
5137 Main *tmp_gmain = BKE_blender_globals_main_swap(orig_gmain);
5138 BLI_assert(tmp_gmain == bmain);
5139 UNUSED_VARS_NDEBUG(tmp_gmain);
5140}
5141
5143{
5144 /* The only strong known case currently are objects used by override collections. */
5145 /* TODO: There are most likely other cases... This may need to be addressed in a better way at
5146 * some point. */
5147 if (GS(id->name) != ID_OB) {
5148 return true;
5149 }
5150 Object *ob = reinterpret_cast<Object *>(id);
5151 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
5152 if (!ID_IS_OVERRIDE_LIBRARY(collection)) {
5153 continue;
5154 }
5155 if (BKE_collection_has_object(collection, ob)) {
5156 return false;
5157 }
5158 }
5159 return true;
5160}
5161
5162void BKE_lib_override_debug_print(IDOverrideLibrary *liboverride, const char *intro_txt)
5163{
5164 const char *line_prefix = "";
5165 if (intro_txt != nullptr) {
5166 std::cout << intro_txt << "\n";
5167 line_prefix = "\t";
5168 }
5169
5171 std::cout << line_prefix << op->rna_path << " [";
5172 if (op->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
5173 std::cout << " UNUSED ";
5174 }
5175 std::cout << "]\n";
5176
5177 LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
5178 std::cout << line_prefix << line_prefix << opop->operation << " [";
5179 if (opop->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
5180 std::cout << " UNUSED ";
5181 }
5183 std::cout << " MATCH_REF ";
5184 }
5185 std::cout << "] ";
5186 if (opop->subitem_reference_name || opop->subitem_local_name) {
5187 std::cout << "(" << opop->subitem_reference_name << " <" << opop->subitem_reference_id
5188 << "> -> " << opop->subitem_local_name << " <" << opop->subitem_local_id << ">)";
5189 }
5190 else if (opop->subitem_reference_index >= 0 || opop->subitem_local_index >= 0) {
5191 std::cout << "(" << opop->subitem_reference_index << " -> " << opop->subitem_local_index
5192 << ")";
5193 }
5194 std::cout << "\n";
5195 }
5196 }
5197}
5198
5219
5221 OverrideLibraryStorage *liboverride_storage,
5222 ID *local)
5223{
5224 if (ID_IS_OVERRIDE_LIBRARY_VIRTUAL(local)) {
5225 /* This is actually one of these embedded IDs (root node trees, master collections or
5226 * shape-keys) that cannot have their own override. Nothing to do here! */
5227 return nullptr;
5228 }
5229
5231 BLI_assert(liboverride_storage != nullptr);
5232 UNUSED_VARS_NDEBUG(liboverride_storage);
5233
5234 /* Forcefully ensure we know about all needed override operations. */
5235 BKE_lib_override_library_operations_create(bmain, local, nullptr);
5236
5237 ID *storage_id;
5238#ifdef DEBUG_OVERRIDE_TIMEIT
5240#endif
5241
5242 /* This is fully disabled for now, as it generated very hard to solve issues with Collections and
5243 * how they reference each-other in their parents/children relations.
5244 * Core of the issue is creating and storing those copies in a separate Main, while collection
5245 * copy code re-assign blindly parents/children, even if they do not belong to the same Main.
5246 * One solution could be to implement special flag as discussed below, and prevent any
5247 * other-ID-reference creation/update in that case (since no differential operation is expected
5248 * to involve those anyway). */
5249#if 0
5250 /* XXX TODO: We may also want a specialized handling of things here too, to avoid copying heavy
5251 * never-overridable data (like Mesh geometry etc.)? And also maybe avoid lib
5252 * reference-counting completely (shallow copy). */
5253 /* This would imply change in handling of user-count all over RNA
5254 * (and possibly all over Blender code).
5255 * Not impossible to do, but would rather see first is extra useless usual user handling is
5256 * actually a (performances) issue here, before doing it. */
5257 storage_id = BKE_id_copy(reinterpret_cast<Main *>(liboverride_storage), local);
5258
5259 if (storage_id != nullptr) {
5260 PointerRNA rnaptr_reference = RNA_id_pointer_create(local->override_library->reference);
5261 PointerRNA rnaptr_final = RNA_id_pointer_create(local);
5262 PointerRNA rnaptr_storage = RNA_id_pointer_create(storage_id);
5263
5265 bmain, &rnaptr_final, &rnaptr_reference, &rnaptr_storage, local->override_library))
5266 {
5267 BKE_id_free_ex(override_storage, storage_id, LIB_ID_FREE_NO_UI_USER, true);
5268 storage_id = nullptr;
5269 }
5270 }
5271#else
5272 storage_id = nullptr;
5273#endif
5274
5275 local->override_library->storage = storage_id;
5276
5277#ifdef DEBUG_OVERRIDE_TIMEIT
5279#endif
5280 return storage_id;
5281}
5282
5284 OverrideLibraryStorage * /*liboverride_storage*/, ID *local)
5285{
5287
5288 /* Nothing else to do here really, we need to keep all temp override storage data-blocks in
5289 * memory until whole file is written anyway (otherwise we'd get mem pointers overlap). */
5290 local->override_library->storage = nullptr;
5291}
5292
5294 OverrideLibraryStorage *liboverride_storage)
5295{
5296 /* We cannot just call BKE_main_free(override_storage), not until we have option to make
5297 * 'ghost' copies of IDs without increasing user-count of used data-blocks. */
5298 ID *id;
5299
5300 FOREACH_MAIN_ID_BEGIN (liboverride_storage, id) {
5301 BKE_id_free_ex(liboverride_storage, id, LIB_ID_FREE_NO_UI_USER, true);
5302 }
5304
5305 BKE_main_free(liboverride_storage);
5306}
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:89
void BKE_animdata_liboverride_post_process(ID *id)
void BKE_pose_clear_pointers(bPose *pose)
Definition armature.cc:2729
void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
Definition armature.cc:2822
Blender util stuff.
Main * BKE_blender_globals_main_swap(Main *new_gmain)
Definition blender.cc:226
void BKE_collection_add_from_collection(Main *bmain, Scene *scene, Collection *collection_src, Collection *collection_dst)
Collection * BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
bool BKE_collection_has_object(Collection *collection, const Object *ob)
bool BKE_collection_is_empty(const Collection *collection)
bool BKE_collection_is_in_scene(Collection *collection)
void BKE_collection_add_from_object(Main *bmain, Scene *scene, const Object *ob_src, Collection *collection_dst)
GSet * BKE_scene_objects_as_gset(Scene *scene, GSet *objects_gset)
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
bool BKE_collection_has_collection(const Collection *parent, const Collection *collection)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
FCurve * BKE_animadata_fcurve_find_by_rna_path(AnimData *animdata, const char *rna_path, const int rna_index, bAction **r_action, bool *r_driven)
bool BKE_idtype_idcode_is_linkable(short idcode)
Definition idtype.cc:201
Key ** BKE_key_from_id_p(ID *id)
Definition key.cc:1775
Key * BKE_key_from_id(ID *id)
Definition key.cc:1800
bool BKE_view_layer_has_collection(const ViewLayer *view_layer, const Collection *collection)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_layer_collection_resync_forbid()
void BKE_scene_view_layers_synced_ensure(const Scene *scene)
void BKE_main_collection_sync_remap(const Main *bmain)
void BKE_layer_collection_resync_allow()
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void BKE_main_collection_sync(const Main *bmain)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
void BKE_main_view_layers_synced_ensure(const Main *bmain)
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
void size_t BKE_id_multi_tagged_delete(Main *bmain) ATTR_NONNULL()
@ LIB_ID_COPY_NO_LIB_OVERRIDE
@ LIB_ID_COPY_NO_LIB_OVERRIDE_LOCAL_DATA_FLAG
@ LIB_ID_CREATE_NO_MAIN
@ LIB_ID_COPY_DEFAULT
void BKE_id_free(Main *bmain, void *idv)
void id_us_plus(ID *id)
Definition lib_id.cc:351
void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
Definition lib_id.cc:1737
void id_fake_user_set(ID *id)
Definition lib_id.cc:389
void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_self_remap, const int self_remap_flags)
Definition lib_id.cc:1022
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:1947
ID * BKE_id_owner_get(ID *id, const bool debug_relationship_assert=true)
Definition lib_id.cc:2444
struct ID * BKE_id_copy_in_lib(Main *bmain, std::optional< Library * > owner_library, const ID *id, const ID *new_owner_id, ID **new_id_p, int flag)
Definition lib_id.cc:656
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:760
ID * BKE_id_copy(Main *bmain, const ID *id)
Definition lib_id.cc:765
@ LIB_ID_FREE_NO_UI_USER
@ LIB_ID_FREE_NO_NAMEMAP_REMOVE
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
void id_us_min(ID *id)
Definition lib_id.cc:359
void BKE_id_free_ex(Main *bmain, void *idv, int flag_orig, bool use_flag_from_idtag)
void BKE_libblock_management_main_add(Main *bmain, void *idv)
Definition lib_id.cc:1097
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1198
@ IDWALK_RET_STOP_ITER
@ IDWALK_RET_NOP
void BKE_lib_query_unused_ids_tag(Main *bmain, int tag, LibQueryUnusedIDsData &parameters)
Definition lib_query.cc:962
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE
@ IDWALK_CB_OVERRIDE_LIBRARY_HIERARCHY_DEFAULT
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, int flag)
Definition lib_query.cc:416
@ IDWALK_READONLY
@ ID_REMAP_SKIP_OVERRIDE_LIBRARY
@ ID_REMAP_FORCE_USER_REFCOUNT
@ ID_REMAP_SKIP_INDIRECT_USAGE
@ ID_REMAP_FORCE_NEVER_NULL_USAGE
void BKE_libblock_relink_multiple(Main *bmain, const blender::Span< ID * > ids, eIDRemapType remap_type, blender::bke::id::IDRemapper &id_remapper, int remap_flags)
Definition lib_remap.cc:782
@ ID_REMAP_TYPE_REMAP
@ ID_REMAP_TYPE_CLEANUP
void BKE_libblock_remap_multiple(Main *bmain, blender::bke::id::IDRemapper &mappings, const int remap_flags)
Definition lib_remap.cc:701
void BKE_libblock_relink_ex(Main *bmain, void *idv, void *old_idv, void *new_idv, int remap_flags) ATTR_NONNULL(2)
Definition lib_remap.cc:844
void void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, int remap_flags) ATTR_NONNULL(1
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:500
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:842
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:469
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:463
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:481
eMainIDRelationsEntryTags
Definition BKE_main.hh:79
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO
Definition BKE_main.hh:85
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED
Definition BKE_main.hh:90
@ MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS
Definition BKE_main.hh:101
@ MAINIDRELATIONS_ENTRY_TAGS_DOIT
Definition BKE_main.hh:81
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_FROM
Definition BKE_main.hh:88
void BKE_main_relations_tag_set(Main *bmain, eMainIDRelationsEntryTags tag, bool value)
Definition main.cc:592
Main * BKE_main_new(void)
Definition main.cc:45
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:474
void BKE_main_free(Main *bmain)
Definition main.cc:175
void BKE_main_relations_create(Main *bmain, short flag)
Definition main.cc:544
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:494
void BKE_main_relations_free(Main *bmain)
Definition main.cc:580
void BKE_main_namemap_destroy(UniqueName_Map **r_name_map) ATTR_NONNULL()
bool BKE_main_namemap_get_name(Main *bmain, ID *id, char *name, const bool do_unique_in_bmain) ATTR_NONNULL()
void BKE_main_namemap_remove_name(Main *bmain, ID *id, const char *name) ATTR_NONNULL()
bool BKE_main_namemap_validate(Main *bmain) ATTR_NONNULL()
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define ATTR_FALLTHROUGH
#define BLI_INLINE
struct GSet GSet
Definition BLI_ghash.h:341
bool BLI_ghashutil_strcmp(const void *a, const void *b)
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:299
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:819
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition BLI_ghash.c:911
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:855
unsigned int BLI_ghashutil_ptrhash(const void *key)
void BLI_ghashIterator_free(GHashIterator *ghi)
Definition BLI_ghash.c:925
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:303
#define GHASH_ITER(gh_iter_, ghash_)
Definition BLI_ghash.h:322
void * BLI_gset_lookup(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:1058
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:686
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
GHashIterator * BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:888
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:745
void * BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:802
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
unsigned int BLI_ghashutil_strhash_p_murmur(const void *ptr)
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:787
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.c:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:1034
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:752
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:311
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
void BLI_insertlinkreplace(ListBase *listbase, void *vreplacelink, void *vnewlink) ATTR_NONNULL(1
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_listbase_findafter_string_ptr(struct Link *link, const char *id, const int offset)
Definition listbase.cc:671
void * BLI_listbase_bytes_find(const ListBase *listbase, const void *bytes, size_t bytes_size, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
void * BLI_findstring_ptr(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
@ TASK_PRIORITY_HIGH
Definition BLI_task.h:57
void * BLI_task_pool_user_data(TaskPool *pool)
Definition task_pool.cc:516
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition task_pool.cc:471
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition task_pool.cc:394
void BLI_task_pool_free(TaskPool *pool)
Definition task_pool.cc:431
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition task_pool.cc:450
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.c:65
Utility defines for timing/benchmarks.
#define TIMEIT_START_AVERAGED(var)
#define TIMEIT_END_AVERAGED(var)
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
#define STREQ(a, b)
external readfile function prototypes.
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_id_tag_update_ex(Main *bmain, ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
ID and Library types, which are fundamental for SDNA.
#define ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id)
Definition DNA_ID.h:680
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SELECT
Definition DNA_ID.h:1068
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_RECALC_ALL
Definition DNA_ID.h:1155
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1071
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:676
@ LIBOVERRIDE_PROP_TAG_NEEDS_RETORE
Definition DNA_ID.h:296
@ LIBOVERRIDE_PROP_OP_TAG_UNUSED
Definition DNA_ID.h:293
@ LIBOVERRIDE_TAG_NEEDS_RESTORE
Definition DNA_ID.h:315
@ LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT
Definition DNA_ID.h:321
@ LIBOVERRIDE_TAG_NEEDS_RELOAD
Definition DNA_ID.h:309
@ LIBOVERRIDE_TAG_NEED_RESYNC_ORIGINAL
Definition DNA_ID.h:327
@ LIBOVERRIDE_OP_FLAG_IDPOINTER_ITEM_USE_ID
Definition DNA_ID.h:261
@ LIBOVERRIDE_OP_FLAG_IDPOINTER_MATCH_REFERENCE
Definition DNA_ID.h:255
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define MAX_ID_NAME
Definition DNA_ID.h:377
@ ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE
Definition DNA_ID.h:736
@ ID_FLAG_LIB_OVERRIDE_RESYNC_LEFTOVER
Definition DNA_ID.h:741
@ LIBOVERRIDE_OP_NOOP
Definition DNA_ID.h:227
@ LIBOVERRIDE_OP_ADD
Definition DNA_ID.h:232
@ LIBOVERRIDE_OP_SUBTRACT
Definition DNA_ID.h:234
@ LIBOVERRIDE_OP_REPLACE
Definition DNA_ID.h:229
@ LIBOVERRIDE_OP_MULTIPLY
Definition DNA_ID.h:236
@ LIBOVERRIDE_OP_INSERT_BEFORE
Definition DNA_ID.h:240
@ LIBOVERRIDE_OP_INSERT_AFTER
Definition DNA_ID.h:239
@ ID_TAG_NO_USER_REFCOUNT
Definition DNA_ID.h:985
@ ID_TAG_LIBOVERRIDE_AUTOREFRESH
Definition DNA_ID.h:843
@ ID_TAG_INDIRECT
Definition DNA_ID.h:794
@ ID_TAG_MISSING
Definition DNA_ID.h:813
@ ID_TAG_DOIT
Definition DNA_ID.h:1003
@ ID_TAG_LIBOVERRIDE_NEED_RESYNC
Definition DNA_ID.h:852
@ ID_TAG_LIBOVERRIDE_REFOK
Definition DNA_ID.h:837
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:945
@ LIBOVERRIDE_FLAG_NO_HIERARCHY
Definition DNA_ID.h:362
@ LIBOVERRIDE_FLAG_SYSTEM_DEFINED
Definition DNA_ID.h:367
@ INDEX_ID_NULL
Definition DNA_ID.h:1325
#define ID_REAL_USERS(id)
Definition DNA_ID.h:637
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:683
@ LIBRARY_TAG_RESYNC_REQUIRED
Definition DNA_ID.h:541
#define ID_MISSING(_id)
Definition DNA_ID.h:652
@ ID_AR
@ ID_NT
@ ID_KE
@ ID_SCE
@ ID_GR
@ ID_OB
@ POSE_RECALC
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_RENDER
@ COLLECTION_HIDE_VIEWPORT
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
#define OB_DATA_SUPPORT_ID(_id_type)
@ OB_ARMATURE
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
eRNAOverrideApplyFlag
@ RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS
@ RNA_OVERRIDE_APPLY_FLAG_SKIP_RESYNC_CHECK
@ RNA_OVERRIDE_APPLY_FLAG_NOP
@ RNA_OVERRIDE_APPLY_FLAG_RESTORE_ONLY
eRNAOverrideMatch
@ RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN
@ RNA_OVERRIDE_COMPARE_CREATE
@ RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE
@ RNA_OVERRIDE_COMPARE_RESTORE
@ RNA_OVERRIDE_COMPARE_TAG_FOR_RESTORE
eRNAOverrideMatchResult
@ RNA_OVERRIDE_MATCH_RESULT_RESTORED
@ RNA_OVERRIDE_MATCH_RESULT_RESTORE_TAGGED
@ RNA_OVERRIDE_MATCH_RESULT_CREATED
@ RNA_OVERRIDE_MATCH_RESULT_INIT
@ PROP_POINTER
Definition RNA_types.hh:70
@ PROP_COLLECTION
Definition RNA_types.hh:71
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE uint32_t atomic_fetch_and_or_uint32(uint32_t *p, uint32_t x)
bool contains(const Key &key) const
Definition BLI_set.hh:291
bool add(const Key &key)
Definition BLI_set.hh:248
void clear()
Definition BLI_set.hh:532
bool remove(const Key &key)
Definition BLI_set.hh:366
void append(const T &value)
void add(ID *old_id, ID *new_id)
#define offsetof(t, d)
TaskPool * task_pool
#define GS(x)
Definition iris.cc:202
void lib_id_copy_ensure_local(Main *bmain, const ID *old_id, ID *new_id, const int flags)
Definition lib_id.cc:480
void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
void BKE_lib_override_library_main_tag(Main *bmain, const short tag, const bool do_set)
static bool lib_override_library_main_resync_on_library_indirect_level(Main *bmain, Scene *scene, ViewLayer *view_layer, Collection *override_resync_residual_storage, const int library_indirect_level, BlendFileReadReport *reports)
static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTagData *data)
static void lib_override_library_create_post_process(Main *bmain, Scene *scene, ViewLayer *view_layer, const Library *owner_library, ID *id_root, ID *id_instance_hint, Collection *residual_storage, const Object *old_active_object, const bool is_resync)
static LibOverrideMissingIDsData_Key lib_override_library_resync_missing_id_key(ID *id)
static bool lib_override_resync_id_lib_level_is_valid(ID *id, const int library_indirect_level, const bool do_strict_equal)
static void lib_override_library_property_clear(IDOverrideLibraryProperty *op)
static void lib_override_resync_tagging_finalize(Main *bmain, GHash *id_roots, const int library_indirect_level)
static bool override_library_is_valid(const ID &id, const IDOverrideLibrary &liboverride, ReportList *reports)
BLI_INLINE GHash * override_library_rna_path_mapping_ensure(IDOverrideLibrary *liboverride)
std::map< LibOverrideMissingIDsData_Key, LibOverrideMissingIDsData_Value > LibOverrideMissingIDsData
static void lib_override_group_tag_data_object_to_collection_init_collection_process(LibOverrideGroupTagData *data, Collection *collection)
static void lib_override_group_tag_data_object_to_collection_init(LibOverrideGroupTagData *data)
static void lib_override_hierarchy_dependencies_recursive_tag_from(LibOverrideGroupTagData *data)
static IDOverrideLibraryPropertyOperation * liboverride_opop_find_name_lib_iterative(ListBase *liboverride_operations, const char *subitem_main_name, const char *subitem_other_name, const std::optional< const ID * > &subitem_main_id, const std::optional< const ID * > &subitem_other_id, const size_t offesetof_opop_main_name, const size_t offesetof_opop_other_name, const size_t offesetof_opop_main_id, const size_t offesetof_opop_other_id)
bool BKE_lib_override_library_property_rna_path_change(IDOverrideLibrary *liboverride, const char *old_rna_path, const char *new_rna_path)
void BKE_lib_override_library_property_operation_delete(IDOverrideLibraryProperty *liboverride_property, IDOverrideLibraryPropertyOperation *liboverride_property_operation)
void BKE_lib_override_library_main_validate(Main *bmain, ReportList *reports)
IDOverrideLibraryProperty * BKE_lib_override_library_property_find(IDOverrideLibrary *liboverride, const char *rna_path)
static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *data)
static ID * lib_override_root_find(Main *bmain, ID *id, const int curr_level, int *r_best_level)
IDOverrideLibraryPropertyOperation * BKE_lib_override_library_property_operation_get(IDOverrideLibraryProperty *liboverride_property, const short operation, const char *subitem_refname, const char *subitem_locname, const std::optional< ID * > &subitem_refid, const std::optional< ID * > &subitem_locid, const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict, bool *r_created)
void BKE_lib_override_library_main_operations_create(Main *bmain, const bool force_auto, int *r_report_flags)
void BKE_lib_override_library_main_operations_restore(Main *bmain, int *r_report_flags)
void BKE_lib_override_library_properties_tag(IDOverrideLibrary *liboverride, const short tag, const bool do_set)
void BKE_lib_override_debug_print(IDOverrideLibrary *liboverride, const char *intro_txt)
bool BKE_lib_override_library_id_is_user_deletable(Main *bmain, ID *id)
IDOverrideLibraryProperty * BKE_lib_override_library_property_get(IDOverrideLibrary *liboverride, const char *rna_path, bool *r_created)
static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
OverrideLibraryStorage * BKE_lib_override_library_operations_store_init()
bool BKE_lib_override_library_property_is_animated(const ID *id, const IDOverrideLibraryProperty *liboverride_prop, const PropertyRNA *override_rna_prop, const int rnaprop_index)
static LibOverrideMissingIDsData lib_override_library_resync_build_missing_ids_data(Main *bmain)
#define OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME
void BKE_lib_override_id_tag_on_deg_tag_from_user(ID *id)
bool BKE_lib_override_library_property_search_and_delete(IDOverrideLibrary *liboverride, const char *rna_path)
static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID *id_from, blender::Set< ID * > &processed_ids)
static void lib_override_library_operations_create(Main *bmain, ID *local, const eRNAOverrideMatch liboverride_match_flags, eRNAOverrideMatchResult *r_report_flags)
bool BKE_lib_override_library_property_operation_operands_validate(IDOverrideLibraryPropertyOperation *liboverride_property_operation, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, PropertyRNA *prop_dst, PropertyRNA *prop_src, PropertyRNA *prop_storage)
static void lib_override_library_property_operation_copy(IDOverrideLibraryPropertyOperation *opop_dst, IDOverrideLibraryPropertyOperation *opop_src)
bool BKE_lib_override_library_status_check_reference(Main *bmain, ID *local)
void BKE_lib_override_library_update(Main *bmain, ID *local)
void BKE_lib_override_library_operations_restore(Main *bmain, ID *local, int *r_report_flags)
std::deque< ID * > LibOverrideMissingIDsData_Value
static void lib_override_id_swap(Main *bmain, ID *id_local, ID *id_temp)
static void lib_override_cleanup_after_resync(Main *bmain)
BLI_INLINE IDOverrideLibraryRuntime * override_library_runtime_ensure(IDOverrideLibrary *liboverride)
void BKE_lib_override_library_clear(IDOverrideLibrary *liboverride, const bool do_id_user)
void BKE_lib_override_library_id_unused_cleanup(ID *local)
static void lib_override_library_operations_create_cb(TaskPool *__restrict pool, void *taskdata)
static bool lib_override_library_create_do(Main *bmain, Scene *scene, Library *owner_library, ID *id_root_reference, ID *id_hierarchy_root_reference, const bool do_fully_editable)
void BKE_lib_override_library_main_resync(Main *bmain, Scene *scene, ViewLayer *view_layer, BlendFileReadReport *reports)
static void lib_override_resync_tagging_finalize_recurse(Main *bmain, ID *id_root, ID *id_from, const int library_indirect_level, bool is_in_partial_resync_hierarchy)
bool BKE_lib_override_library_create(Main *bmain, Scene *scene, ViewLayer *view_layer, Library *owner_library, ID *id_root_reference, ID *id_hierarchy_root_reference, ID *id_instance_hint, ID **r_id_root_override, const bool do_fully_editable)
static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root, const bool do_reset_system_override)
bool BKE_lib_override_library_is_user_edited(const ID *id)
ID * BKE_lib_override_library_operations_store_start(Main *bmain, OverrideLibraryStorage *liboverride_storage, ID *local)
static CLG_LogRef LOG_RESYNC
IDOverrideLibraryPropertyOperation * BKE_lib_override_library_property_operation_find(IDOverrideLibraryProperty *liboverride_property, const char *subitem_refname, const char *subitem_locname, const std::optional< const ID * > &subitem_refid, const std::optional< const ID * > &subitem_locid, const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict)
static void lib_override_remapper_overrides_add(id::IDRemapper &id_remapper, ID *reference_id, ID *local_id)
void BKE_lib_override_library_operations_store_finalize(OverrideLibraryStorage *liboverride_storage)
bool BKE_lib_override_library_create_from_tag(Main *bmain, Library *owner_library, const ID *id_root_reference, ID *id_hierarchy_root, const ID *id_hierarchy_root_reference, const bool do_no_main, const bool do_fully_editable)
void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root, const bool do_reset_system_override)
bool BKE_lib_override_rna_property_find(PointerRNA *idpoin, const IDOverrideLibraryProperty *library_prop, PointerRNA *r_override_poin, PropertyRNA **r_override_prop, int *r_index)
void BKE_lib_override_library_operations_store_end(OverrideLibraryStorage *, ID *local)
bool BKE_lib_override_library_status_check_local(Main *bmain, ID *local)
static void lib_override_linked_group_tag_clear_boneshapes_objects(LibOverrideGroupTagData *data)
void BKE_lib_override_library_operations_create(Main *bmain, ID *local, int *r_report_flags)
static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *id_root, const bool do_reset_system_override)
bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root, Collection *override_resync_residual_storage, const bool do_hierarchy_enforce, BlendFileReadReport *reports)
static void lib_override_library_property_delete(IDOverrideLibrary *liboverride, IDOverrideLibraryProperty *liboverride_property, const bool do_runtime_updates)
static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
static bool lib_override_hierarchy_dependencies_skip_check(ID *owner_id, ID *other_id, const bool check_override)
void BKE_lib_override_library_make_local(Main *bmain, ID *id)
static bool lib_override_linked_group_tag_collections_keep_tagged_check_recursive(LibOverrideGroupTagData *data, Collection *collection)
IDOverrideLibrary * BKE_lib_override_library_init(ID *local_id, ID *reference_id)
void BKE_lib_override_library_validate(Main *bmain, ID *id, ReportList *reports)
BLI_INLINE void lib_override_object_posemode_transfer(ID *id_dst, ID *id_src)
const std::pair< std::string, Library * > LibOverrideMissingIDsData_Key
static bool lib_override_hierarchy_dependencies_relationship_skip_check(MainIDRelationsEntryItem *relation_id_entry)
static bool lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_layer, ID *id_root, LinkNode *id_resync_roots, ListBase *no_main_ids_list, Collection *override_resync_residual_storage, const bool do_hierarchy_enforce, const bool do_post_process, BlendFileReadReport *reports)
static void lib_override_library_remap(Main *bmain, const ID *id_root_reference, blender::Vector< std::pair< ID *, ID * > > &references_and_new_overrides, GHash *linkedref_to_old_override)
void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
static bool lib_override_library_main_resync_id_skip_check(ID *id, const int library_indirect_level)
bool BKE_lib_override_library_is_hierarchy_leaf(Main *bmain, ID *id)
static CLG_LogRef LOG
static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *data)
static int foreachid_is_hierarchy_leaf_fn(LibraryIDLinkCallbackData *cb_data)
static ID * lib_override_library_resync_search_missing_ids_data(LibOverrideMissingIDsData &missing_ids, ID *id_override)
void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root, const bool do_reset_system_override)
void BKE_lib_override_library_property_delete(IDOverrideLibrary *liboverride, IDOverrideLibraryProperty *liboverride_property)
static void lib_override_library_property_operation_clear(IDOverrideLibraryPropertyOperation *opop)
void BKE_lib_override_library_main_update(Main *bmain)
void BKE_lib_override_library_main_unused_cleanup(Main *bmain)
static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
ID * BKE_lib_override_library_create_from_id(Main *bmain, ID *reference_id, const bool do_tagged_remap)
#define HIERARCHY_BREAKING_ID_TYPES
static ID * lib_override_library_create_from(Main *bmain, Library *owner_library, ID *reference_id, const int lib_id_copy_flags)
void BKE_lib_override_library_operations_tag(IDOverrideLibraryProperty *liboverride_property, const short tag, const bool do_set)
void BKE_lib_override_library_free(IDOverrideLibrary **liboverride, const bool do_id_user)
BLI_INLINE const IDOverrideLibrary * BKE_lib_override_library_get(const Main *, const ID *id, const ID *, const ID **r_owner_id)
static void lib_override_prefill_newid_from_existing_overrides(Main *bmain, ID *id_hierarchy_root)
void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_full_copy)
static int lib_override_libraries_index_define(Main *bmain)
static bool lib_override_resync_tagging_finalize_recursive_check_from(Main *bmain, ID *id, const int library_indirect_level)
static void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst, IDOverrideLibraryProperty *op_src)
double parameters[NUM_PARAMETERS]
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
bNodeTree * node_tree_from_id(ID *id)
Definition node.cc:3732
bool RNA_struct_is_ID(const StructRNA *type)
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
PropertyType RNA_property_type(PropertyRNA *prop)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create(ID *id, StructRNA *type, void *data)
PointerRNA RNA_id_pointer_create(ID *id)
bool RNA_struct_override_store(Main *bmain, PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage, IDOverrideLibrary *liboverride)
void RNA_struct_override_apply(Main *bmain, PointerRNA *id_ptr_dst, PointerRNA *id_ptr_src, PointerRNA *id_ptr_storage, IDOverrideLibrary *liboverride, const eRNAOverrideApplyFlag flag)
bool RNA_struct_override_matches(Main *bmain, PointerRNA *ptr_local, PointerRNA *ptr_reference, const char *root_path, const size_t root_path_len, IDOverrideLibrary *liboverride, const eRNAOverrideMatch flags, eRNAOverrideMatchResult *r_report_flags)
const char * RNA_path_array_index_token_find(const char *rna_path, const PropertyRNA *array_prop)
Definition rna_path.cc:715
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:553
bool RNA_path_resolve_property_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition rna_path.cc:565
unsigned int uint32_t
Definition stdint.h:80
LinkNode * resynced_lib_overrides_libraries
double lib_overrides_recursive_resync
bool do_resynced_lib_overrides_libraries_list
int resynced_lib_overrides_libraries_count
struct BlendFileReadReport::@127 duration
struct BlendFileReadReport::@128 count
struct CollectionChild * next
struct IDOverrideLibraryProperty * next
Definition DNA_ID.h:266
struct GHash * rna_path_to_override_properties
Definition DNA_ID.h:302
struct ID * storage
Definition DNA_ID.h:348
ListBase properties
Definition DNA_ID.h:335
unsigned int flag
Definition DNA_ID.h:352
struct ID * hierarchy_root
Definition DNA_ID.h:343
struct ID * reference
Definition DNA_ID.h:333
IDOverrideLibraryRuntime * runtime
Definition DNA_ID.h:350
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
struct Library * lib
Definition DNA_ID.h:419
struct ID * newid
Definition DNA_ID.h:417
IDOverrideLibrary * override_library
Definition DNA_ID.h:459
short flag
Definition DNA_ID.h:430
void * next
Definition DNA_ID.h:416
char name[66]
Definition DNA_ID.h:425
ID * from
bool id_tag_clear(ID *id, const bool is_missing)
blender::Set< ID * > linked_ids_hierarchy_default_override
void root_set(ID *id_root)
void hierarchy_root_set(ID *hierarchy_root_id)
GHash * linked_object_to_instantiating_collections
bool id_tag_set(ID *id, const bool is_missing)
eRNAOverrideMatchResult report_flags
char filepath[1024]
Definition DNA_ID.h:531
struct Library_Runtime runtime
Definition DNA_ID.h:535
void * data
struct LinkData * next
LinkNode * last_node
LinkNode * list
void * link
struct LinkNode * next
void * first
MainIDRelationsEntryItem * from_ids
Definition BKE_main.hh:67
MainIDRelationsEntryItem * to_ids
Definition BKE_main.hh:69
GHash * relations_from_pointers
Definition BKE_main.hh:108
UniqueName_Map * name_map_global
Definition BKE_main.hh:270
ListBase libraries
Definition BKE_main.hh:211
ListBase collections
Definition BKE_main.hh:231
MainIDRelations * relations
Definition BKE_main.hh:260
ListBase objects
Definition BKE_main.hh:212
struct Object * parent
ID * owner_id
Definition RNA_types.hh:40
StructRNA * type
Definition RNA_types.hh:41
void * data
Definition RNA_types.hh:42
struct Base * basact
ccl_device_inline bool is_leaf(const ccl_global KernelLightTreeNode *knode)
Definition tree.h:79
PointerRNA * ptr
Definition wm_files.cc:4126