Blender V5.0
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 = {"lib.override"};
83static CLG_LogRef LOG_RESYNC = {"lib.override.resync"};
84
86
88{
89 return !USER_DEVELOPER_TOOL_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_root)) {
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 {
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_DEBUG(&LOG,
1937 "Modifying library override hierarchy of ID '%s'.\n"
1938 "\tFrom old root '%s' to new root '%s'.",
1939 id->name,
1940 id->override_library->hierarchy_root ? id->override_library->hierarchy_root->name :
1941 "<NONE>",
1942 id_root->name);
1943
1944 id->override_library->hierarchy_root = id_root;
1945 }
1946
1947 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
1949 BLI_assert(entry != nullptr);
1950
1951 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
1952 to_id_entry = to_id_entry->next)
1953 {
1955 continue;
1956 }
1957 ID *to_id = *to_id_entry->id_pointer.to;
1959 continue;
1960 }
1961
1962 /* Recursively process the sub-hierarchy. */
1963 lib_override_root_hierarchy_set(bmain, id_root, to_id, id, processed_ids);
1964 }
1965}
1966
1968 ID *id,
1969 blender::Set<ID *> &processed_ids)
1970{
1972
1973 if (id->override_library->hierarchy_root != nullptr) {
1974 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id->override_library->hierarchy_root) ||
1975 id->override_library->hierarchy_root->lib != id->lib)
1976 {
1977 CLOG_ERROR(
1978 &LOG,
1979 "Existing override hierarchy root ('%s') for ID '%s' is invalid, will try to find a "
1980 "new valid one",
1981 id->override_library->hierarchy_root != nullptr ?
1982 id->override_library->hierarchy_root->name :
1983 "<NONE>",
1984 id->name);
1985 id->override_library->hierarchy_root = nullptr;
1986 }
1987 else if (!lib_override_root_is_valid(bmain, id)) {
1988 /* Serious invalid cases (likely resulting from bugs or invalid operations) should have
1989 * been caught by the first check above. Invalid hierarchy roots detected here can happen
1990 * in normal situations, e.g. when breaking a hierarchy by making one of its components
1991 * local. See also #137412. */
1992 CLOG_DEBUG(
1993 &LOG,
1994 "Existing override hierarchy root ('%s') for ID '%s' is invalid, will try to find a "
1995 "new valid one",
1996 id->override_library->hierarchy_root != nullptr ?
1997 id->override_library->hierarchy_root->name :
1998 "<NONE>",
1999 id->name);
2000 id->override_library->hierarchy_root = nullptr;
2001 }
2002 else {
2003 /* This ID is considered as having a valid hierarchy root. */
2004 processed_ids.add(id);
2005 return;
2006 }
2007 }
2008
2011
2012 int best_level = 0;
2013 ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
2014
2015 if (!ELEM(id->override_library->hierarchy_root, id_root, nullptr)) {
2016 /* In case the detected hierarchy root does not match with the currently defined one, this is
2017 * likely an issue and is worth a warning. */
2018 CLOG_WARN(&LOG,
2019 "Potential inconsistency in library override hierarchy of ID '%s' (current root "
2020 "%s), detected as part of the hierarchy of '%s' (current root '%s')",
2021 id->name,
2022 id->override_library->hierarchy_root != nullptr ?
2023 id->override_library->hierarchy_root->name :
2024 "<NONE>",
2025 id_root->name,
2026 id_root->override_library->hierarchy_root != nullptr ?
2028 "<NONE>");
2029 processed_ids.add(id);
2030 return;
2031 }
2032
2033 lib_override_root_hierarchy_set(bmain, id_root, id, nullptr, processed_ids);
2034
2035 BLI_assert(id->override_library->hierarchy_root != nullptr);
2036}
2037
2039{
2040 ID *id;
2041
2042 BKE_main_relations_create(bmain, 0);
2043 blender::Set<ID *> processed_ids;
2044
2045 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2046 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
2047 processed_ids.add(id);
2048 continue;
2049 }
2050
2052 }
2054
2056}
2057
2059 Main *bmain,
2060 const ID *id_root_reference,
2061 blender::Vector<std::pair<ID *, ID *>> &references_and_new_overrides,
2062 GHash *linkedref_to_old_override)
2063{
2064 id::IDRemapper remapper_overrides_old_to_new;
2065 blender::Vector<ID *> nomain_ids;
2066 blender::Vector<ID *> new_overrides;
2067
2068 /* Used to ensure that newly created overrides have all of their 'linked id' pointers remapped to
2069 * the matching override if it exists. Necessary because in partial resync case, some existing
2070 * liboverride may be used by the resynced ones, yet they would not be part of the resynced
2071 * partial hierarchy, so #BKE_lib_override_library_create_from_tag cannot find them and handle
2072 * their remapping. */
2073 id::IDRemapper remapper_overrides_reference_to_old;
2074
2075 /* Add remapping from old to new overrides. */
2076 for (auto [id_reference, id_override_new] : references_and_new_overrides) {
2077 new_overrides.append(id_override_new);
2078 ID *id_override_old = static_cast<ID *>(
2079 BLI_ghash_lookup(linkedref_to_old_override, id_reference));
2080 if (id_override_old == nullptr) {
2081 continue;
2082 }
2083 remapper_overrides_old_to_new.add(id_override_old, id_override_new);
2084 }
2085
2086 GHashIterator linkedref_to_old_override_iter;
2087 GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) {
2088 /* Remap no-main override IDs we just created too. */
2089 ID *id_override_old_iter = static_cast<ID *>(
2090 BLI_ghashIterator_getValue(&linkedref_to_old_override_iter));
2091 if ((id_override_old_iter->tag & ID_TAG_NO_MAIN) != 0) {
2092 nomain_ids.append(id_override_old_iter);
2093 }
2094 /* And remap linked data to old (existing, unchanged) overrides, when no new one was created.
2095 */
2096 ID *id_reference_iter = static_cast<ID *>(
2097 BLI_ghashIterator_getKey(&linkedref_to_old_override_iter));
2098
2099 /* NOTE: Usually `id_reference_iter->lib == id_root_reference->lib` should always be true.
2100 * However, there are some cases where it is not, e.g. if the linked reference of a liboverride
2101 * is relocated to another ID in another library. */
2102#if 0
2103 BLI_assert(id_reference_iter->lib == id_root_reference->lib);
2104 UNUSED_VARS_NDEBUG(id_root_reference);
2105#else
2106 UNUSED_VARS(id_root_reference);
2107#endif
2108 if (!id_reference_iter->newid) {
2109 remapper_overrides_reference_to_old.add(id_reference_iter, id_override_old_iter);
2110 }
2111 }
2112
2113 /* Remap all IDs to use the new override. */
2114 BKE_libblock_remap_multiple(bmain, remapper_overrides_old_to_new, 0);
2116 nomain_ids,
2118 remapper_overrides_old_to_new,
2120 /* In new overrides, remap linked ID to their matching already existing overrides. */
2122 new_overrides,
2124 remapper_overrides_reference_to_old,
2126}
2127
2147
2148using LibOverrideMissingIDsData_Key = const std::pair<std::string, Library *>;
2149using LibOverrideMissingIDsData_Value = std::deque<ID *>;
2151 std::map<LibOverrideMissingIDsData_Key, LibOverrideMissingIDsData_Value>;
2152
2153/* Return a key suitable for the missing IDs mapping, i.e. a pair of
2154 * `<full ID name (including first two ID type chars) without a potential numeric extension,
2155 * ID library>`.
2156 *
2157 * So e.g. returns `<"OBMyObject", lib>` for ID from `lib` with names like `"OBMyObject"`,
2158 * `"OBMyObject.002"`, `"OBMyObject.12345"`, and so on, but _not_ `"OBMyObject.12.002"`.
2159 */
2161{
2162 std::string id_name_key(id->name);
2163 const size_t last_key_index = id_name_key.find_last_not_of("0123456789");
2164
2165 BLI_assert(last_key_index != std::string::npos);
2166
2167 if (id_name_key[last_key_index] == '.') {
2168 id_name_key.resize(last_key_index);
2169 }
2170
2171 return LibOverrideMissingIDsData_Key(id_name_key, id->lib);
2172}
2173
2175 Main *bmain, const bool is_relocate)
2176{
2177 LibOverrideMissingIDsData missing_ids;
2178 ID *id_iter;
2179 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2180 if (is_relocate) {
2181 if (!ID_IS_OVERRIDE_LIBRARY(id_iter)) {
2182 continue;
2183 }
2184 const int required_tags = ID_TAG_LIBOVERRIDE_NEED_RESYNC;
2185 if ((id_iter->tag & required_tags) != required_tags) {
2186 continue;
2187 }
2188 }
2189 else { /* Handling of missing linked liboverrides. */
2190 if (!ID_IS_LINKED(id_iter)) {
2191 continue;
2192 }
2193 const int required_tags = (ID_TAG_MISSING | ID_TAG_LIBOVERRIDE_NEED_RESYNC);
2194 if ((id_iter->tag & required_tags) != required_tags) {
2195 continue;
2196 }
2197 }
2198
2200 std::pair<LibOverrideMissingIDsData::iterator, bool> value = missing_ids.try_emplace(
2202 value.first->second.push_back(id_iter);
2203 }
2205
2206 return missing_ids;
2207}
2208
2210 LibOverrideMissingIDsData &missing_ids, ID *id_override)
2211{
2213 const LibOverrideMissingIDsData::iterator value = missing_ids.find(key);
2214 if (value == missing_ids.end()) {
2215 return nullptr;
2216 }
2217 if (value->second.empty()) {
2218 return nullptr;
2219 }
2220 ID *match_id = value->second.front();
2221 value->second.pop_front();
2222 return match_id;
2223}
2224
2226 Main *bmain,
2227 const blender::Map<Library *, Library *> *new_to_old_libraries_map,
2228 Scene *scene,
2229 ViewLayer *view_layer,
2230 ID *id_root,
2231 LinkNode *id_resync_roots,
2232 ListBase *no_main_ids_list,
2233 Collection *override_resync_residual_storage,
2234 const bool do_hierarchy_enforce,
2235 const bool do_post_process,
2236 BlendFileReadReport *reports)
2237{
2239
2240 ID *id_root_reference = id_root->override_library->reference;
2241 ID *id;
2242
2243 const Object *old_active_object = nullptr;
2244 if (view_layer) {
2245 BKE_view_layer_synced_ensure(scene, view_layer);
2246 old_active_object = BKE_view_layer_active_object_get(view_layer);
2247 }
2248 else {
2250 }
2251
2252 if (id_root_reference->tag & ID_TAG_MISSING) {
2253 BKE_reportf(reports != nullptr ? reports->reports : nullptr,
2254 RPT_ERROR,
2255 "Impossible to resync data-block %s and its dependencies, as its linked reference "
2256 "is missing",
2257 id_root->name + 2);
2258 return false;
2259 }
2260
2261 BKE_main_relations_create(bmain, 0);
2263 data.bmain = bmain;
2264 data.scene = scene;
2265 data.tag = ID_TAG_DOIT;
2266 data.missing_tag = ID_TAG_MISSING;
2267 data.is_override = true;
2268 data.is_resync = true;
2269
2270 data.root_set(id_root);
2271 data.hierarchy_root_set(id_root->override_library->hierarchy_root);
2272
2274
2275 /* Mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, populated from
2276 * each sub-tree that actually needs to be resynced. */
2277 GHash *linkedref_to_old_override = BLI_ghash_new(
2279
2280 /* Only tag linked IDs from related linked reference hierarchy that are actually part of
2281 * the sub-trees of each detected sub-roots needing resync. */
2282 for (LinkNode *resync_root_link = id_resync_roots; resync_root_link != nullptr;
2283 resync_root_link = resync_root_link->next)
2284 {
2285 ID *id_resync_root = static_cast<ID *>(resync_root_link->link);
2286 BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_resync_root));
2287
2288 if ((id_resync_root->tag & ID_TAG_NO_MAIN) != 0) {
2290 "While dealing with root '%s', resync root ID '%s' (%p) found to be alreaady "
2291 "resynced.\n",
2292 id_root->name,
2293 id_resync_root->name,
2294 id_resync_root);
2295 }
2296 // if (no_main_ids_list && BLI_findindex(no_main_ids_list, id_resync_root) != -1) {
2297 // CLOG_ERROR(
2298 // &LOG,
2299 // "While dealing with root '%s', resync root ID '%s' found to be alreaady
2300 // resynced.\n", id_root->name, id_resync_root->name);
2301 // }
2302
2303 ID *id_resync_root_reference = id_resync_root->override_library->reference;
2304
2305 if (id_resync_root_reference->tag & ID_TAG_MISSING) {
2307 reports != nullptr ? reports->reports : nullptr,
2308 RPT_ERROR,
2309 "Impossible to resync data-block %s and its dependencies, as its linked reference "
2310 "is missing",
2311 id_root->name + 2);
2312 BLI_ghash_free(linkedref_to_old_override, nullptr, nullptr);
2314 data.clear();
2315 return false;
2316 }
2317
2318 /* Tag local overrides of the current resync sub-hierarchy. */
2320 data.is_override = true;
2321 data.root_set(id_resync_root);
2323
2324 /* Tag reference data matching the current resync sub-hierarchy. */
2326 data.is_override = false;
2327 data.root_set(id_resync_root->override_library->reference);
2328 data.hierarchy_root_set(
2331
2334
2335 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2336 if ((id->lib != id_root->lib) || !ID_IS_OVERRIDE_LIBRARY(id)) {
2337 continue;
2338 }
2339
2340 /* IDs that get fully removed from linked data remain as local overrides (using place-holder
2341 * linked IDs as reference), but they are often not reachable from any current valid local
2342 * override hierarchy anymore. This will ensure they get properly deleted at the end of this
2343 * function. */
2344 if (!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
2345 (id->override_library->reference->tag & ID_TAG_MISSING) != 0 &&
2346 /* Unfortunately deleting obdata means deleting their objects too. Since there is no
2347 * guarantee that a valid override object using an obsolete override obdata gets properly
2348 * updated, we ignore those here for now. In practice this should not be a big issue. */
2349 !OB_DATA_SUPPORT_ID(GS(id->name)))
2350 {
2351 id->tag |= ID_TAG_MISSING;
2352 }
2353
2354 /* While this should not happen in typical cases (and won't be properly supported here),
2355 * user is free to do all kind of very bad things, including having different local
2356 * overrides of a same linked ID in a same hierarchy. */
2357 IDOverrideLibrary *id_override_library = BKE_lib_override_library_get(
2358 bmain, id, nullptr, nullptr);
2359
2360 if (id_override_library->hierarchy_root != id_root->override_library->hierarchy_root) {
2361 continue;
2362 }
2363
2364 ID *reference_id = id_override_library->reference;
2365 if (GS(reference_id->name) != GS(id->name)) {
2366 switch (GS(id->name)) {
2367 case ID_KE:
2368 reference_id = reinterpret_cast<ID *>(BKE_key_from_id(reference_id));
2369 break;
2370 case ID_GR:
2371 BLI_assert(GS(reference_id->name) == ID_SCE);
2372 reference_id = reinterpret_cast<ID *>(
2373 reinterpret_cast<Scene *>(reference_id)->master_collection);
2374 break;
2375 case ID_NT:
2376 reference_id = reinterpret_cast<ID *>(blender::bke::node_tree_from_id(id));
2377 break;
2378 default:
2379 break;
2380 }
2381 }
2382 if (reference_id == nullptr) {
2383 /* Can happen e.g. when there is a local override of a shape-key, but the matching linked
2384 * obdata (mesh etc.) does not have any shape-key anymore. */
2385 continue;
2386 }
2387 BLI_assert(GS(reference_id->name) == GS(id->name));
2388
2389 if (!BLI_ghash_haskey(linkedref_to_old_override, reference_id)) {
2390 BLI_ghash_insert(linkedref_to_old_override, reference_id, id);
2391 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || (id->tag & ID_TAG_DOIT) == 0) {
2392 continue;
2393 }
2394 if ((id->override_library->reference->tag & ID_TAG_DOIT) == 0) {
2395 /* We have an override, but now it does not seem to be necessary to override that ID
2396 * anymore. Check if there are some actual overrides from the user, otherwise assume
2397 * that we can get rid of this local override. */
2399 id->override_library->reference->tag |= ID_TAG_DOIT;
2400 }
2401 }
2402 }
2403 }
2405
2406 /* Code above may have added some tags, we need to update this too. */
2409 }
2410
2411 /* Tag all local overrides of the current hierarchy. */
2413 data.is_override = true;
2414 data.root_set(id_root);
2415 data.hierarchy_root_set(id_root->override_library->hierarchy_root);
2417
2419 data.clear();
2420
2421 /* Make new override from linked data. */
2422 /* Note that this call also remaps all pointers of tagged IDs from old override IDs to new
2423 * override IDs (including within the old overrides themselves, since those are tagged too
2424 * above). */
2425 const bool success = BKE_lib_override_library_create_from_tag(
2426 bmain,
2427 nullptr,
2428 id_root_reference,
2430 nullptr,
2431 true,
2432 false);
2433
2434 if (!success) {
2435 BLI_ghash_free(linkedref_to_old_override, nullptr, nullptr);
2436 return success;
2437 }
2438
2439 /* This used to be the library of the root reference. Should always be the same as the current
2440 * library on readfile case, but may differ when relocating linked data from a library to
2441 * another (See #BKE_blendfile_id_relocate and #BKE_blendfile_library_relocate). */
2442 Library *id_root_reference_lib_old = (new_to_old_libraries_map ?
2443 new_to_old_libraries_map->lookup_default(
2444 id_root_reference->lib, id_root_reference->lib) :
2445 id_root_reference->lib);
2446 const bool is_relocate = id_root_reference_lib_old != id_root_reference->lib;
2447
2448 /* Get a mapping of all missing linked IDs that were liboverrides, to search for 'old
2449 * liboverrides' for newly created ones that do not already have one, in next step. */
2451 bmain, is_relocate);
2452 /* Vector of pairs of reference IDs, and their new override IDs. */
2453 blender::Vector<std::pair<ID *, ID *>> references_and_new_overrides;
2454
2455 ListBase *lb;
2456 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
2457 ID *id_reference_iter;
2458 FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_reference_iter) {
2459 if ((id_reference_iter->tag & ID_TAG_DOIT) == 0 || id_reference_iter->newid == nullptr ||
2460 !ELEM(id_reference_iter->lib, id_root_reference->lib, id_root_reference_lib_old))
2461 {
2462 continue;
2463 }
2464 ID *id_override_new = id_reference_iter->newid;
2465 references_and_new_overrides.append(std::make_pair(id_reference_iter, id_override_new));
2466
2467 ID *id_override_old = static_cast<ID *>(
2468 BLI_ghash_lookup(linkedref_to_old_override, id_reference_iter));
2469
2470 BLI_assert((id_override_new->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0);
2471
2472 /* We need to 'move back' newly created override into its proper library (since it was
2473 * duplicated from the reference ID with 'no main' option, it should currently be the same
2474 * as the reference ID one). */
2475 BLI_assert( id_override_new->lib ==
2476 id_reference_iter->lib);
2477 BLI_assert(id_override_old == nullptr || id_override_old->lib == id_root->lib);
2478 id_override_new->lib = id_root->lib;
2479
2480 /* The old override may have been created as linked data and then referenced by local data
2481 * during a previous Blender session, in which case it became directly linked and a reference
2482 * to it was stored in the local .blend file. however, since that linked liboverride ID does
2483 * not actually exist in the original library file, on next file read it is lost and marked
2484 * as missing ID. */
2485 if (id_override_old == nullptr && (ID_IS_LINKED(id_override_new) || is_relocate)) {
2486 id_override_old = lib_override_library_resync_search_missing_ids_data(missing_ids_data,
2487 id_override_new);
2488 BLI_assert(id_override_old == nullptr || id_override_old->lib == id_override_new->lib);
2489 if (id_override_old != nullptr) {
2490 BLI_ghash_insert(linkedref_to_old_override, id_reference_iter, id_override_old);
2491
2492 Key *key_override_old = BKE_key_from_id(id_override_old);
2493 Key *key_reference_iter = BKE_key_from_id(id_reference_iter);
2494 if (key_reference_iter && key_override_old) {
2496 linkedref_to_old_override, &key_reference_iter->id, &key_override_old->id);
2497 }
2498
2500 "Found missing linked old override best-match %s for new linked override %s",
2501 id_override_old->name,
2502 id_override_new->name);
2503 }
2504 }
2505
2506 /* Remap step below will tag directly linked ones properly as needed. */
2507 if (ID_IS_LINKED(id_override_new)) {
2508 id_override_new->tag |= ID_TAG_INDIRECT;
2509 }
2510
2511 if (id_override_old != nullptr) {
2512 /* Swap the names between old override ID and new one. */
2513 char id_name_buf[MAX_ID_NAME];
2514 memcpy(id_name_buf, id_override_old->name, sizeof(id_name_buf));
2515 memcpy(id_override_old->name, id_override_new->name, sizeof(id_override_old->name));
2516 memcpy(id_override_new->name, id_name_buf, sizeof(id_override_new->name));
2517
2518 BLI_insertlinkreplace(lb, id_override_old, id_override_new);
2519 id_override_old->tag |= ID_TAG_NO_MAIN;
2520 id_override_new->tag &= ~ID_TAG_NO_MAIN;
2521
2522 lib_override_object_posemode_transfer(id_override_new, id_override_old);
2523
2524 /* Missing old liboverrides cannot transfer their override rules to new liboverride.
2525 * This is fine though, since these are expected to only be 'virtual' linked overrides
2526 * generated by resync of linked overrides. So nothing is expected to be overridden here.
2527 */
2528 if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new) &&
2529 (id_override_old->tag & ID_TAG_MISSING) == 0)
2530 {
2531 BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old));
2532
2533 id_override_new->override_library->flag = id_override_old->override_library->flag;
2534
2535 /* NOTE: Since `runtime->tag` is not copied from old to new liboverride, the potential
2536 * `LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT` is kept on the old, to-be-freed
2537 * liboverride, and the new one is assumed to be properly part of its hierarchy again. */
2538
2539 /* Copy over overrides rules from old override ID to new one. */
2541 &id_override_old->override_library->properties);
2543 id_override_new->override_library->properties.first);
2545 id_override_old->override_library->properties.first);
2546 for (; op_new; op_new = op_new->next, op_old = op_old->next) {
2547 lib_override_library_property_copy(op_new, op_old);
2548 }
2549 }
2550
2551 BLI_addtail(no_main_ids_list, id_override_old);
2552 }
2553 else {
2554 /* Add to proper main list, ensure unique name for local ID, sort, and clear relevant
2555 * tags. */
2556 BKE_libblock_management_main_add(bmain, id_override_new);
2557 }
2558 }
2560 }
2562
2563 /* We remap old to new override usages in a separate step, after all new overrides have
2564 * been added to Main.
2565 *
2566 * This function also ensures that newly created overrides get all their linked ID pointers
2567 * remapped to a valid override one, whether new or already existing. In partial resync case,
2568 * #BKE_lib_override_library_create_from_tag cannot reliably discover _all_ valid existing
2569 * overrides used by the newly resynced ones, since the local resynced hierarchy may not contain
2570 * them. */
2572 bmain, id_root_reference, references_and_new_overrides, linkedref_to_old_override);
2573
2575
2576 blender::Vector<ID *> id_override_old_vector;
2577
2578 /* We need to apply override rules in a separate loop, after all ID pointers have been properly
2579 * remapped, and all new local override IDs have gotten their proper original names, otherwise
2580 * override operations based on those ID names would fail. */
2581 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2582 if ((id->tag & ID_TAG_DOIT) == 0 || id->newid == nullptr || id->lib != id_root_reference->lib)
2583 {
2584 continue;
2585 }
2586
2587 ID *id_override_new = id->newid;
2588 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_override_new)) {
2589 continue;
2590 }
2591
2592 ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id));
2593 if (id_override_old == nullptr) {
2594 continue;
2595 }
2596
2597 if (ID_IS_OVERRIDE_LIBRARY_REAL(id_override_old)) {
2598 /* The remapping from old to new liboverrides above has a sad side effect on ShapeKeys. Since
2599 * old liboverrides are also remapped, it means that the old liboverride owner of the shape
2600 * key is also now pointing to the new liboverride shape key, not the old one. Since shape
2601 * keys do not own their liboverride data, the old liboverride shape key user has to be
2602 * restored to use the old liboverride shape-key, otherwise applying shape key override
2603 * operations will be useless (would apply using the new, from linked data, liboverride,
2604 * being effectively a no-op). */
2605 Key **key_override_old_p = BKE_key_from_id_p(id_override_old);
2606 if (key_override_old_p != nullptr && *key_override_old_p != nullptr) {
2607 Key *key_linked_reference = BKE_key_from_id(id_override_new->override_library->reference);
2608 BLI_assert(key_linked_reference != nullptr);
2609 BLI_assert(key_linked_reference->id.newid == &(*key_override_old_p)->id);
2610 Key *key_override_old = static_cast<Key *>(
2611 BLI_ghash_lookup(linkedref_to_old_override, &key_linked_reference->id));
2612 BLI_assert(key_override_old != nullptr);
2613 *key_override_old_p = key_override_old;
2614 }
2615
2616 /* Apply rules on new override ID using old one as 'source' data. */
2617 /* Note that since we already remapped ID pointers in old override IDs to new ones, we
2618 * can also apply ID pointer override rules safely here. */
2619 PointerRNA rnaptr_src = RNA_id_pointer_create(id_override_old);
2620 PointerRNA rnaptr_dst = RNA_id_pointer_create(id_override_new);
2621
2622 /* In case the parent of the liboverride object matches hierarchy-wise the parent of its
2623 * linked reference, also enforce clearing any override of the other related parenting
2624 * settings.
2625 *
2626 * While this may break some rare use-cases, in almost all situations the best behavior here
2627 * is to follow the values from the reference data (especially when it comes to the invert
2628 * parent matrix). */
2629 bool do_clear_parenting_override = false;
2630 if (GS(id_override_new->name) == ID_OB) {
2631 Object *ob_old = reinterpret_cast<Object *>(id_override_old);
2632 Object *ob_new = reinterpret_cast<Object *>(id_override_new);
2633 if (ob_new->parent && ob_new->parent != ob_old->parent &&
2634 /* Parent is not a liboverride. */
2635 (ob_new->parent ==
2636 reinterpret_cast<Object *>(ob_new->id.override_library->reference)->parent ||
2637 /* Parent is a hierarchy-matching liboverride. */
2639 reinterpret_cast<Object *>(ob_new->parent->id.override_library->reference) ==
2640 reinterpret_cast<Object *>(ob_new->id.override_library->reference)->parent)))
2641 {
2642 do_clear_parenting_override = true;
2643 }
2644 }
2645
2646 /* We remove any operation tagged with `LIBOVERRIDE_OP_FLAG_IDPOINTER_MATCH_REFERENCE`,
2647 * that way the potentially new pointer will be properly kept, when old one is still valid
2648 * too (typical case: assigning new ID to some usage, while old one remains used elsewhere
2649 * in the override hierarchy). */
2651 IDOverrideLibraryProperty *, op, &id_override_new->override_library->properties)
2652 {
2656 BLI_freelinkN(&op->operations, opop);
2657 }
2658 }
2659 if (BLI_listbase_is_empty(&op->operations)) {
2661 }
2662 else if (do_clear_parenting_override) {
2663 if (strstr(op->rna_path, "matrix_parent_inverse") ||
2664 strstr(op->rna_path, "parent_type") || strstr(op->rna_path, "parent_bone") ||
2665 strstr(op->rna_path, "parent_vertices"))
2666 {
2668 "Deleting liboverride property '%s' from object %s, as its parent pointer "
2669 "matches the reference data hierarchy wise",
2670 id_override_new->name + 2,
2671 op->rna_path);
2673 }
2674 }
2675 }
2676
2678 &rnaptr_dst,
2679 &rnaptr_src,
2680 nullptr,
2681 id_override_new->override_library,
2682 do_hierarchy_enforce ? RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS :
2684
2685 /* Clear the old shape key pointer again, otherwise it won't make ID management code happy
2686 * when freeing (at least from user count side of things). */
2687 if (key_override_old_p != nullptr) {
2688 *key_override_old_p = nullptr;
2689 }
2690 }
2691
2692 id_override_old_vector.append(id_override_old);
2693 }
2695
2696 /* Once overrides have been properly 'transferred' from old to new ID, we can clear ID usages
2697 * of the old one.
2698 * This is necessary in case said old ID is not in Main anymore. */
2699 id::IDRemapper id_remapper;
2701 id_override_old_vector,
2703 id_remapper,
2705 for (ID *id_override_old : id_override_old_vector) {
2706 id_override_old->tag |= ID_TAG_NO_USER_REFCOUNT;
2707 }
2708 id_override_old_vector.clear();
2709
2710 /* Delete old override IDs.
2711 * Note that we have to use tagged group deletion here, since ID deletion also uses
2712 * ID_TAG_DOIT. This improves performances anyway, so everything is fine. */
2713 int user_edited_overrides_deletion_count = 0;
2714 FOREACH_MAIN_ID_BEGIN (bmain, id) {
2715 if (id->tag & ID_TAG_DOIT) {
2716 /* Since this code can also be called on linked liboverride now (during recursive resync),
2717 * order of processing cannot guarantee anymore that the old liboverride won't be tagged for
2718 * deletion before being processed by this loop (which would then untag it again).
2719 *
2720 * So instead store old liboverrides in Main into a temp list again, and do the tagging
2721 * separately once this loop over all IDs in main is done. */
2722 if (id->newid != nullptr && id->lib == id_root_reference->lib) {
2723 ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id));
2724
2725 if (id_override_old != nullptr) {
2726 id->newid->tag &= ~ID_TAG_DOIT;
2727 if (id_override_old->tag & ID_TAG_NO_MAIN) {
2728 id_override_old->tag |= ID_TAG_DOIT;
2729 BLI_assert(BLI_findindex(no_main_ids_list, id_override_old) != -1);
2730 }
2731 else {
2732 /* Defer tagging. */
2733 id_override_old_vector.append(id_override_old);
2734 }
2735 }
2736 }
2737 id->tag &= ~ID_TAG_DOIT;
2738 }
2739 /* Also deal with old overrides that went missing in new linked data - only for real local
2740 * overrides for now, not those who are linked. */
2741 else if (id->tag & ID_TAG_MISSING && !ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
2742 bool do_delete;
2743 ID *hierarchy_root = id->override_library->hierarchy_root;
2744 if (id->override_library->reference->lib->id.tag & ID_TAG_MISSING) {
2745 /* Do not delete overrides which reference is missing because the library itself is missing
2746 * (ref. #100586). */
2747 do_delete = false;
2748 }
2749 else if (hierarchy_root != nullptr &&
2750 hierarchy_root->override_library->reference->tag & ID_TAG_MISSING)
2751 {
2752 /* Do not delete overrides which root hierarchy reference is missing. This would typically
2753 * cause more harm than good. */
2754 do_delete = false;
2755 }
2757 /* If user never edited them, we can delete them. */
2758 do_delete = true;
2759 CLOG_DEBUG(&LOG_RESYNC, "Old override %s is being deleted", id->name);
2760 }
2761#if 0
2762 else {
2763 /* Otherwise, keep them, user needs to decide whether what to do with them. */
2764 BLI_assert((id->tag & ID_TAG_DOIT) == 0);
2765 do_delete = false;
2766 id_fake_user_set(id);
2769 "Old override %s is being kept around as it was user-edited",
2770 id->name);
2771 }
2772#else
2773 else {
2774 /* Delete them nevertheless, with fat warning, user needs to decide whether they want to
2775 * save that version of the file (and accept the loss), or not. */
2776 do_delete = true;
2778 "Old override %s is being deleted even though it was user-edited",
2779 id->name);
2780 user_edited_overrides_deletion_count++;
2781 }
2782#endif
2783 if (do_delete) {
2784 id->tag |= ID_TAG_DOIT;
2785 id->tag &= ~ID_TAG_MISSING;
2786 }
2787 else if (id->override_library->runtime != nullptr) {
2788 /* Cleanup of this temporary tag, since that somewhat broken liboverride is explicitly
2789 * kept for now. */
2790 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
2791 }
2792 }
2793 }
2795
2796 /* Finalize tagging old liboverrides for deletion. */
2797 for (ID *id_override_old : id_override_old_vector) {
2798 id_override_old->tag |= ID_TAG_DOIT;
2799 }
2800 id_override_old_vector.clear();
2801
2802 /* Cleanup, many pointers in this GHash are already invalid now. */
2803 BLI_ghash_free(linkedref_to_old_override, nullptr, nullptr);
2804
2806
2807 /* At this point, `id_root` may have been resynced, therefore deleted. In that case we need to
2808 * update it to its new version.
2809 */
2810 if (id_root_reference->newid != nullptr) {
2811 id_root = id_root_reference->newid;
2812 }
2813
2814 if (user_edited_overrides_deletion_count > 0) {
2815 BKE_reportf(reports != nullptr ? reports->reports : nullptr,
2817 "During resync of data-block %s, %d obsolete overrides were deleted, that had "
2818 "local changes defined by user",
2819 id_root->name + 2,
2820 user_edited_overrides_deletion_count);
2821 }
2822
2823 if (do_post_process) {
2824 /* Essentially ensures that potentially new overrides of new objects will be instantiated. */
2825 /* NOTE: Here 'reference' collection and 'newly added' collection are the same, which is fine
2826 * since we already relinked old root override collection to new resync'ed one above. So this
2827 * call is not expected to instantiate this new resync'ed collection anywhere, just to ensure
2828 * that we do not have any stray objects. */
2830 scene,
2831 view_layer,
2832 nullptr,
2833 id_root_reference,
2834 id_root,
2835 override_resync_residual_storage,
2836 old_active_object,
2837 true);
2838 }
2839
2840 /* Cleanup. */
2842 /* That one should not be needed in fact, as #BKE_id_multi_tagged_delete call above should have
2843 * deleted all tagged IDs. */
2844 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
2845
2846 return success;
2847}
2848
2851{
2852 LibQueryUnusedIDsData parameters;
2853 parameters.do_local_ids = true;
2854 parameters.do_linked_ids = true;
2855 parameters.do_recursive = true;
2856 parameters.filter_fn = [](const ID *id) -> bool {
2857 if (ID_IS_LINKED(id) && (id->tag & ID_TAG_MISSING) != 0) {
2858 return true;
2859 }
2860 /* This is a fairly complex case.
2861 *
2862 * LibOverride resync process takes care of removing 'no more valid' liboverrides (see at the
2863 * end of #lib_override_library_main_resync_on_library_indirect_level). However, since it does
2864 * not resync data which linked reference is missing (see
2865 * #lib_override_library_main_resync_id_skip_check), these are kept 'as is'. Indeed,
2866 * liboverride resync code cannot know if a specific liboverride data is only part of its
2867 * hierarchy, or if it is also used by some other data (in which case it should be preserved if
2868 * the linked reference goes missing).
2869 *
2870 * So instead, we consider these cases as also valid candidates for deletion here, since the
2871 * whole recursive process in `BKE_lib_query_unused_ids_tag` will ensure that if there is still
2872 * any valid user of these, they won't get tagged for deletion.
2873 *
2874 * Also, do not delete 'orphaned' liboverrides if it's a hierarchy root, or if its hierarchy
2875 * root's reference is missing, since this is much more likely a case of actual missing data,
2876 * rather than changes in the liboverride's hierarchy in the linked data.
2877 */
2878 if (ID_IS_OVERRIDE_LIBRARY(id)) {
2879 const IDOverrideLibrary *override_library = BKE_lib_override_library_get(
2880 nullptr, id, nullptr, nullptr);
2881 /* NOTE: Since hierarchy root final validation is only done on 'expected-to-be-processed' IDs
2882 * after each level of recursive resync (and not the whole Main data-base, see @00375abc38),
2883 * `root` may now be null here. Likely, because deleting some root override sets that pointer
2884 * to null.
2885 *
2886 * If this turns out to be a wrong fix, the other likely solution would be to add a call to
2887 * #BKE_lib_override_library_main_hierarchy_root_ensure before calling
2888 * #lib_override_cleanup_after_resync.
2889 *
2890 * This was technically already possible before (e.g. for non-hierarchical isolated
2891 * liboverrides), but in practice this is very rare case. */
2892 const ID *root = override_library->hierarchy_root;
2893 if (root && (root == id || (root->override_library->reference->tag & ID_TAG_MISSING) != 0)) {
2894 return false;
2895 }
2896 return ((override_library->reference->tag & ID_TAG_MISSING) != 0);
2897 }
2898 return false;
2899 };
2900 BKE_lib_query_unused_ids_tag(bmain, ID_TAG_DOIT, parameters);
2901 if (parameters.num_total[INDEX_ID_NULL]) {
2903 "Deleting %d unused linked missing IDs and their unused liboverrides (including %d "
2904 "local ones)\n",
2905 parameters.num_total[INDEX_ID_NULL],
2906 parameters.num_local[INDEX_ID_NULL]);
2907 }
2909}
2910
2912 Scene *scene,
2913 ViewLayer *view_layer,
2914 ID *id_root,
2915 Collection *override_resync_residual_storage,
2916 const bool do_hierarchy_enforce,
2917 BlendFileReadReport *reports)
2918{
2919 ListBase no_main_ids_list = {nullptr};
2920 LinkNode id_resync_roots{};
2921 id_resync_roots.link = id_root;
2922 id_resync_roots.next = nullptr;
2923
2924 const bool success = lib_override_library_resync(bmain,
2925 nullptr,
2926 scene,
2927 view_layer,
2928 id_root,
2929 &id_resync_roots,
2930 &no_main_ids_list,
2931 override_resync_residual_storage,
2932 do_hierarchy_enforce,
2933 true,
2934 reports);
2935
2936 LISTBASE_FOREACH_MUTABLE (ID *, id_iter, &no_main_ids_list) {
2937 BKE_id_free(bmain, id_iter);
2938 }
2939
2940 /* Cleanup global namemap, to avoid extra processing with regular ID name management. Better to
2941 * re-create the global namemap on demand. */
2943
2945
2946 return success;
2947}
2948
2950 const int library_indirect_level,
2951 const bool do_strict_equal)
2952{
2953 const int id_lib_level = (ID_IS_LINKED(id) ? id->lib->runtime->temp_index : 0);
2954 return do_strict_equal ? id_lib_level == library_indirect_level :
2955 id_lib_level <= library_indirect_level;
2956}
2957
2958/* Check ancestors overrides for resync, to ensure all IDs in-between two tagged-for-resync ones
2959 * are also properly tagged.
2960 *
2961 * WARNING: Expects `bmain` to have valid relation data.
2962 *
2963 * Returns `true` if it finds an ancestor within the current liboverride hierarchy also tagged as
2964 * needing resync, `false` otherwise.
2965 *
2966 * NOTE: If `check_only` is true, it only does the check and returns, without any modification to
2967 * the data.
2968 */
2970 ID *id_root,
2971 ID *id_from,
2972 const int library_indirect_level,
2973 bool is_in_partial_resync_hierarchy)
2974{
2976 BLI_assert(id_root->override_library->hierarchy_root != nullptr);
2977
2978 if (!lib_override_resync_id_lib_level_is_valid(id_root, library_indirect_level, false)) {
2979 CLOG_ERROR(
2980 &LOG,
2981 "While processing indirect level %d, ID %s from lib %s of indirect level %d detected "
2982 "as needing resync, skipping",
2983 library_indirect_level,
2984 id_root->name,
2985 id_root->lib ? id_root->lib->filepath : "<LOCAL>",
2986 id_root->lib ? id_root->lib->runtime->temp_index : 0);
2988 return;
2989 }
2990
2991 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
2993 BLI_assert(entry != nullptr);
2994
2995 bool is_reprocessing_current_entry = false;
2997 /* This ID is already being processed, this indicates a dependency loop. */
2999
3000 if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
3001 /* This ID is already tagged for resync, then the loop leading back to it is also fully
3002 * tagged for resync, nothing else to do. */
3003 BLI_assert(is_in_partial_resync_hierarchy);
3004 return;
3005 }
3006 if (!is_in_partial_resync_hierarchy) {
3007 /* This ID is not tagged for resync, and is part of a loop where none of the other IDs are
3008 * tagged for resync, nothing else to do. */
3009 return;
3010 }
3011 /* This ID is not yet tagged for resync, but is part of a loop which is (partially) tagged
3012 * for resync.
3013 * The whole loop needs to be processed a second time to ensure all of its members are properly
3014 * tagged for resync then. */
3015 is_reprocessing_current_entry = true;
3016
3017 CLOG_DEBUG(
3018 &LOG,
3019 "ID %s (%p) is detected as part of a hierarchy dependency loop requiring resync, it "
3020 "is now being re-processed to ensure proper tagging of the whole loop",
3021 id_root->name,
3022 id_root->lib);
3023 }
3024 else if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
3025 /* This ID has already been processed. */
3027
3028 /* If it was already detected as needing resync, then its whole sub-tree should also be fully
3029 * processed. Only need to ensure that it is not tagged as potential partial resync root
3030 * anymore, if now processed as part of another partial resync hierarchy. */
3031 if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
3032 if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_DOIT && is_in_partial_resync_hierarchy) {
3033 CLOG_DEBUG(
3034 &LOG,
3035 "ID %s (%p) was marked as a potential root for partial resync, but it is used by "
3036 "%s (%p), which is also tagged for resync, so it is not a root after all",
3037 id_root->name,
3038 id_root->lib,
3039 id_from->name,
3040 id_from->lib);
3041
3043 }
3044 return;
3045 }
3046 /* Else, if it is not being processed as part of a resync hierarchy, nothing more to do either,
3047 * its current status and the one of its whole dependency tree is also assumed valid. */
3048 if (!is_in_partial_resync_hierarchy) {
3049 return;
3050 }
3051
3052 /* Else, this ID was processed before and not detected as needing resync, but it now needs
3053 * resync, so its whole sub-tree needs to be re-processed to be properly tagged as needing
3054 * resync. */
3056 }
3057
3058 if (is_in_partial_resync_hierarchy) {
3059 BLI_assert(id_from != nullptr);
3060
3061 if ((id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0) {
3062 CLOG_DEBUG(&LOG,
3063 "ID %s (%p) now tagged as needing resync because they are used by %s (%p) "
3064 "that needs to be resynced",
3065 id_root->name,
3066 id_root->lib,
3067 id_from->name,
3068 id_from->lib);
3070 }
3071 }
3072 else if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
3073 /* Not yet within a partial resync hierarchy, and this ID is tagged for resync, it is a
3074 * potential partial resync root. */
3075 is_in_partial_resync_hierarchy = true;
3076 }
3077
3078 /* Temporary tag to help manage dependency loops. */
3079 if (!is_reprocessing_current_entry) {
3082
3083 /* Since this ID is reached from the hierarchy root, it is not isolated from it. */
3084 if (id_root->override_library->hierarchy_root != id_root &&
3085 id_root->override_library->runtime != nullptr)
3086 {
3088 }
3089 }
3090
3091 /* Check the whole sub-tree hierarchy of this ID. */
3092 for (MainIDRelationsEntryItem *entry_item = entry->to_ids; entry_item != nullptr;
3093 entry_item = entry_item->next)
3094 {
3096 continue;
3097 }
3098 ID *id_to = *(entry_item->id_pointer.to);
3099 /* Ensure the 'real' override is processed, in case `id_to` is e.g. an embedded ID, get its
3100 * owner instead. */
3101 BKE_lib_override_library_get(bmain, id_to, nullptr, &id_to);
3102
3103 if (lib_override_hierarchy_dependencies_skip_check(id_root, id_to, true)) {
3104 continue;
3105 }
3107 "Check above ensured `id_to` is a liboverride, so it should be a real one (not "
3108 "an embedded one)");
3109
3110 /* Non-matching hierarchy root IDs mean this is not the same liboverride hierarchy anymore. */
3112 continue;
3113 }
3114
3116 bmain, id_to, id_root, library_indirect_level, is_in_partial_resync_hierarchy);
3117
3118 /* Call above may have changed that status in case of dependency loop, update it for the next
3119 * dependency processing. */
3120 is_in_partial_resync_hierarchy = (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) != 0;
3121 }
3122
3123 if (!is_reprocessing_current_entry) {
3126
3129
3130 if (is_in_partial_resync_hierarchy &&
3131 (id_from == nullptr || (id_from->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0))
3132 {
3133 /* This ID (and its whole sub-tree of dependencies) is now considered as processed. If it is
3134 * tagged for resync, but its 'calling parent' is not, it is a potential partial resync root.
3135 */
3136 CLOG_DEBUG(
3137 &LOG_RESYNC, "Potential root for partial resync: %s (%p)", id_root->name, id_root->lib);
3139 }
3140 }
3141}
3142
3143/* Return true if the ID should be skipped for resync given current context. */
3145 const int library_indirect_level)
3146{
3147 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
3148 return true;
3149 }
3150
3151 if (!lib_override_resync_id_lib_level_is_valid(id, library_indirect_level, true)) {
3152 return true;
3153 }
3154
3155 /* Do not attempt to resync from missing data. */
3156 if (((id->tag | id->override_library->reference->tag) & ID_TAG_MISSING) != 0) {
3157 return true;
3158 }
3159
3160 if (id->override_library->flag & LIBOVERRIDE_FLAG_NO_HIERARCHY) {
3161 /* This ID is not part of an override hierarchy. */
3163 return true;
3164 }
3165
3166 /* Do not attempt to resync when hierarchy root is missing, this would usually do more harm
3167 * than good. */
3168 ID *hierarchy_root = id->override_library->hierarchy_root;
3169 if (hierarchy_root == nullptr ||
3170 ((hierarchy_root->tag | hierarchy_root->override_library->reference->tag) &
3171 ID_TAG_MISSING) != 0)
3172 {
3173 return true;
3174 }
3175
3176 return false;
3177}
3178
3191 Main *bmain, ID *id, const int library_indirect_level)
3192{
3193 BLI_assert(!lib_override_library_main_resync_id_skip_check(id, library_indirect_level));
3194
3195 if (id->override_library->hierarchy_root == id ||
3196 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT) == 0)
3197 {
3198 BLI_assert(
3199 id->override_library->hierarchy_root != id || id->override_library->runtime == nullptr ||
3200 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT) == 0);
3201 return true;
3202 }
3203
3204 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3206 BLI_assert(entry != nullptr);
3207
3209 /* This ID has already been processed, since 'true' conditions have already been checked above,
3210 * it is validated as an isolated liboverride. */
3211 return false;
3212 }
3213 /* This way we won't process again that ID, should we encounter it again through another
3214 * relationship hierarchy. */
3216
3217 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
3218 to_id_entry = to_id_entry->next)
3219 {
3221 continue;
3222 }
3223 ID *to_id = *(to_id_entry->id_pointer.to);
3224 if (lib_override_library_main_resync_id_skip_check(to_id, library_indirect_level)) {
3225 continue;
3226 }
3227
3229 bmain, to_id, library_indirect_level))
3230 {
3231 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
3232 return true;
3233 }
3234 }
3235
3236 return false;
3237}
3238
3239/* Once all IDs needing resync have been tagged, partial ID roots can be found by processing each
3240 * tagged-for-resync IDs' ancestors within their liboverride hierarchy. */
3242 GHash *id_roots,
3243 const int library_indirect_level)
3244{
3245 ID *id_iter;
3246
3247 /* Tag all IDs to be processed, which are real liboverrides part of a hierarchy, and not the
3248 * root of their hierarchy, as potentially isolated from their hierarchy root. */
3249 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3250 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3251 continue;
3252 }
3253
3254 if (!ELEM(id_iter->override_library->hierarchy_root, id_iter, nullptr)) {
3257 }
3258 }
3260
3261 /* Finalize all IDs needing tagging for resync, and tag partial resync roots. Will also clear the
3262 * 'isolated' tag from all processed IDs. */
3263 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3264 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3265 continue;
3266 }
3267
3268 /* Only process hierarchy root IDs here. */
3269 if (id_iter->override_library->hierarchy_root != id_iter) {
3270 continue;
3271 }
3272
3274 bmain, id_iter, nullptr, library_indirect_level, false);
3275 }
3277
3278#ifndef NDEBUG
3279 /* Validation loop to ensure all entries have been processed as expected by
3280 * `lib_override_resync_tagging_finalize_recurse`, in above loop. */
3281 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3282 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3283 continue;
3284 }
3285 if ((id_iter->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0) {
3286 continue;
3287 }
3288
3289 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3291 BLI_assert(entry != nullptr);
3293
3294 if ((entry->tags & MAINIDRELATIONS_ENTRY_TAGS_DOIT) == 0) {
3295 continue;
3296 }
3297
3299 }
3301#endif
3302
3304
3305 /* Process above cleared all IDs actually still in relation with their root from the tag.
3306 *
3307 * The only exception being IDs only in relation with their root through a 'reversed' from
3308 * pointer (typical case: armature object is the hierarchy root, its child mesh object is only
3309 * related to it through its own 'parent' pointer, the armature one has no 'to' relationships to
3310 * its deformed mesh object.
3311 *
3312 * Remaining ones are in a limbo, typically they could have been removed or moved around in the
3313 * hierarchy (e.g. an object moved into another sub-collection). Tag them as needing resync,
3314 * actual resyncing code will handle them as needed. */
3315 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3316 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3317 continue;
3318 }
3319
3320 if (!ELEM(id_iter->override_library->hierarchy_root, id_iter, nullptr) &&
3322 {
3323 /* Check and clear 'isolated' tags from cases like child objects of a hierarchy root object.
3324 * Sigh. */
3326 bmain, id_iter, library_indirect_level))
3327 {
3331 "ID %s (%p) detected as only related to its hierarchy root by 'reversed' "
3332 "relationship(s) (e.g. object parenting), tagging it as needing "
3333 "resync",
3334 id_iter->name,
3335 id_iter->lib);
3336 }
3337 else {
3338 CLOG_DEBUG(
3339 &LOG_RESYNC,
3340 "ID %s (%p) detected as 'isolated' from its hierarchy root, tagging it as needing "
3341 "resync",
3342 id_iter->name,
3343 id_iter->lib);
3344 }
3346 }
3347 }
3349
3351
3352 /* If no tagged-for-resync ancestor was found, but the iterated ID is tagged for resync, then it
3353 * is a root of a resync sub-tree. Find the root of the whole override hierarchy and add the
3354 * iterated ID as one of its resync sub-tree roots. */
3355 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
3356 if (lib_override_library_main_resync_id_skip_check(id_iter, library_indirect_level)) {
3357 continue;
3358 }
3359 if ((id_iter->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) == 0) {
3360 continue;
3361 }
3362
3363 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3365 BLI_assert(entry != nullptr);
3366
3367 if ((entry->tags & MAINIDRELATIONS_ENTRY_TAGS_DOIT) == 0) {
3368 continue;
3369 }
3370
3371 ID *hierarchy_root = id_iter->override_library->hierarchy_root;
3372 BLI_assert(hierarchy_root->lib == id_iter->lib);
3373
3374 if (id_iter != hierarchy_root) {
3376 "Found root ID '%s' for partial resync root ID '%s'",
3377 hierarchy_root->name,
3378 id_iter->name);
3379
3380 BLI_assert(hierarchy_root->override_library != nullptr);
3381
3384 }
3385
3386 LinkNodePair **id_resync_roots_p;
3387 if (!BLI_ghash_ensure_p(
3388 id_roots, hierarchy_root, reinterpret_cast<void ***>(&id_resync_roots_p)))
3389 {
3390 *id_resync_roots_p = MEM_callocN<LinkNodePair>(__func__);
3391 }
3392 BLI_linklist_append(*id_resync_roots_p, id_iter);
3393 }
3395
3397 bmain,
3401 false);
3402}
3403
3404/* Ensure resync of all overrides at one level of indirect usage.
3405 *
3406 * We need to handle each level independently, since an override at level n may be affected by
3407 * other overrides from level n + 1 etc. (i.e. from linked overrides it may use).
3408 */
3410 Main *bmain,
3411 const blender::Map<Library *, Library *> *new_to_old_libraries_map,
3412 Scene *scene,
3413 ViewLayer *view_layer,
3414 Collection *override_resync_residual_storage,
3415 const int library_indirect_level,
3416 BlendFileReadReport *reports)
3417{
3418 const bool do_reports_recursive_resync_timing = (library_indirect_level != 0);
3419 const double init_time = do_reports_recursive_resync_timing ? BLI_time_now_seconds() : 0.0;
3420
3421 BKE_main_relations_create(bmain, 0);
3422 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3423
3424 /* NOTE: in code below, the order in which `FOREACH_MAIN_ID_BEGIN` processes ID types ensures
3425 * that we always process 'higher-level' overrides first (i.e. scenes, then collections, then
3426 * objects, then other types). */
3427
3428 /* Detect all linked data that would need to be overridden if we had to create an override from
3429 * those used by current existing overrides. */
3431 data.bmain = bmain;
3432 data.scene = scene;
3433 data.tag = ID_TAG_DOIT;
3434 data.missing_tag = ID_TAG_MISSING;
3435 data.is_override = false;
3436 data.is_resync = true;
3438 ID *id;
3439 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3440 if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
3441 continue;
3442 }
3443
3444 if (id->tag & (ID_TAG_DOIT | ID_TAG_MISSING)) {
3445 /* We already processed that ID as part of another ID's hierarchy. */
3446 continue;
3447 }
3448
3449 data.root_set(id->override_library->reference);
3454 }
3456 data.clear();
3457
3458 GHash *id_roots = BLI_ghash_ptr_new(__func__);
3459
3460 /* Now check existing overrides, those needing resync will be the one either already tagged as
3461 * such, or the one using linked data that is now tagged as needing override. */
3462 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3463 if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
3464 continue;
3465 }
3466
3468 CLOG_DEBUG(
3469 &LOG_RESYNC, "ID %s (%p) was already tagged as needing resync", id->name, id->lib);
3471 override_library_runtime_ensure(id->override_library)->tag |=
3473 }
3474 continue;
3475 }
3476
3477 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
3479 BLI_assert(entry != nullptr);
3480
3481 for (MainIDRelationsEntryItem *entry_item = entry->to_ids; entry_item != nullptr;
3482 entry_item = entry_item->next)
3483 {
3485 continue;
3486 }
3487 ID *id_to = *entry_item->id_pointer.to;
3488
3489 /* Case where this ID pointer was to a linked ID, that now needs to be overridden. */
3490 if (ID_IS_LINKED(id_to) && (id_to->lib != id->lib) && (id_to->tag & ID_TAG_DOIT) != 0) {
3492 "ID %s (%p) now tagged as needing resync because they use linked %s (%p) that "
3493 "now needs to be overridden",
3494 id->name,
3495 id->lib,
3496 id_to->name,
3497 id_to->lib);
3499 break;
3500 }
3501 }
3502 }
3504
3505 /* Handling hierarchy relations for final tagging needs to happen after all IDs in a given
3506 * hierarchy have been tagged for resync in previous loop above. Otherwise, some resync roots may
3507 * be missing. */
3508 lib_override_resync_tagging_finalize(bmain, id_roots, library_indirect_level);
3509
3510#ifndef NDEBUG
3511 /* Check for validity/integrity of the computed set of root IDs, and their sub-branches defined
3512 * by their resync root IDs. */
3513 {
3515 GHashIterator *id_roots_iter = BLI_ghashIterator_new(id_roots);
3516 while (!BLI_ghashIterator_done(id_roots_iter)) {
3517 ID *id_root = static_cast<ID *>(BLI_ghashIterator_getKey(id_roots_iter));
3518 LinkNodePair *id_resync_roots = static_cast<LinkNodePair *>(
3519 BLI_ghashIterator_getValue(id_roots_iter));
3521 "Checking validity of computed TODO data for root '%s'... \n",
3522 id_root->name);
3523
3524 if (id_root->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) {
3525 LinkNode *id_resync_root_iter = id_resync_roots->list;
3526 ID *id_resync_root = static_cast<ID *>(id_resync_root_iter->link);
3527
3528 if (id_resync_roots->list != id_resync_roots->last_node || id_resync_root != id_root) {
3530 "Hierarchy root ID is tagged for resync, yet it is not the only partial "
3531 "resync roots, this should not happen."
3532 "\n\tRoot ID: %s"
3533 "\n\tFirst Resync root ID: %s"
3534 "\n\tLast Resync root ID: %s",
3535 id_root->name,
3536 static_cast<ID *>(id_resync_roots->list->link)->name,
3537 static_cast<ID *>(id_resync_roots->last_node->link)->name);
3538 }
3539 }
3540 for (LinkNode *id_resync_root_iter = id_resync_roots->list; id_resync_root_iter != nullptr;
3541 id_resync_root_iter = id_resync_root_iter->next)
3542 {
3543 ID *id_resync_root = static_cast<ID *>(id_resync_root_iter->link);
3544 BLI_assert(id_resync_root == id_root || !BLI_ghash_haskey(id_roots, id_resync_root));
3545 if (id_resync_root == id_root) {
3546 if (id_resync_root_iter != id_resync_roots->list ||
3547 id_resync_root_iter != id_resync_roots->last_node)
3548 {
3550 "Resync root ID is same as root ID of the override hierarchy, yet other "
3551 "resync root IDs are also defined, this should not happen at this point."
3552 "\n\tRoot ID: %s"
3553 "\n\tFirst Resync root ID: %s"
3554 "\n\tLast Resync root ID: %s",
3555 id_root->name,
3556 static_cast<ID *>(id_resync_roots->list->link)->name,
3557 static_cast<ID *>(id_resync_roots->last_node->link)->name);
3558 }
3559 }
3560 }
3561 BLI_ghashIterator_step(id_roots_iter);
3562 }
3563 BLI_ghashIterator_free(id_roots_iter);
3564 }
3565#endif
3566
3568 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3569
3570 ListBase no_main_ids_list = {nullptr};
3571
3572 GHashIterator *id_roots_iter = BLI_ghashIterator_new(id_roots);
3573 while (!BLI_ghashIterator_done(id_roots_iter)) {
3574 ID *id_root = static_cast<ID *>(BLI_ghashIterator_getKey(id_roots_iter));
3575 Library *library = id_root->lib;
3576 LinkNodePair *id_resync_roots = static_cast<LinkNodePair *>(
3577 BLI_ghashIterator_getValue(id_roots_iter));
3578
3579 if (ID_IS_LINKED(id_root)) {
3580 id_root->lib->runtime->tag |= LIBRARY_TAG_RESYNC_REQUIRED;
3581 }
3582
3584 "Resyncing all dependencies under root %s (%p), first one being '%s'...",
3585 id_root->name,
3586 reinterpret_cast<void *>(library),
3587 reinterpret_cast<ID *>(id_resync_roots->list->link)->name);
3588 const bool success = lib_override_library_resync(bmain,
3589 new_to_old_libraries_map,
3590 scene,
3591 view_layer,
3592 id_root,
3593 id_resync_roots->list,
3594 &no_main_ids_list,
3595 override_resync_residual_storage,
3596 false,
3597 false,
3598 reports);
3599 CLOG_DEBUG(&LOG_RESYNC, "\tSuccess: %d", success);
3600 if (success) {
3601 reports->count.resynced_lib_overrides++;
3602 if (library_indirect_level > 0 && reports->do_resynced_lib_overrides_libraries_list &&
3604 {
3607 }
3608 }
3609
3610 BLI_linklist_free(id_resync_roots->list, nullptr);
3611 BLI_ghashIterator_step(id_roots_iter);
3612 }
3613 BLI_ghashIterator_free(id_roots_iter);
3614
3615 LISTBASE_FOREACH_MUTABLE (ID *, id_iter, &no_main_ids_list) {
3616 BKE_id_free(bmain, id_iter);
3617 }
3618 BLI_listbase_clear(&no_main_ids_list);
3619
3620 /* Just in case, should not be needed in theory, since #lib_override_library_resync should have
3621 * already cleared them all. */
3622 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3623
3624 /* Check there are no left-over IDs needing resync from the current (or higher) level of indirect
3625 * library level. */
3626 bool process_lib_level_again = false;
3627
3628 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3629 if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
3630 continue;
3631 }
3632
3633 const bool need_resync = (id->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC) != 0;
3634 const bool need_reseync_original = (id->override_library->runtime != nullptr &&
3635 (id->override_library->runtime->tag &
3637 const bool is_isolated_from_root = (id->override_library->runtime != nullptr &&
3638 (id->override_library->runtime->tag &
3640
3641 if (need_resync && is_isolated_from_root) {
3643 CLOG_WARN(
3644 &LOG_RESYNC,
3645 "Deleting unused ID override %s from library level %d, still found as needing "
3646 "resync, and being isolated from its hierarchy root. This can happen when its "
3647 "otherwise unchanged linked reference was moved around in the library file (e.g. if "
3648 "an object was moved into another sub-collection of the same hierarchy).",
3649 id->name,
3650 ID_IS_LINKED(id) ? id->lib->runtime->temp_index : 0);
3651 id->tag |= ID_TAG_DOIT;
3652 }
3653 else {
3654 CLOG_WARN(
3655 &LOG_RESYNC,
3656 "Keeping user-edited ID override %s from library level %d still found as "
3657 "needing resync, and being isolated from its hierarchy root. This can happen when its "
3658 "otherwise unchanged linked reference was moved around in the library file (e.g. if "
3659 "an object was moved into another sub-collection of the same hierarchy).",
3660 id->name,
3661 ID_IS_LINKED(id) ? id->lib->runtime->temp_index : 0);
3663 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
3664 }
3665 }
3666 else if (need_resync) {
3667 if (need_reseync_original) {
3669 "ID override %s from library level %d still found as needing resync after "
3670 "tackling library level %d. Since it was originally tagged as such by "
3671 "RNA/liboverride apply code, this whole level of library needs to be processed "
3672 "another time.",
3673 id->name,
3674 ID_IS_LINKED(id) ? id->lib->runtime->temp_index : 0,
3675 library_indirect_level);
3676 process_lib_level_again = true;
3677 /* Cleanup tag for now, will be re-set by next iteration of this function. */
3678 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEED_RESYNC_ORIGINAL;
3679 }
3680 else {
3681 /* If it was only tagged for resync as part of resync process itself, it means it was
3682 * originally inside of a resync hierarchy, but not in the matching reference hierarchy
3683 * anymore. So it did not actually need to be resynced, simply clear the tag. */
3685 "ID override %s from library level %d still found as needing resync after "
3686 "tackling library level %d. However, it was not tagged as such by "
3687 "RNA/liboverride apply code, so ignoring it",
3688 id->name,
3689 ID_IS_LINKED(id) ? id->lib->runtime->temp_index : 0,
3690 library_indirect_level);
3692 }
3693 }
3694 else if (need_reseync_original) {
3695 /* Just cleanup of temporary tag, the ID has been resynced successfully. */
3696 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEED_RESYNC_ORIGINAL;
3697 }
3698 else if (is_isolated_from_root) {
3699 CLOG_ERROR(
3700 &LOG_RESYNC,
3701 "ID override %s from library level %d still tagged as isolated from its hierarchy root, "
3702 "it should have been either properly resynced or removed at that point.",
3703 id->name,
3704 ID_IS_LINKED(id) ? id->lib->runtime->temp_index : 0);
3705 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT;
3706 }
3707 }
3709
3710 /* Delete 'isolated from root' remaining IDs tagged in above check loop. */
3712 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3713
3714 BLI_ghash_free(id_roots, nullptr, MEM_freeN);
3715
3716 /* In some fairly rare (and degenerate) cases, some root ID from other liboverrides may have been
3717 * freed, and therefore set to nullptr. Attempt to fix this as best as possible. */
3718 /* WARNING: Cannot use directly #BKE_lib_override_library_main_hierarchy_root_ensure here, as it
3719 * processes the whole Main content - only the IDs matching current resync scope should be
3720 * checked here. */
3721 {
3722 BKE_main_relations_create(bmain, 0);
3723 blender::Set<ID *> processed_ids;
3724
3725 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3726 if (lib_override_library_main_resync_id_skip_check(id, library_indirect_level)) {
3727 processed_ids.add(id);
3728 continue;
3729 }
3730
3732 }
3734
3736 }
3737
3738 if (do_reports_recursive_resync_timing) {
3740 }
3741
3742 return process_lib_level_again;
3743}
3744
3746{
3747 if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
3748 return IDWALK_RET_NOP;
3749 }
3750 ID *id_owner = cb_data->owner_id;
3751 ID *id = *cb_data->id_pointer;
3752 if (id != nullptr && ID_IS_LINKED(id) && id->lib != id_owner->lib) {
3753 const int owner_library_indirect_level = ID_IS_LINKED(id_owner) ?
3754 id_owner->lib->runtime->temp_index :
3755 0;
3756 if (owner_library_indirect_level > 100) {
3758 "Levels of indirect usages of libraries is way too high, there are most likely "
3759 "dependency loops, skipping further building loops (involves at least '%s' from "
3760 "'%s' and '%s' from '%s')",
3761 id_owner->name,
3762 id_owner->lib->filepath,
3763 id->name,
3764 id->lib->filepath);
3765 return IDWALK_RET_NOP;
3766 }
3767 if (owner_library_indirect_level > 90) {
3768 CLOG_WARN(
3769 &LOG_RESYNC,
3770 "Levels of indirect usages of libraries is suspiciously too high, there are most likely "
3771 "dependency loops (involves at least '%s' from '%s' and '%s' from '%s')",
3772 id_owner->name,
3773 id_owner->lib->filepath,
3774 id->name,
3775 id->lib->filepath);
3776 }
3777
3778 if (owner_library_indirect_level >= id->lib->runtime->temp_index) {
3779 id->lib->runtime->temp_index = owner_library_indirect_level + 1;
3780 *reinterpret_cast<bool *>(cb_data->user_data) = true;
3781 }
3782 }
3783 return IDWALK_RET_NOP;
3784}
3785
3793{
3795 /* index 0 is reserved for local data. */
3796 library->runtime->temp_index = 1;
3797 }
3798 bool do_continue = true;
3799 while (do_continue) {
3800 do_continue = false;
3801 ID *id;
3802 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3803 /* NOTE: In theory all non-liboverride IDs could be skipped here. This does not gives any
3804 * performances boost though, so for now keep it as is (i.e. also consider non-liboverride
3805 * relationships to establish libraries hierarchy). */
3807 bmain, id, lib_override_sort_libraries_func, &do_continue, IDWALK_READONLY);
3808 }
3810 }
3811
3812 int library_indirect_level_max = 0;
3814 library_indirect_level_max = std::max(library->runtime->temp_index,
3815 library_indirect_level_max);
3816 }
3817 return library_indirect_level_max;
3818}
3819
3821 Main *bmain,
3822 const blender::Map<Library *, Library *> *new_to_old_libraries_map,
3823 Scene *scene,
3824 ViewLayer *view_layer,
3825 BlendFileReadReport *reports)
3826{
3827 /* We use a specific collection to gather/store all 'orphaned' override collections and objects
3828 * generated by re-sync-process. This avoids putting them in scene's master collection. */
3829#define OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME "OVERRIDE_RESYNC_LEFTOVERS"
3830 Collection *override_resync_residual_storage = static_cast<Collection *>(BLI_findstring(
3832 if (override_resync_residual_storage != nullptr &&
3833 ID_IS_LINKED(override_resync_residual_storage))
3834 {
3835 override_resync_residual_storage = nullptr;
3836 }
3837 if (override_resync_residual_storage == nullptr) {
3838 override_resync_residual_storage = BKE_collection_add(
3840 /* Hide the collection from viewport and render. */
3841 override_resync_residual_storage->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER;
3842 }
3843 /* BKE_collection_add above could have tagged the view_layer out of sync. */
3844 BKE_view_layer_synced_ensure(scene, view_layer);
3845 const Object *old_active_object = BKE_view_layer_active_object_get(view_layer);
3846
3847 /* Necessary to improve performances, and prevent layers matching override sub-collections to be
3848 * lost when re-syncing the parent override collection.
3849 * Ref. #73411. */
3851
3852 int library_indirect_level = lib_override_libraries_index_define(bmain);
3853 while (library_indirect_level >= 0) {
3854 int level_reprocess_count = 0;
3855 /* Update overrides from each indirect level separately.
3856 *
3857 * About the looping here: It may happen that some sub-hierarchies of liboverride are moved
3858 * around (the hierarchy in reference data does not match anymore the existing one in
3859 * liboverride data). In some cases, these sub-hierarchies won't be resynced then. If some IDs
3860 * in these sub-hierarchies actually do need resync, then the whole process needs to be applied
3861 * again, until all cases are fully processed.
3862 *
3863 * In practice, even in very complex and 'dirty'/outdated production files, typically less than
3864 * ten reprocesses are enough to cover all cases (in the vast majority of cases, no reprocess
3865 * is needed at all). */
3867 bmain,
3868 new_to_old_libraries_map,
3869 scene,
3870 view_layer,
3871 override_resync_residual_storage,
3872 library_indirect_level,
3873 reports))
3874 {
3875 level_reprocess_count++;
3876 if (level_reprocess_count > 100) {
3877 CLOG_WARN(
3878 &LOG_RESYNC,
3879 "Need to reprocess resync for library level %d more than %d times, aborting. This is "
3880 "either caused by extremely complex liboverride hierarchies, or a bug",
3881 library_indirect_level,
3882 level_reprocess_count);
3883 break;
3884 }
3886 "Applying reprocess %d for resyncing at library level %d",
3887 level_reprocess_count,
3888 library_indirect_level);
3889 }
3890 library_indirect_level--;
3891 }
3892
3894
3895 /* Essentially ensures that potentially new overrides of new objects will be instantiated. */
3897 scene,
3898 view_layer,
3899 nullptr,
3900 nullptr,
3901 nullptr,
3902 override_resync_residual_storage,
3903 old_active_object,
3904 true);
3905
3906 if (BKE_collection_is_empty(override_resync_residual_storage)) {
3907 BKE_collection_delete(bmain, override_resync_residual_storage, true);
3908 }
3909
3911 if (library->runtime->tag & LIBRARY_TAG_RESYNC_REQUIRED) {
3913 "library '%s' contains some linked overrides that required recursive resync, "
3914 "consider updating it",
3915 library->filepath);
3916 }
3917 }
3918
3919 /* Cleanup global namemap, to avoid extra processing with regular ID name management. Better to
3920 * re-create the global namemap on demand. */
3922
3924
3926}
3927
3929{
3931
3932 /* Tag all library overrides in the chains of dependencies from the given root one. */
3933 BKE_main_relations_create(bmain, 0);
3935 data.bmain = bmain;
3936 data.scene = nullptr;
3937 data.tag = ID_TAG_DOIT;
3938 data.missing_tag = ID_TAG_MISSING;
3939 data.is_override = true;
3940 data.is_resync = false;
3941
3942 data.root_set(id_root);
3943 data.hierarchy_root_set(id_root->override_library->hierarchy_root);
3944
3947
3949 data.clear();
3950
3951 ID *id;
3952 FOREACH_MAIN_ID_BEGIN (bmain, id) {
3953 if (id->tag & ID_TAG_DOIT) {
3955 ID *id_override_reference = id->override_library->reference;
3956
3957 /* Remap the whole local IDs to use the linked data. */
3958 BKE_libblock_remap(bmain, id, id_override_reference, ID_REMAP_SKIP_INDIRECT_USAGE);
3959 }
3960 }
3961 }
3963
3964 /* Delete the override IDs. */
3966
3967 /* Should not actually be needed here. */
3968 BKE_main_id_tag_all(bmain, ID_TAG_DOIT, false);
3969}
3970
3972{
3974 /* We should never directly 'make local' virtual overrides (aka shape keys). */
3977 return;
3978 }
3979 /* Cannot use `ID_IS_OVERRIDE_LIBRARY` here, as we may call this function on some already
3980 * partially processed liboverrides (e.g. from the #PartialWriteContext code), where the linked
3981 * reference pointer has already been set to null. */
3982 if (!id->override_library) {
3983 return;
3984 }
3985
3986 BKE_lib_override_library_free(&id->override_library, true);
3987
3988 Key *shape_key = BKE_key_from_id(id);
3989 if (shape_key != nullptr) {
3991 }
3992
3993 if (GS(id->name) == ID_SCE) {
3994 Collection *master_collection = reinterpret_cast<Scene *>(id)->master_collection;
3995 if (master_collection != nullptr) {
3996 master_collection->id.flag &= ~ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE;
3997 }
3998 }
3999
4001 if (node_tree != nullptr) {
4003 }
4004
4005 /* In case a liboverride hierarchy root is 'made local', i.e. is not a liboverride anymore, all
4006 * hierarchy roots of all liboverrides need to be validated/re-generated again.
4007 * Only in case `bmain` is given, otherwise caller is responsible to do this. */
4008 if (bmain) {
4010 }
4011}
4012
4013/* We only build override GHash on request. */
4015{
4017 if (liboverride_runtime->rna_path_to_override_properties == nullptr) {
4018 liboverride_runtime->rna_path_to_override_properties = BLI_ghash_new(
4020 for (IDOverrideLibraryProperty *op =
4021 static_cast<IDOverrideLibraryProperty *>(liboverride->properties.first);
4022 op != nullptr;
4023 op = op->next)
4024 {
4025 BLI_ghash_insert(liboverride_runtime->rna_path_to_override_properties, op->rna_path, op);
4026 }
4027 }
4028
4029 return liboverride_runtime->rna_path_to_override_properties;
4030}
4031
4033 const char *rna_path)
4034{
4036 return static_cast<IDOverrideLibraryProperty *>(BLI_ghash_lookup(liboverride_runtime, rna_path));
4037}
4038
4040 const char *rna_path,
4041 bool *r_created)
4042{
4044
4045 if (op == nullptr) {
4047 op->rna_path = BLI_strdup(rna_path);
4048 BLI_addtail(&liboverride->properties, op);
4049
4051 BLI_ghash_insert(liboverride_runtime, op->rna_path, op);
4052
4053 if (r_created) {
4054 *r_created = true;
4055 }
4056 }
4057 else if (r_created) {
4058 *r_created = false;
4059 }
4060
4061 return op;
4062}
4063
4065 const IDOverrideLibraryProperty *library_prop,
4066 PointerRNA *r_override_poin,
4067 PropertyRNA **r_override_prop,
4068 int *r_index)
4069{
4072 idpoin, library_prop->rna_path, r_override_poin, r_override_prop, r_index);
4073}
4074
4077{
4078 op_dst->rna_path = BLI_strdup(op_src->rna_path);
4079 BLI_duplicatelist(&op_dst->operations, &op_src->operations);
4080
4082 opop_dst = static_cast<IDOverrideLibraryPropertyOperation *>(op_dst->operations.first),
4083 *opop_src = static_cast<IDOverrideLibraryPropertyOperation *>(op_src->operations.first);
4084 opop_dst;
4085 opop_dst = opop_dst->next, opop_src = opop_src->next)
4086 {
4088 }
4089}
4090
4102
4104 const char *old_rna_path,
4105 const char *new_rna_path)
4106{
4107 /* Find the override property by its old RNA path. */
4109 IDOverrideLibraryProperty *liboverride_property = static_cast<IDOverrideLibraryProperty *>(
4110 BLI_ghash_popkey(liboverride_runtime, old_rna_path, nullptr));
4111
4112 if (liboverride_property == nullptr) {
4113 return false;
4114 }
4115
4116 /* Switch over the RNA path. */
4117 MEM_SAFE_FREE(liboverride_property->rna_path);
4118 liboverride_property->rna_path = BLI_strdup(new_rna_path);
4119
4120 /* Put property back into the lookup mapping, using the new RNA path. */
4121 BLI_ghash_insert(liboverride_runtime, liboverride_property->rna_path, liboverride_property);
4122
4123 return true;
4124}
4125
4127 IDOverrideLibraryProperty *liboverride_property,
4128 const bool do_runtime_updates)
4129{
4130 if (do_runtime_updates &&
4131 !ELEM(nullptr, liboverride->runtime, liboverride->runtime->rna_path_to_override_properties))
4132 {
4133 BLI_ghash_remove(liboverride->runtime->rna_path_to_override_properties,
4134 liboverride_property->rna_path,
4135 nullptr,
4136 nullptr);
4137 }
4138 lib_override_library_property_clear(liboverride_property);
4139 BLI_freelinkN(&liboverride->properties, liboverride_property);
4140}
4141
4143 const char *rna_path)
4144{
4145 /* Find the override property by its old RNA path. */
4147 IDOverrideLibraryProperty *liboverride_property = static_cast<IDOverrideLibraryProperty *>(
4148 BLI_ghash_popkey(liboverride_runtime, rna_path, nullptr));
4149
4150 if (liboverride_property == nullptr) {
4151 return false;
4152 }
4153
4154 /* The key (rna_path) was already popped out of the runtime mapping above. */
4155 lib_override_library_property_delete(liboverride, liboverride_property, false);
4156 return true;
4157}
4158
4164
4166 ListBase *liboverride_operations,
4167 const char *subitem_main_name,
4168 const char *subitem_other_name,
4169 const std::optional<const ID *> &subitem_main_id,
4170 const std::optional<const ID *> &subitem_other_id,
4171 const size_t offesetof_opop_main_name,
4172 const size_t offesetof_opop_other_name,
4173 const size_t offesetof_opop_main_id,
4174 const size_t offesetof_opop_other_id)
4175{
4176 const bool do_ids(subitem_main_id);
4178 for (opop = static_cast<IDOverrideLibraryPropertyOperation *>(BLI_findstring_ptr(
4179 liboverride_operations, subitem_main_name, int(offesetof_opop_main_name)));
4180 opop;
4182 reinterpret_cast<Link *>(opop), subitem_main_name, int(offesetof_opop_main_name))))
4183 {
4184 const char *opop_other_name = *reinterpret_cast<const char **>(reinterpret_cast<char *>(opop) +
4185 offesetof_opop_other_name);
4186 const bool opop_use_id = (opop->flag & LIBOVERRIDE_OP_FLAG_IDPOINTER_ITEM_USE_ID) != 0;
4187
4188 if (do_ids && opop_use_id) {
4189 /* Skip if ID pointers are expected valid and they do not exactly match. */
4190 const ID *opop_main_id = *reinterpret_cast<const ID **>(reinterpret_cast<char *>(opop) +
4191 offesetof_opop_main_id);
4192 if (*subitem_main_id != opop_main_id) {
4193 continue;
4194 }
4195 const ID *opop_other_id = *reinterpret_cast<const ID **>(reinterpret_cast<char *>(opop) +
4196 offesetof_opop_other_id);
4197 if (*subitem_other_id != opop_other_id) {
4198 continue;
4199 }
4200 }
4201
4202 /* Only check other name if ID handling is matching between given search parameters and
4203 * current liboverride operation (i.e. if both have valid ID pointers, or both have none). */
4204 if ((do_ids && opop_use_id) || (!do_ids && !opop_use_id)) {
4205 if (!subitem_other_name && !opop_other_name) {
4206 return opop;
4207 }
4208 if (subitem_other_name && opop_other_name && STREQ(subitem_other_name, opop_other_name)) {
4209 return opop;
4210 }
4211 }
4212
4213 /* No exact match found, keep checking the rest of the list of operations. */
4214 }
4215
4216 return nullptr;
4217}
4218
4220 IDOverrideLibraryProperty *liboverride_property,
4221 const char *subitem_refname,
4222 const char *subitem_locname,
4223 const std::optional<const ID *> &subitem_refid,
4224 const std::optional<const ID *> &subitem_locid,
4225 const int subitem_refindex,
4226 const int subitem_locindex,
4227 const bool strict,
4228 bool *r_strict)
4229{
4230 BLI_assert(!subitem_refid == !subitem_locid);
4231
4233 const int subitem_defindex = -1;
4234
4235 if (r_strict) {
4236 *r_strict = true;
4237 }
4238
4239 if (subitem_locname != nullptr) {
4241 &liboverride_property->operations,
4242 subitem_locname,
4243 subitem_refname,
4244 subitem_locid,
4245 subitem_refid,
4246 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_name),
4247 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_name),
4249 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_id));
4250
4251 if (opop != nullptr) {
4252 return opop;
4253 }
4254 }
4255
4256 if (subitem_refname != nullptr) {
4258 &liboverride_property->operations,
4259 subitem_refname,
4260 subitem_locname,
4261 subitem_refid,
4262 subitem_locid,
4263 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_name),
4264 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_name),
4265 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_id),
4266 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_id));
4267
4268 if (opop != nullptr) {
4269 return opop;
4270 }
4271 }
4272
4273 opop = static_cast<IDOverrideLibraryPropertyOperation *>(
4274 BLI_listbase_bytes_find(&liboverride_property->operations,
4275 &subitem_locindex,
4276 sizeof(subitem_locindex),
4277 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_index)));
4278 if (opop) {
4279 return ELEM(subitem_refindex, -1, opop->subitem_reference_index) ? opop : nullptr;
4280 }
4281
4283 &liboverride_property->operations,
4284 &subitem_refindex,
4285 sizeof(subitem_refindex),
4286 offsetof(IDOverrideLibraryPropertyOperation, subitem_reference_index)));
4287 if (opop) {
4288 return ELEM(subitem_locindex, -1, opop->subitem_local_index) ? opop : nullptr;
4289 }
4290
4291 /* `index == -1` means all indices, that is a valid fallback in case we requested specific index.
4292 */
4293 if (!strict && (subitem_locindex != subitem_defindex)) {
4295 &liboverride_property->operations,
4296 &subitem_defindex,
4297 sizeof(subitem_defindex),
4298 offsetof(IDOverrideLibraryPropertyOperation, subitem_local_index)));
4299 if (opop) {
4300 if (r_strict) {
4301 *r_strict = false;
4302 }
4303 return opop;
4304 }
4305 }
4306
4307 return nullptr;
4308}
4309
4311 IDOverrideLibraryProperty *liboverride_property,
4312 const short operation,
4313 const char *subitem_refname,
4314 const char *subitem_locname,
4315 const std::optional<ID *> &subitem_refid,
4316 const std::optional<ID *> &subitem_locid,
4317 const int subitem_refindex,
4318 const int subitem_locindex,
4319 const bool strict,
4320 bool *r_strict,
4321 bool *r_created)
4322{
4323 BLI_assert(!subitem_refid == !subitem_locid);
4324
4326 liboverride_property,
4327 subitem_refname,
4328 subitem_locname,
4329 subitem_refid,
4330 subitem_locid,
4331 subitem_refindex,
4332 subitem_locindex,
4333 strict,
4334 r_strict);
4335
4336 if (opop == nullptr) {
4338 opop->operation = operation;
4339 if (subitem_locname) {
4340 opop->subitem_local_name = BLI_strdup(subitem_locname);
4341 }
4342 if (subitem_refname) {
4343 opop->subitem_reference_name = BLI_strdup(subitem_refname);
4344 }
4345 opop->subitem_local_index = subitem_locindex;
4346 opop->subitem_reference_index = subitem_refindex;
4347
4348 if (subitem_refid) {
4349 opop->subitem_reference_id = *subitem_refid;
4350 opop->subitem_local_id = *subitem_locid;
4352 }
4353
4354 BLI_addtail(&liboverride_property->operations, opop);
4355
4356 if (r_created) {
4357 *r_created = true;
4358 }
4359 }
4360 else if (r_created) {
4361 *r_created = false;
4362 }
4363
4364 return opop;
4365}
4366
4377
4387
4389 IDOverrideLibraryProperty *liboverride_property,
4390 IDOverrideLibraryPropertyOperation *liboverride_property_operation)
4391{
4392 lib_override_library_property_operation_clear(liboverride_property_operation);
4393 BLI_freelinkN(&liboverride_property->operations, liboverride_property_operation);
4394}
4395
4397 IDOverrideLibraryPropertyOperation *liboverride_property_operation,
4398 PointerRNA *ptr_dst,
4399 PointerRNA *ptr_src,
4400 PointerRNA *ptr_storage,
4401 PropertyRNA *prop_dst,
4402 PropertyRNA *prop_src,
4403 PropertyRNA *prop_storage)
4404{
4405 switch (liboverride_property_operation->operation) {
4407 return true;
4408 case LIBOVERRIDE_OP_ADD:
4413 if (ptr_storage == nullptr || ptr_storage->data == nullptr || prop_storage == nullptr) {
4414 BLI_assert_msg(0, "Missing data to apply differential override operation.");
4415 return false;
4416 }
4423 if ((ptr_dst == nullptr || ptr_dst->data == nullptr || prop_dst == nullptr) ||
4424 (ptr_src == nullptr || ptr_src->data == nullptr || prop_src == nullptr))
4425 {
4426 BLI_assert_msg(0, "Missing data to apply override operation.");
4427 return false;
4428 }
4429 }
4430
4431 return true;
4432}
4433
4434static bool override_library_is_valid(const ID &id,
4436 ReportList *reports)
4437{
4438 if (liboverride.reference == nullptr) {
4439 /* This (probably) used to be a template ID, could be linked or local, not an override. */
4440 BKE_reportf(reports,
4442 "Library override templates have been removed: removing all override data from "
4443 "the data-block '%s'",
4444 id.name);
4445 return false;
4446 }
4447 if (liboverride.reference == &id) {
4448 /* Very serious data corruption, cannot do much about it besides removing the liboverride data.
4449 */
4450 BKE_reportf(reports,
4451 RPT_ERROR,
4452 "Data corruption: data-block '%s' is using itself as library override reference, "
4453 "removing all override data",
4454 id.name);
4455 return false;
4456 }
4457 if (!ID_IS_LINKED(liboverride.reference)) {
4458 /* Very serious data corruption, cannot do much about it besides removing the liboverride data.
4459 */
4460 BKE_reportf(reports,
4461 RPT_ERROR,
4462 "Data corruption: data-block '%s' is using another local data-block ('%s') as "
4463 "library override reference, removing all override data",
4464 id.name,
4465 liboverride.reference->name);
4466 return false;
4467 }
4468 return true;
4469}
4470
4474 ReportList *reports)
4475{
4477 if (!op->rna_path) {
4479 reports,
4480 RPT_ERROR,
4481 "Data corruption: data-block `%s` has a Library Override property with no RNA path",
4482 id.name);
4483 /* Simpler to allocate a dummy string here, than fix all 'normal' clearing/deletion code that
4484 * does expect a non-null RNA path. */
4485 op->rna_path = BLI_strdup("");
4487 }
4488 }
4489}
4490
4492{
4493 /* Do NOT use `ID_IS_OVERRIDE_LIBRARY` here, since this code also needs to fix broken cases (like
4494 * null reference pointer), which would be skipped by that macro. */
4495 if (id->override_library == nullptr && !ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)) {
4496 return;
4497 }
4498
4499 ID *liboverride_id = id;
4500 IDOverrideLibrary *liboverride = id->override_library;
4502 liboverride = BKE_lib_override_library_get(bmain, id, nullptr, &liboverride_id);
4503 if (!liboverride || !override_library_is_valid(*liboverride_id, *liboverride, reports)) {
4504 /* Happens in case the given ID is a liboverride-embedded one (actual embedded ID like
4505 * NodeTree or master collection, or shape-keys), used by a totally not-liboverride owner ID.
4506 * Just clear the relevant ID flag.
4507 */
4509 return;
4510 }
4511 }
4513
4514 /* NOTE: In code deleting liboverride data below, #BKE_lib_override_library_make_local is used
4515 * instead of directly calling #BKE_lib_override_library_free, because the former also handles
4516 * properly 'liboverride embedded' IDs, like root node-trees, or shape-keys. */
4517 if (!override_library_is_valid(*liboverride_id, *liboverride, reports)) {
4518 BKE_lib_override_library_make_local(nullptr, liboverride_id);
4519 return;
4520 }
4521
4522 override_library_properties_validate(*liboverride_id, *liboverride, reports);
4523}
4524
4526{
4527 ID *id;
4528
4529 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4530 BKE_lib_override_library_validate(bmain, id, reports);
4531 }
4533}
4534
4536{
4538
4539 ID *reference = local->override_library->reference;
4540
4541 BLI_assert(reference);
4542 BLI_assert(GS(local->name) == GS(reference->name));
4543
4544 if (GS(local->name) == ID_OB) {
4545 /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would
4546 * ensure this is valid, but in some situations (like hidden collections etc.) this won't
4547 * be the case, so we need to take care of this ourselves. */
4548 Object *ob_local = reinterpret_cast<Object *>(local);
4549 if (ob_local->type == OB_ARMATURE) {
4550 Object *ob_reference = reinterpret_cast<Object *>(local->override_library->reference);
4551 BLI_assert(ob_local->data != nullptr);
4552 BLI_assert(ob_reference->data != nullptr);
4553 BKE_pose_ensure(bmain, ob_local, static_cast<bArmature *>(ob_local->data), true);
4554 BKE_pose_ensure(bmain, ob_reference, static_cast<bArmature *>(ob_reference->data), true);
4555 }
4556 }
4557
4558 /* Note that reference is assumed always valid, caller has to ensure that itself. */
4559
4560 PointerRNA rnaptr_local = RNA_id_pointer_create(local);
4561 PointerRNA rnaptr_reference = RNA_id_pointer_create(reference);
4562
4564 bmain,
4565 &rnaptr_local,
4566 &rnaptr_reference,
4567 nullptr,
4568 0,
4569 local->override_library,
4571 nullptr))
4572 {
4574 return false;
4575 }
4576
4577 return true;
4578}
4579
4581{
4583
4584 ID *reference = local->override_library->reference;
4585
4586 BLI_assert(reference);
4587 BLI_assert(GS(local->name) == GS(reference->name));
4588
4589 if (reference->override_library && (reference->tag & ID_TAG_LIBOVERRIDE_REFOK) == 0) {
4590 if (!BKE_lib_override_library_status_check_reference(bmain, reference)) {
4591 /* If reference is also an override of another data-block, and its status is not OK,
4592 * then this override is not OK either.
4593 * Note that this should only happen when reloading libraries. */
4595 return false;
4596 }
4597 }
4598
4599 if (GS(local->name) == ID_OB) {
4600 /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would
4601 * ensure this is valid, but in some situations (like hidden collections etc.) this won't
4602 * be the case, so we need to take care of this ourselves. */
4603 Object *ob_local = reinterpret_cast<Object *>(local);
4604 if (ob_local->type == OB_ARMATURE) {
4605 Object *ob_reference = reinterpret_cast<Object *>(local->override_library->reference);
4606 BLI_assert(ob_local->data != nullptr);
4607 BLI_assert(ob_reference->data != nullptr);
4608 BKE_pose_ensure(bmain, ob_local, static_cast<bArmature *>(ob_local->data), true);
4609 BKE_pose_ensure(bmain, ob_reference, static_cast<bArmature *>(ob_reference->data), true);
4610 }
4611 }
4612
4613 PointerRNA rnaptr_local = RNA_id_pointer_create(local);
4614 PointerRNA rnaptr_reference = RNA_id_pointer_create(reference);
4615
4616 if (!RNA_struct_override_matches(bmain,
4617 &rnaptr_local,
4618 &rnaptr_reference,
4619 nullptr,
4620 0,
4621 local->override_library,
4623 nullptr))
4624 {
4626 return false;
4627 }
4628
4629 return true;
4630}
4631
4633 ID *local,
4634 const eRNAOverrideMatch liboverride_match_flags,
4635 eRNAOverrideMatchResult *r_report_flags)
4636{
4637 BLI_assert(!ID_IS_LINKED(local));
4639
4640 /* Do not attempt to generate overriding rules from an empty place-holder generated by link
4641 * code when it cannot find the actual library/ID. Much better to keep the local data-block as
4642 * is in the file in that case, until broken lib is fixed. */
4643 if (ID_MISSING(local->override_library->reference)) {
4644 return;
4645 }
4646
4647 if (GS(local->name) == ID_OB) {
4648 /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would
4649 * ensure this is valid, but in some situations (like hidden collections etc.) this won't
4650 * be the case, so we need to take care of this ourselves. */
4651 Object *ob_local = reinterpret_cast<Object *>(local);
4652 if (ob_local->type == OB_ARMATURE) {
4653 Object *ob_reference = reinterpret_cast<Object *>(local->override_library->reference);
4654 BLI_assert(ob_local->data != nullptr);
4655 BLI_assert(ob_reference->data != nullptr);
4656 BKE_pose_ensure(bmain, ob_local, static_cast<bArmature *>(ob_local->data), true);
4657 BKE_pose_ensure(bmain, ob_reference, static_cast<bArmature *>(ob_reference->data), true);
4658 }
4659 }
4660
4661 PointerRNA rnaptr_local = RNA_id_pointer_create(local);
4662 PointerRNA rnaptr_reference = RNA_id_pointer_create(local->override_library->reference);
4663
4666 &rnaptr_local,
4667 &rnaptr_reference,
4668 nullptr,
4669 0,
4670 local->override_library,
4671 liboverride_match_flags,
4672 &local_report_flags);
4673
4674 if (local_report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORED) {
4675 CLOG_DEBUG(&LOG, "We did restore some properties of %s from its reference", local->name);
4676 }
4677 if (local_report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORE_TAGGED) {
4678 CLOG_DEBUG(
4679 &LOG, "We did tag some properties of %s for restoration from its reference", local->name);
4680 }
4681 if (local_report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) {
4682 CLOG_DEBUG(&LOG, "We did generate library override rules for %s", local->name);
4683 }
4684 else {
4685 CLOG_DEBUG(&LOG, "No new library override rules for %s", local->name);
4686 }
4687
4688 if (r_report_flags != nullptr) {
4689 *r_report_flags = (*r_report_flags | local_report_flags);
4690 }
4691}
4692void BKE_lib_override_library_operations_create(Main *bmain, ID *local, int *r_report_flags)
4693{
4695 bmain,
4696 local,
4698 reinterpret_cast<eRNAOverrideMatchResult *>(r_report_flags));
4699}
4700
4701void BKE_lib_override_library_operations_restore(Main *bmain, ID *local, int *r_report_flags)
4702{
4703 if (!ID_IS_OVERRIDE_LIBRARY_REAL(local) ||
4705 {
4706 return;
4707 }
4708
4709 PointerRNA rnaptr_src = RNA_id_pointer_create(local);
4712 bmain,
4713 &rnaptr_dst,
4714 &rnaptr_src,
4715 nullptr,
4716 local->override_library,
4719
4721 {
4722 if (op->tag & LIBOVERRIDE_PROP_TAG_NEEDS_RETORE) {
4724 if (opop->tag & LIBOVERRIDE_PROP_TAG_NEEDS_RETORE) {
4726 }
4727 }
4730 }
4731 else {
4733 }
4734 }
4735 }
4737
4738 if (r_report_flags != nullptr) {
4739 *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED;
4740 }
4741}
4742
4747
4748static void lib_override_library_operations_create_cb(TaskPool *__restrict pool, void *taskdata)
4749{
4750 LibOverrideOpCreateData *create_data = static_cast<LibOverrideOpCreateData *>(
4752 ID *id = static_cast<ID *>(taskdata);
4753
4756 create_data->bmain,
4757 id,
4759 &report_flags);
4760 atomic_fetch_and_or_uint32(reinterpret_cast<uint32_t *>(&create_data->report_flags),
4761 report_flags);
4762}
4763
4765 const bool force_auto,
4766 int *r_report_flags)
4767{
4768 ID *id;
4769
4770#ifdef DEBUG_OVERRIDE_TIMEIT
4772#endif
4773
4774 /* When force-auto is set, we also remove all unused existing override properties & operations.
4775 */
4776 if (force_auto) {
4778 }
4779
4780 /* Usual pose bones issue, need to be done outside of the threaded process or we may run into
4781 * concurrency issues here.
4782 * Note that calling #BKE_pose_ensure again in thread in
4783 * #BKE_lib_override_library_operations_create is not a problem then. */
4784 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
4785 if (ob->type == OB_ARMATURE) {
4786 BLI_assert(ob->data != nullptr);
4787 BKE_pose_ensure(bmain, ob, static_cast<bArmature *>(ob->data), true);
4788 }
4789 }
4790
4791 LibOverrideOpCreateData create_pool_data{};
4792 create_pool_data.bmain = bmain;
4795
4796 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4797 if (ID_IS_LINKED(id) || !ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
4798 continue;
4799 }
4800 /* Propagate potential embedded data tag to the owner ID (see also
4801 * #BKE_lib_override_id_tag_on_deg_tag_from_user). */
4802 if (Key *key = BKE_key_from_id(id)) {
4803 if (key->id.tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH) {
4804 key->id.tag &= ~ID_TAG_LIBOVERRIDE_AUTOREFRESH;
4806 }
4807 }
4808 if (bNodeTree *ntree = blender::bke::node_tree_from_id(id)) {
4809 if (ntree->id.tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH) {
4810 ntree->id.tag &= ~ID_TAG_LIBOVERRIDE_AUTOREFRESH;
4812 }
4813 }
4814 if (GS(id->name) == ID_SCE) {
4815 if (Collection *scene_collection = reinterpret_cast<Scene *>(id)->master_collection) {
4816 if (scene_collection->id.tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH) {
4817 scene_collection->id.tag &= ~ID_TAG_LIBOVERRIDE_AUTOREFRESH;
4819 }
4820 }
4821 }
4822
4823 if (force_auto || (id->tag & ID_TAG_LIBOVERRIDE_AUTOREFRESH)) {
4824 /* Usual issue with pose, it's quiet rare but sometimes they may not be up to date when this
4825 * function is called. */
4826 if (GS(id->name) == ID_OB) {
4827 Object *ob = reinterpret_cast<Object *>(id);
4828 if (ob->type == OB_ARMATURE) {
4829 BLI_assert(ob->data != nullptr);
4830 BKE_pose_ensure(bmain, ob, static_cast<bArmature *>(ob->data), true);
4831 }
4832 }
4833 /* Only check overrides if we do have the real reference data available, and not some empty
4834 * 'placeholder' for missing data (broken links). */
4835 if ((id->override_library->reference->tag & ID_TAG_MISSING) == 0) {
4838 }
4839 else {
4841 id->override_library, LIBOVERRIDE_PROP_OP_TAG_UNUSED, false);
4842 }
4843 }
4844 else {
4845 /* Clear 'unused' tag for un-processed IDs, otherwise e.g. linked overrides will loose their
4846 * list of overridden properties. */
4848 id->override_library, LIBOVERRIDE_PROP_OP_TAG_UNUSED, false);
4849 }
4851 }
4853
4855
4857
4860 bmain, reinterpret_cast<int *>(&create_pool_data.report_flags));
4861 create_pool_data.report_flags = (create_pool_data.report_flags &
4863 }
4864
4865 if (r_report_flags != nullptr) {
4866 *r_report_flags |= create_pool_data.report_flags;
4867 }
4868
4869 if (force_auto) {
4871 }
4872
4873#ifdef DEBUG_OVERRIDE_TIMEIT
4875#endif
4876}
4877
4879{
4880 ID *id;
4881
4882 FOREACH_MAIN_ID_BEGIN (bmain, id) {
4883 if (!(!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY_REAL(id) && id->override_library->runtime &&
4884 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_NEEDS_RESTORE) != 0))
4885 {
4886 continue;
4887 }
4888
4889 /* Only restore overrides if we do have the real reference data available, and not some empty
4890 * 'placeholder' for missing data (broken links). */
4891 if (id->override_library->reference->tag & ID_TAG_MISSING) {
4892 continue;
4893 }
4894
4895 BKE_lib_override_library_operations_restore(bmain, id, r_report_flags);
4896 }
4898}
4899
4901 ID *id_root,
4902 const bool do_reset_system_override)
4903{
4904 bool was_op_deleted = false;
4905
4906 if (do_reset_system_override) {
4908 }
4909
4912 {
4913 bool do_op_delete = true;
4914 const bool is_collection = op->rna_prop_type == PROP_COLLECTION;
4915 if (is_collection || op->rna_prop_type == PROP_POINTER) {
4916 PointerRNA ptr, ptr_lib;
4917 PropertyRNA *prop, *prop_lib;
4918
4919 PointerRNA ptr_root = RNA_pointer_create_discrete(id_root, &RNA_ID, id_root);
4921 id_root->override_library->reference, &RNA_ID, id_root->override_library->reference);
4922
4923 bool prop_exists = RNA_path_resolve_property(&ptr_root, op->rna_path, &ptr, &prop);
4924 if (prop_exists) {
4925 prop_exists = RNA_path_resolve_property(&ptr_root_lib, op->rna_path, &ptr_lib, &prop_lib);
4926
4927 if (prop_exists) {
4930 if (is_collection) {
4931 ptr.type = RNA_property_pointer_type(&ptr, prop);
4932 ptr_lib.type = RNA_property_pointer_type(&ptr_lib, prop_lib);
4933 }
4934 else {
4936 ptr_lib = RNA_property_pointer_get(&ptr_lib, prop_lib);
4937 }
4938 if (ptr.owner_id != nullptr && ptr_lib.owner_id != nullptr) {
4939 BLI_assert(ptr.type == ptr_lib.type);
4940 do_op_delete = !(RNA_struct_is_ID(ptr.type) &&
4941 ptr.owner_id->override_library != nullptr &&
4942 ptr.owner_id->override_library->reference == ptr_lib.owner_id);
4943 }
4944 }
4945 }
4946 }
4947
4948 if (do_op_delete) {
4950 was_op_deleted = true;
4951 }
4952 }
4953
4954 if (was_op_deleted) {
4957 id_root->override_library);
4958 liboverride_runtime->tag |= LIBOVERRIDE_TAG_NEEDS_RELOAD;
4959 }
4960
4961 return was_op_deleted;
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 if (lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override)) {
4973 if (id_root->override_library->runtime != nullptr &&
4975 {
4976 BKE_lib_override_library_update(bmain, id_root);
4978 }
4979 }
4980}
4981
4983 ID *id_root,
4984 const bool do_reset_system_override)
4985{
4986 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
4987 return;
4988 }
4989
4990 void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id_root);
4991 if (entry_vp == nullptr) {
4992 /* This ID is not used by nor using any other ID. */
4993 lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
4994 return;
4995 }
4996
4997 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(*entry_vp);
4999 /* This ID has already been processed. */
5000 return;
5001 }
5002
5003 lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
5004
5005 /* This way we won't process again that ID, should we encounter it again through another
5006 * relationship hierarchy. */
5008
5009 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
5010 to_id_entry = to_id_entry->next)
5011 {
5013 continue;
5014 }
5015 /* We only consider IDs from the same library. */
5016 if (*to_id_entry->id_pointer.to != nullptr) {
5017 ID *to_id = *to_id_entry->id_pointer.to;
5018 if (to_id->override_library != nullptr) {
5019 lib_override_library_id_hierarchy_recursive_reset(bmain, to_id, do_reset_system_override);
5020 }
5021 }
5022 }
5023}
5024
5026 ID *id_root,
5027 const bool do_reset_system_override)
5028{
5029 BKE_main_relations_create(bmain, 0);
5030
5031 lib_override_library_id_hierarchy_recursive_reset(bmain, id_root, do_reset_system_override);
5032
5034
5035 ID *id;
5036 FOREACH_MAIN_ID_BEGIN (bmain, id) {
5037 if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || id->override_library->runtime == nullptr ||
5038 (id->override_library->runtime->tag & LIBOVERRIDE_TAG_NEEDS_RELOAD) == 0)
5039 {
5040 continue;
5041 }
5043 id->override_library->runtime->tag &= ~LIBOVERRIDE_TAG_NEEDS_RELOAD;
5044 }
5046}
5047
5049 const short tag,
5050 const bool do_set)
5051{
5052 if (liboverride_property != nullptr) {
5053 if (do_set) {
5054 liboverride_property->tag |= tag;
5055 }
5056 else {
5057 liboverride_property->tag &= ~tag;
5058 }
5059
5061 IDOverrideLibraryPropertyOperation *, opop, &liboverride_property->operations)
5062 {
5063 if (do_set) {
5064 opop->tag |= tag;
5065 }
5066 else {
5067 opop->tag &= ~tag;
5068 }
5069 }
5070 }
5071}
5072
5074 const short tag,
5075 const bool do_set)
5076{
5077 if (liboverride != nullptr) {
5080 }
5081 }
5082}
5083
5084void BKE_lib_override_library_main_tag(Main *bmain, const short tag, const bool do_set)
5085{
5086 ID *id;
5087
5088 FOREACH_MAIN_ID_BEGIN (bmain, id) {
5089 if (ID_IS_OVERRIDE_LIBRARY(id)) {
5090 BKE_lib_override_library_properties_tag(id->override_library, tag, do_set);
5091 }
5092 }
5094}
5095
5097{
5098 if (ID_IS_OVERRIDE_LIBRARY_REAL(local)) {
5101 {
5102 if (op->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
5104 }
5105 else {
5107 if (opop->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
5109 }
5110 }
5111 if (BLI_listbase_is_empty(&op->operations)) {
5113 }
5114 }
5115 }
5116 }
5117}
5118
5120{
5121 ID *id;
5122
5123 FOREACH_MAIN_ID_BEGIN (bmain, id) {
5124 if (ID_IS_OVERRIDE_LIBRARY(id)) {
5126 }
5127 }
5129}
5130
5131static void lib_override_id_swap(Main *bmain, ID *id_local, ID *id_temp)
5132{
5133 /* Ensure ViewLayers are in sync in case a Scene is being swapped, and prevent any further resync
5134 * during the swapping itself. */
5135 if (GS(id_local->name) == ID_SCE) {
5136 BKE_scene_view_layers_synced_ensure(reinterpret_cast<Scene *>(id_local));
5137 BKE_scene_view_layers_synced_ensure(reinterpret_cast<Scene *>(id_temp));
5138 }
5140
5141 BKE_lib_id_swap(bmain, id_local, id_temp, true, 0);
5142 /* We need to keep these tags from temp ID into orig one.
5143 * ID swap does not swap most of ID data itself. */
5144 id_local->tag |= (id_temp->tag & ID_TAG_LIBOVERRIDE_NEED_RESYNC);
5145
5147}
5148
5150{
5151 if (!ID_IS_OVERRIDE_LIBRARY_REAL(local)) {
5152 return;
5153 }
5154
5155 /* Do not attempt to apply overriding rules over an empty place-holder generated by link code
5156 * when it cannot find the actual library/ID. Much better to keep the local data-block as loaded
5157 * from the file in that case, until broken lib is fixed. */
5158 if (ID_MISSING(local->override_library->reference)) {
5159 return;
5160 }
5161
5162 /* Recursively do 'ancestor' overrides first, if any. */
5165 {
5167 }
5168
5169 /* We want to avoid having to remap here, however creating up-to-date override is much simpler
5170 * if based on reference than on current override.
5171 * So we work on temp copy of reference, and 'swap' its content with local. */
5172
5173 /* XXX We need a way to get off-Main copies of IDs (similar to localized mats/texts/ etc.)!
5174 * However, this is whole bunch of code work in itself, so for now plain stupid ID copy
5175 * will do, as inefficient as it is. :/
5176 * Actually, maybe not! Since we are swapping with original ID's local content, we want to
5177 * keep user-count in correct state when freeing tmp_id
5178 * (and that user-counts of IDs used by 'new' local data also remain correct). */
5179 /* This would imply change in handling of user-count all over RNA
5180 * (and possibly all over Blender code).
5181 * Not impossible to do, but would rather see first if extra useless usual user handling
5182 * is actually a (performances) issue here. */
5183
5184 ID *tmp_id = BKE_id_copy_ex(bmain,
5186 nullptr,
5188
5189 if (tmp_id == nullptr) {
5190 return;
5191 }
5192
5193 /* Remove the pair (idname, lib) of this temp id from the name map. */
5194 BKE_main_namemap_remove_id(*bmain, *tmp_id);
5195
5196 tmp_id->lib = local->lib;
5197
5198 /* This ID name is problematic, since it is an 'rna name property' it should not be editable or
5199 * different from reference linked ID. But local ID names need to be unique in a given type
5200 * list of Main, so we cannot always keep it identical, which is why we need this special
5201 * manual handling here. */
5202 STRNCPY(tmp_id->name, local->name);
5203
5204 /* Those ugly loop-back pointers again. Luckily we only need to deal with the shape keys here,
5205 * collections' parents are fully runtime and reconstructed later. */
5206 Key *local_key = BKE_key_from_id(local);
5207 Key *tmp_key = BKE_key_from_id(tmp_id);
5208 if (local_key != nullptr && tmp_key != nullptr) {
5209 tmp_key->id.flag |= (local_key->id.flag & ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE);
5210 BKE_main_namemap_remove_id(*bmain, tmp_key->id);
5211 tmp_key->id.lib = local_key->id.lib;
5212 STRNCPY(tmp_key->id.name, local_key->id.name);
5213 }
5214
5215 PointerRNA rnaptr_src = RNA_id_pointer_create(local);
5216 PointerRNA rnaptr_dst = RNA_id_pointer_create(tmp_id);
5217
5219 &rnaptr_dst,
5220 &rnaptr_src,
5221 nullptr,
5222 local->override_library,
5224
5226
5227 /* This also transfers all pointers (memory) owned by local to tmp_id, and vice-versa.
5228 * So when we'll free tmp_id, we'll actually free old, outdated data from local. */
5229 lib_override_id_swap(bmain, local, tmp_id);
5230
5231 if (local_key != nullptr && tmp_key != nullptr) {
5232 /* This is some kind of hard-coded 'always enforced override'. */
5233 lib_override_id_swap(bmain, &local_key->id, &tmp_key->id);
5234 tmp_key->id.flag |= (local_key->id.flag & ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE);
5235 /* The swap of local and tmp_id inverted those pointers, we need to redefine proper
5236 * relationships. */
5237 *BKE_key_from_id_p(local) = local_key;
5238 *BKE_key_from_id_p(tmp_id) = tmp_key;
5239 local_key->from = local;
5240 tmp_key->from = tmp_id;
5241 }
5242
5243 /* Again, horribly inefficient in our case, we need something off-Main
5244 * (aka more generic nolib copy/free stuff).
5245 * NOTE: Do not remove this tmp_id's name from the namemap here, since this name actually still
5246 * exists in `bmain`. */
5248
5249 if (GS(local->name) == ID_AR) {
5250 /* Fun times again, thanks to bone pointers in pose data of objects. We keep same ID addresses,
5251 * but internal data has changed for sure, so we need to invalidate pose-bones caches. */
5252 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
5253 if (ob->pose != nullptr && ob->data == local) {
5254 BLI_assert(ob->type == OB_ARMATURE);
5255 ob->pose->flag |= POSE_RECALC;
5256 /* We need to clear pose bone pointers immediately, some code may access those before pose
5257 * is actually recomputed, which can lead to segfault. */
5258 BKE_pose_clear_pointers(ob->pose);
5259 }
5260 }
5261 }
5262
5263 /* NLA Tweak Mode is, in a way, an "edit mode" for certain animation data. However, contrary to
5264 * mesh/armature edit modes, it doesn't use its own runtime data, but directly changes various
5265 * DNA pointers & flags. As these need to be all consistently set for the system to behave in a
5266 * well-defined manner, and the values can come from different files (library NLA tracks/strips
5267 * vs. override-added NLA tracks/strips), they need to be checked _after_ all overrides have been
5268 * applied. */
5270
5271 local->tag |= ID_TAG_LIBOVERRIDE_REFOK;
5272
5273 /* NOTE: Since we reload full content from linked ID here, potentially from edited local
5274 * override, we do not really have a way to know *what* is changed, so we need to rely on the
5275 * massive destruction weapon of `ID_RECALC_ALL` here. */
5276 DEG_id_tag_update_ex(bmain, local, ID_RECALC_ALL);
5277 /* For same reason as above, also assume that the relationships between IDs changed. */
5279}
5280
5282{
5283 ID *id;
5284
5285 /* This temporary swap of G_MAIN is rather ugly,
5286 * but necessary to avoid asserts checks in some RNA assignment functions,
5287 * since those always use G_MAIN when they need access to a Main database. */
5288 Main *orig_gmain = BKE_blender_globals_main_swap(bmain);
5289
5291
5292 FOREACH_MAIN_ID_BEGIN (bmain, id) {
5293 if (id->override_library != nullptr) {
5295 }
5296 }
5298
5300
5301 Main *tmp_gmain = BKE_blender_globals_main_swap(orig_gmain);
5302 BLI_assert(tmp_gmain == bmain);
5303 UNUSED_VARS_NDEBUG(tmp_gmain);
5304}
5305
5307{
5308 /* The only strong known case currently are objects used by override collections. */
5309 /* TODO: There are most likely other cases... This may need to be addressed in a better way at
5310 * some point. */
5311 if (GS(id->name) != ID_OB) {
5312 return true;
5313 }
5314 Object *ob = reinterpret_cast<Object *>(id);
5315 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
5316 if (!ID_IS_OVERRIDE_LIBRARY(collection)) {
5317 continue;
5318 }
5319 if (BKE_collection_has_object(collection, ob)) {
5320 return false;
5321 }
5322 }
5323 return true;
5324}
5325
5327{
5328 const char *line_prefix = "";
5329 if (intro_txt != nullptr) {
5330 std::cout << intro_txt << "\n";
5331 line_prefix = "\t";
5332 }
5333
5335 std::cout << line_prefix << op->rna_path << " [";
5336 if (op->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
5337 std::cout << " UNUSED ";
5338 }
5339 std::cout << "]\n";
5340
5341 LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
5342 std::cout << line_prefix << line_prefix << opop->operation << " [";
5343 if (opop->tag & LIBOVERRIDE_PROP_OP_TAG_UNUSED) {
5344 std::cout << " UNUSED ";
5345 }
5347 std::cout << " MATCH_REF ";
5348 }
5349 std::cout << "] ";
5350 if (opop->subitem_reference_name || opop->subitem_local_name) {
5351 std::cout << "(" << opop->subitem_reference_name << " <" << opop->subitem_reference_id
5352 << "> -> " << opop->subitem_local_name << " <" << opop->subitem_local_id << ">)";
5353 }
5354 else if (opop->subitem_reference_index >= 0 || opop->subitem_local_index >= 0) {
5355 std::cout << "(" << opop->subitem_reference_index << " -> " << opop->subitem_local_index
5356 << ")";
5357 }
5358 std::cout << "\n";
5359 }
5360 }
5361}
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
void BKE_animdata_liboverride_post_process(ID *id)
void BKE_pose_clear_pointers(bPose *pose)
void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
Blender util stuff.
Main * BKE_blender_globals_main_swap(Main *new_gmain)
Definition blender.cc:236
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:197
Key ** BKE_key_from_id_p(ID *id)
Definition key.cc:1746
Key * BKE_key_from_id(ID *id)
Definition key.cc:1771
bool BKE_view_layer_has_collection(const ViewLayer *view_layer, const Collection *collection)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_layer_collection_resync_forbid()
void BKE_scene_view_layers_synced_ensure(const Scene *scene)
void BKE_main_collection_sync_remap(const Main *bmain)
void BKE_layer_collection_resync_allow()
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void BKE_main_collection_sync(const Main *bmain)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
void BKE_main_view_layers_synced_ensure(const Main *bmain)
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
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:675
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:358
void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
Definition lib_id.cc:1790
void id_fake_user_set(ID *id)
Definition lib_id.cc:396
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:1056
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:2001
ID * BKE_id_owner_get(ID *id, const bool debug_relationship_assert=true)
Definition lib_id.cc:2511
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
@ 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 id_us_min(ID *id)
Definition lib_id.cc:366
@ LIB_ID_FREE_NO_UI_USER
@ LIB_ID_FREE_NO_NAMEMAP_REMOVE
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:1123
void BKE_main_id_tag_all(Main *mainvar, int tag, bool value)
Definition lib_id.cc:1224
void BKE_lib_override_library_main_operations_create(Main *bmain, bool force_auto, int *r_report_flags)
@ IDWALK_RET_STOP_ITER
@ IDWALK_RET_NOP
void BKE_lib_query_unused_ids_tag(Main *bmain, int tag, LibQueryUnusedIDsData &parameters)
@ 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_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:792
@ 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:711
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:854
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:583
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:902
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:552
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:546
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:564
eMainIDRelationsEntryTags
Definition BKE_main.hh:87
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_TO
Definition BKE_main.hh:95
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED
Definition BKE_main.hh:102
@ MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS
Definition BKE_main.hh:121
@ MAINIDRELATIONS_ENTRY_TAGS_DOIT
Definition BKE_main.hh:89
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED_FROM
Definition BKE_main.hh:100
void BKE_main_relations_tag_set(Main *bmain, eMainIDRelationsEntryTags tag, bool value)
Definition main.cc:600
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:557
void BKE_main_relations_create(Main *bmain, short flag)
Definition main.cc:551
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
void BKE_main_relations_free(Main *bmain)
Definition main.cc:588
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
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
#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:693
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:550
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition task_pool.cc:535
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition task_pool.cc:484
void BLI_task_pool_free(TaskPool *pool)
Definition task_pool.cc:521
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition task_pool.cc:526
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
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:188
#define CLOG_DEBUG(clg_ref,...)
Definition CLG_log.h:191
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
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.
#define ID_IS_OVERRIDE_LIBRARY_VIRTUAL(_id)
Definition DNA_ID.h:727
@ ID_TAG_NO_USER_REFCOUNT
Definition DNA_ID.h:1018
@ ID_TAG_LIBOVERRIDE_AUTOREFRESH
Definition DNA_ID.h:897
@ ID_TAG_INDIRECT
Definition DNA_ID.h:848
@ ID_TAG_MISSING
Definition DNA_ID.h:867
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ ID_TAG_LIBOVERRIDE_NEED_RESYNC
Definition DNA_ID.h:906
@ ID_TAG_LIBOVERRIDE_REFOK
Definition DNA_ID.h:891
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:978
@ LIBOVERRIDE_TAG_NEEDS_RESTORE
Definition DNA_ID.h:316
@ LIBOVERRIDE_TAG_RESYNC_ISOLATED_FROM_ROOT
Definition DNA_ID.h:322
@ LIBOVERRIDE_TAG_NEEDS_RELOAD
Definition DNA_ID.h:310
@ LIBOVERRIDE_TAG_NEED_RESYNC_ORIGINAL
Definition DNA_ID.h:328
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1054
@ ID_RECALC_SELECT
Definition DNA_ID.h:1101
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_ALL
Definition DNA_ID.h:1188
@ ID_RECALC_BASE_FLAGS
Definition DNA_ID.h:1104
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:723
@ LIBOVERRIDE_OP_FLAG_IDPOINTER_ITEM_USE_ID
Definition DNA_ID.h:262
@ LIBOVERRIDE_OP_FLAG_IDPOINTER_MATCH_REFERENCE
Definition DNA_ID.h:256
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define MAX_ID_NAME
Definition DNA_ID.h:373
@ INDEX_ID_NULL
Definition DNA_ID.h:1357
@ LIBOVERRIDE_PROP_TAG_NEEDS_RETORE
Definition DNA_ID.h:297
@ LIBOVERRIDE_PROP_OP_TAG_UNUSED
Definition DNA_ID.h:294
#define ID_REAL_USERS(id)
Definition DNA_ID.h:676
@ LIBOVERRIDE_OP_NOOP
Definition DNA_ID.h:228
@ LIBOVERRIDE_OP_ADD
Definition DNA_ID.h:233
@ LIBOVERRIDE_OP_SUBTRACT
Definition DNA_ID.h:235
@ LIBOVERRIDE_OP_REPLACE
Definition DNA_ID.h:230
@ LIBOVERRIDE_OP_MULTIPLY
Definition DNA_ID.h:237
@ LIBOVERRIDE_OP_INSERT_BEFORE
Definition DNA_ID.h:241
@ LIBOVERRIDE_OP_INSERT_AFTER
Definition DNA_ID.h:240
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
@ LIBOVERRIDE_FLAG_NO_HIERARCHY
Definition DNA_ID.h:358
@ LIBOVERRIDE_FLAG_SYSTEM_DEFINED
Definition DNA_ID.h:363
@ ID_FLAG_EMBEDDED_DATA_LIB_OVERRIDE
Definition DNA_ID.h:785
@ ID_FLAG_LIB_OVERRIDE_RESYNC_LEFTOVER
Definition DNA_ID.h:790
#define ID_MISSING(_id)
Definition DNA_ID.h:692
@ 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_DEVELOPER_TOOL_TEST(userdef, member)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
eRNAOverrideApplyFlag
@ RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS
@ RNA_OVERRIDE_APPLY_FLAG_SKIP_RESYNC_CHECK
@ RNA_OVERRIDE_APPLY_FLAG_NOP
@ RNA_OVERRIDE_APPLY_FLAG_RESTORE_ONLY
eRNAOverrideMatch
@ RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN
@ RNA_OVERRIDE_COMPARE_CREATE
@ RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE
@ RNA_OVERRIDE_COMPARE_RESTORE
@ RNA_OVERRIDE_COMPARE_TAG_FOR_RESTORE
eRNAOverrideMatchResult
@ RNA_OVERRIDE_MATCH_RESULT_RESTORED
@ RNA_OVERRIDE_MATCH_RESULT_RESTORE_TAGGED
@ RNA_OVERRIDE_MATCH_RESULT_CREATED
@ RNA_OVERRIDE_MATCH_RESULT_INIT
@ PROP_POINTER
Definition RNA_types.hh:167
@ PROP_COLLECTION
Definition RNA_types.hh:168
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 GS(x)
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:487
static void lib_override_library_main_hierarchy_id_root_ensure(Main *bmain, ID *id, blender::Set< ID * > &processed_ids)
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)
#define LOG(level)
Definition log.h:97
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:4568
const char * name
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
LinkNode * resynced_lib_overrides_libraries
double lib_overrides_recursive_resync
struct BlendFileReadReport::@077003321007012203371307366200326111253233132273 duration
bool do_resynced_lib_overrides_libraries_list
int resynced_lib_overrides_libraries_count
struct BlendFileReadReport::@124362246150331065306145367225174223236260272332 count
struct CollectionChild * next
struct CollectionObject * next
struct IDOverrideLibraryPropertyOperation * next
Definition DNA_ID.h:194
struct IDOverrideLibraryProperty * next
Definition DNA_ID.h:267
struct GHash * rna_path_to_override_properties
Definition DNA_ID.h:303
ListBase properties
Definition DNA_ID.h:336
unsigned int flag
Definition DNA_ID.h:348
struct ID * hierarchy_root
Definition DNA_ID.h:344
struct ID * reference
Definition DNA_ID.h:334
IDOverrideLibraryRuntime * runtime
Definition DNA_ID.h:346
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
struct ID * newid
Definition DNA_ID.h:418
IDOverrideLibrary * override_library
Definition DNA_ID.h:494
short flag
Definition DNA_ID.h:438
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:552
LibraryRuntimeHandle * runtime
Definition DNA_ID.h:579
void * data
struct LinkData * next
LinkNode * last_node
LinkNode * list
void * link
struct LinkNode * next
void * first
MainIDRelationsEntryItem * next
Definition BKE_main.hh:58
LibraryForeachIDCallbackFlag usage_flag
Definition BKE_main.hh:70
MainIDRelationsEntryItem * from_ids
Definition BKE_main.hh:75
MainIDRelationsEntryItem * to_ids
Definition BKE_main.hh:77
GHash * relations_from_pointers
Definition BKE_main.hh:130
UniqueName_Map * name_map_global
Definition BKE_main.hh:341
ListBase libraries
Definition BKE_main.hh:279
ListBase collections
Definition BKE_main.hh:298
MainIDRelations * relations
Definition BKE_main.hh:329
ListBase objects
Definition BKE_main.hh:280
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:4238