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