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