Blender  V3.3
lib_remap.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include "CLG_log.h"
10 
11 #include "BLI_linklist.h"
12 #include "BLI_utildefines.h"
13 
14 #include "DNA_collection_types.h"
15 #include "DNA_object_types.h"
16 
17 #include "BKE_armature.h"
18 #include "BKE_collection.h"
19 #include "BKE_curve.h"
20 #include "BKE_layer.h"
21 #include "BKE_lib_id.h"
22 #include "BKE_lib_query.h"
23 #include "BKE_lib_remap.h"
24 #include "BKE_main.h"
25 #include "BKE_material.h"
26 #include "BKE_mball.h"
27 #include "BKE_modifier.h"
28 #include "BKE_multires.h"
29 #include "BKE_node.h"
30 #include "BKE_object.h"
31 
32 #include "DEG_depsgraph.h"
33 #include "DEG_depsgraph_build.h"
34 
35 #include "lib_intern.h" /* own include */
36 
37 static CLG_LogRef LOG = {.identifier = "bke.lib_remap"};
38 
40 
42 {
44 }
45 
47 
50 {
52 }
53 
54 typedef struct IDRemap {
56  Main *bmain; /* Only used to trigger depsgraph updates in the right bmain. */
57 
58  struct IDRemapper *id_remapper;
59 
62  short flag;
64 
65 /* IDRemap->flag enums defined in BKE_lib.h */
66 
67 static void foreach_libblock_remap_callback_skip(const ID *UNUSED(id_owner),
68  ID **id_ptr,
69  const int cb_flag,
70  const bool is_indirect,
71  const bool is_reference,
72  const bool violates_never_null,
73  const bool UNUSED(is_obj),
74  const bool is_obj_editmode)
75 {
76  ID *id = *id_ptr;
77  BLI_assert(id != NULL);
78 
79  if (is_indirect) {
80  id->runtime.remap.skipped_indirect++;
81  }
82  else if (violates_never_null || is_obj_editmode || is_reference) {
83  id->runtime.remap.skipped_direct++;
84  }
85  else {
87  }
88 
89  if (cb_flag & IDWALK_CB_USER) {
90  id->runtime.remap.skipped_refcounted++;
91  }
92  else if (cb_flag & IDWALK_CB_USER_ONE) {
93  /* No need to count number of times this happens, just a flag is enough. */
94  id->runtime.remap.status |= ID_REMAP_IS_USER_ONE_SKIPPED;
95  }
96 }
97 
99  ID *id_self,
100  ID **id_ptr,
101  IDRemap *id_remap_data,
102  const struct IDRemapper *mappings,
103  const IDRemapperApplyOptions id_remapper_options,
104  const int cb_flag,
105  const bool is_indirect,
106  const bool violates_never_null,
107  const bool force_user_refcount)
108 {
109  ID *old_id = *id_ptr;
110  if (!violates_never_null) {
111  BKE_id_remapper_apply_ex(mappings, id_ptr, id_remapper_options, id_self);
112  DEG_id_tag_update_ex(id_remap_data->bmain,
113  id_self,
115  if (id_self != id_owner) {
116  DEG_id_tag_update_ex(id_remap_data->bmain,
117  id_owner,
119  }
120  }
121  /* Get the new_id pointer. When the mapping is violating never null we should use a NULL
122  * pointer otherwise the incorrect users are decreased and increased on the same instance. */
123  ID *new_id = violates_never_null ? NULL : *id_ptr;
124 
125  if (cb_flag & IDWALK_CB_USER) {
126  /* NOTE: by default we don't user-count IDs which are not in the main database.
127  * This is because in certain conditions we can have data-blocks in
128  * the main which are referencing data-blocks outside of it.
129  * For example, BKE_mesh_new_from_object() called on an evaluated
130  * object will cause such situation.
131  */
132  if (force_user_refcount || (old_id->tag & LIB_TAG_NO_MAIN) == 0) {
133  id_us_min(old_id);
134  }
135  if (new_id != NULL && (force_user_refcount || (new_id->tag & LIB_TAG_NO_MAIN) == 0)) {
136  /* Do not handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */
137  id_us_plus_no_lib(new_id);
138  }
139  }
140  else if (cb_flag & IDWALK_CB_USER_ONE) {
141  id_us_ensure_real(new_id);
142  /* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET)
143  * are assumed to be set as needed, that extra user is processed in final handling. */
144  }
145  if (!is_indirect && new_id) {
147  }
148 }
149 
151 {
152  const int cb_flag = cb_data->cb_flag;
153 
154  if (cb_flag & IDWALK_CB_EMBEDDED) {
155  return IDWALK_RET_NOP;
156  }
157 
158  ID *id_owner = cb_data->id_owner;
159  ID *id_self = cb_data->id_self;
160  ID **id_p = cb_data->id_pointer;
161  IDRemap *id_remap_data = cb_data->user_data;
162 
163  /* Those asserts ensure the general sanity of ID tags regarding 'embedded' ID data (root
164  * nodetrees and co). */
165  BLI_assert(id_owner == id_remap_data->id_owner);
166  BLI_assert(id_self == id_owner || (id_self->flag & LIB_EMBEDDED_DATA) != 0);
167 
168  /* Early exit when id pointer isn't set. */
169  if (*id_p == NULL) {
170  return IDWALK_RET_NOP;
171  }
172 
173  struct IDRemapper *id_remapper = id_remap_data->id_remapper;
174  IDRemapperApplyOptions id_remapper_options = ID_REMAP_APPLY_DEFAULT;
175 
176  /* Used to cleanup all IDs used by a specific one. */
177  if (id_remap_data->type == ID_REMAP_TYPE_CLEANUP) {
178  /* Clearing existing instance to reduce potential lookup times for IDs referencing many other
179  * IDs. This makes sure that there will only be a single rule in the id_remapper. */
180  BKE_id_remapper_clear(id_remapper);
181  BKE_id_remapper_add(id_remapper, *id_p, NULL);
182  }
183 
184  /* Better remap to NULL than not remapping at all,
185  * then we can handle it as a regular remap-to-NULL case. */
186  if ((cb_flag & IDWALK_CB_NEVER_SELF)) {
187  id_remapper_options |= ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF;
188  }
189 
190  const IDRemapperApplyResult expected_mapping_result = BKE_id_remapper_get_mapping_result(
191  id_remapper, *id_p, id_remapper_options, id_self);
192  /* Exit, when no modifications will be done; ensuring id->runtime counters won't changed. */
193  if (ELEM(expected_mapping_result,
196  BLI_assert_msg(id_remap_data->type == ID_REMAP_TYPE_REMAP,
197  "Cleanup should always do unassign.");
198  return IDWALK_RET_NOP;
199  }
200 
201  const bool is_reference = (cb_flag & IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE) != 0;
202  const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
203  const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
204  const bool is_obj = (GS(id_owner->name) == ID_OB);
205  /* NOTE: Edit Mode is a 'skip direct' case, unless specifically requested, obdata should not be
206  * remapped in this situation. */
207  const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner) &&
208  (id_remap_data->flag & ID_REMAP_FORCE_OBDATA_IN_EDITMODE) == 0);
209  const bool violates_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) &&
210  (expected_mapping_result ==
212  (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
213  const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_OVERRIDE_LIBRARY) != 0;
214  const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
215  const bool force_user_refcount = (id_remap_data->flag & ID_REMAP_FORCE_USER_REFCOUNT) != 0;
216 
217 #ifdef DEBUG_PRINT
218  printf(
219  "In %s (lib %p): Remapping %s (%p) remap operation: %s "
220  "(is_indirect: %d, skip_indirect: %d, is_reference: %d, skip_reference: %d)\n",
221  id_owner->name,
222  id_owner->lib,
223  (*id_p)->name,
224  *id_p,
225  BKE_id_remapper_result_string(expected_mapping_result),
226  is_indirect,
227  skip_indirect,
228  is_reference,
229  skip_reference);
230 #endif
231 
232  if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) && (cb_flag & IDWALK_CB_NEVER_NULL)) {
233  id_owner->tag |= LIB_TAG_DOIT;
234  }
235 
236  /* Special hack in case it's Object->data and we are in edit mode, and new_id is not NULL
237  * (otherwise, we follow common NEVER_NULL flags).
238  * (skipped_indirect too). */
239  if ((violates_never_null && skip_never_null) ||
240  (is_obj_editmode && (((Object *)id_owner)->data == *id_p) &&
241  (expected_mapping_result == ID_REMAP_RESULT_SOURCE_REMAPPED)) ||
242  (skip_indirect && is_indirect) || (is_reference && skip_reference)) {
244  id_p,
245  cb_flag,
246  is_indirect,
247  is_reference,
248  violates_never_null,
249  is_obj,
250  is_obj_editmode);
251  }
252  else {
254  id_self,
255  id_p,
256  id_remap_data,
257  id_remapper,
258  id_remapper_options,
259  cb_flag,
260  is_indirect,
261  violates_never_null,
262  force_user_refcount);
263  }
264 
265  return IDWALK_RET_NOP;
266 }
267 
269  eIDRemapType remap_type,
270  const struct IDRemapper *id_remapper)
271 {
272  if (ob->type != OB_ARMATURE) {
273  return;
274  }
275  if (ob->pose == NULL) {
276  return;
277  }
278 
279  const bool is_cleanup_type = remap_type == ID_REMAP_TYPE_CLEANUP;
280  /* Early exit when mapping, but no armature mappings present. */
281  if (!is_cleanup_type && !BKE_id_remapper_has_mapping_for(id_remapper, FILTER_ID_AR)) {
282  return;
283  }
284 
285  /* Object's pose holds reference to armature bones. sic */
286  /* Note that in theory, we should have to bother about linked/non-linked/never-null/etc.
287  * flags/states.
288  * Fortunately, this is just a tag, so we can accept to 'over-tag' a bit for pose recalc,
289  * and avoid another complex and risky condition nightmare like the one we have in
290  * foreach_libblock_remap_callback(). */
291  const IDRemapperApplyResult expected_mapping_result = BKE_id_remapper_get_mapping_result(
292  id_remapper, ob->data, ID_REMAP_APPLY_DEFAULT, NULL);
293  if (is_cleanup_type || expected_mapping_result == ID_REMAP_RESULT_SOURCE_REMAPPED) {
294  ob->pose->flag |= POSE_RECALC;
295  /* We need to clear pose bone pointers immediately, some code may access those before
296  * pose is actually recomputed, which can lead to segfault. */
298  }
299 }
300 
301 static void libblock_remap_data_preprocess(ID *id_owner,
302  eIDRemapType remap_type,
303  const struct IDRemapper *id_remapper)
304 {
305  switch (GS(id_owner->name)) {
306  case ID_OB: {
307  Object *ob = (Object *)id_owner;
308  libblock_remap_data_preprocess_ob(ob, remap_type, id_remapper);
309  break;
310  }
311  default:
312  break;
313  }
314 }
315 
321  Object *old_ob,
322  Object *new_ob,
323  const bool do_sync_collection)
324 {
325  if (new_ob == NULL) {
326  /* In case we unlinked old_ob (new_ob is NULL), the object has already
327  * been removed from the scenes and their collections. We still have
328  * to remove the NULL children from collections not used in any scene. */
330  }
331  else {
332  /* Remapping may have created duplicates of CollectionObject pointing to the same object within
333  * the same collection. */
335  }
336 
337  if (do_sync_collection) {
339  }
340 
341  if (old_ob == NULL) {
342  for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) {
343  if (ob->type == OB_MBALL && BKE_mball_is_basis(ob)) {
345  }
346  }
347  }
348  else {
349  for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) {
350  if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) {
352  break; /* There is only one basis... */
353  }
354  }
355  }
356 }
357 
358 /* Can be called with both old_collection and new_collection being NULL,
359  * this means we have to check whole Main database then. */
361  Collection *owner_collection,
362  Collection *UNUSED(old_collection),
363  Collection *new_collection)
364 {
365  if (new_collection == NULL) {
366  /* XXX Complex cases can lead to NULL pointers in other collections than old_collection,
367  * and BKE_main_collection_sync_remap() does not tolerate any of those, so for now always check
368  * whole existing collections for NULL pointers.
369  * I'd consider optimizing that whole collection remapping process a TODO: for later. */
370  BKE_collections_child_remove_nulls(bmain, owner_collection, NULL /*old_collection*/);
371  }
372  else {
373  /* Temp safe fix, but a "tad" brute force... We should probably be able to use parents from
374  * old_collection instead? */
375  /* NOTE: Also takes care of duplicated child collections that remapping may have created. */
377  }
378 
380 }
381 
383 {
384  if (ob->data == new_id) {
385  switch (GS(new_id->name)) {
386  case ID_ME:
388  break;
389  case ID_CU_LEGACY:
391  break;
392  default:
393  break;
394  }
396  BKE_object_materials_test(bmain, ob, new_id);
397  }
398 }
399 
401 {
402  /* Update all group nodes using a node group. */
403  ntreeUpdateAllUsers(bmain, new_id);
404 }
405 
406 static void libblock_remap_data_update_tags(ID *old_id, ID *new_id, void *user_data)
407 {
408  IDRemap *id_remap_data = user_data;
409  const int remap_flags = id_remap_data->flag;
410  if ((remap_flags & ID_REMAP_SKIP_USER_CLEAR) == 0) {
411  /* XXX We may not want to always 'transfer' fake-user from old to new id...
412  * Think for now it's desired behavior though,
413  * we can always add an option (flag) to control this later if needed. */
414  if (old_id != NULL && (old_id->flag & LIB_FAKEUSER) && new_id != NULL) {
415  id_fake_user_clear(old_id);
416  id_fake_user_set(new_id);
417  }
418 
419  id_us_clear_real(old_id);
420  }
421 
422  if (new_id != NULL && (new_id->tag & LIB_TAG_INDIRECT) &&
424  new_id->tag &= ~LIB_TAG_INDIRECT;
425  new_id->flag &= ~LIB_INDIRECT_WEAK_LINK;
426  new_id->tag |= LIB_TAG_EXTERN;
427  }
428 }
429 
431  ID *new_id,
432  void *UNUSED(user_data))
433 {
435  if (new_id != NULL) {
437  }
438 }
439 
462 ATTR_NONNULL(1)
463 static void libblock_remap_data(Main *bmain,
464  ID *id,
465  eIDRemapType remap_type,
466  struct IDRemapper *id_remapper,
467  const short remap_flags)
468 {
469  IDRemap id_remap_data = {0};
470  const int foreach_id_flags = ((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ?
472  IDWALK_NOP);
473 
474  id_remap_data.id_remapper = id_remapper;
475  id_remap_data.type = remap_type;
476  id_remap_data.bmain = bmain;
477  id_remap_data.id_owner = NULL;
478  id_remap_data.flag = remap_flags;
479 
481 
482  if (id) {
483 #ifdef DEBUG_PRINT
484  printf("\tchecking id %s (%p, %p)\n", id->name, id, id->lib);
485 #endif
486  id_remap_data.id_owner = id;
487  libblock_remap_data_preprocess(id_remap_data.id_owner, remap_type, id_remapper);
489  NULL, id, foreach_libblock_remap_callback, &id_remap_data, foreach_id_flags);
490  }
491  else {
492  /* Note that this is a very 'brute force' approach,
493  * maybe we could use some depsgraph to only process objects actually using given old_id...
494  * sounds rather unlikely currently, though, so this will do for now. */
495  ID *id_curr;
496 
497  FOREACH_MAIN_ID_BEGIN (bmain, id_curr) {
498  const uint64_t can_use_filter_id = BKE_library_id_can_use_filter_id(id_curr);
499  const bool has_mapping = BKE_id_remapper_has_mapping_for(id_remapper, can_use_filter_id);
500 
501  /* Continue when id_remapper doesn't have any mappings that can be used by id_curr. */
502  if (!has_mapping) {
503  continue;
504  }
505 
506  /* Note that we cannot skip indirect usages of old_id
507  * here (if requested), we still need to check it for the
508  * user count handling...
509  * XXX No more true (except for debug usage of those
510  * skipping counters). */
511  id_remap_data.id_owner = id_curr;
512  libblock_remap_data_preprocess(id_remap_data.id_owner, remap_type, id_remapper);
514  NULL, id_curr, foreach_libblock_remap_callback, &id_remap_data, foreach_id_flags);
515  }
517  }
518 
519  BKE_id_remapper_iter(id_remapper, libblock_remap_data_update_tags, &id_remap_data);
520 }
521 
524  short remap_flags;
526 
527 static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_data)
528 {
530  Main *bmain = data->bmain;
531  const short remap_flags = data->remap_flags;
532 
533  BLI_assert(old_id != NULL);
534  BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
535  BLI_assert(old_id != new_id);
536 
539  }
540 
541  if ((remap_flags & ID_REMAP_SKIP_USER_CLEAR) == 0) {
542  /* If old_id was used by some ugly 'user_one' stuff (like Image or Clip editors...), and user
543  * count has actually been incremented for that, we have to decrease once more its user
544  * count... unless we had to skip some 'user_one' cases. */
545  if ((old_id->tag & LIB_TAG_EXTRAUSER_SET) &&
547  id_us_clear_real(old_id);
548  }
549  }
550 
551  const int skipped_refcounted = old_id->runtime.remap.skipped_refcounted;
552  if (old_id->us - skipped_refcounted < 0) {
553  CLOG_ERROR(&LOG,
554  "Error in remapping process from '%s' (%p) to '%s' (%p): "
555  "wrong user count in old ID after process (summing up to %d)",
556  old_id->name,
557  old_id,
558  new_id ? new_id->name : "<NULL>",
559  new_id,
560  old_id->us - skipped_refcounted);
561  }
562 
563  const int skipped_direct = old_id->runtime.remap.skipped_direct;
564  if (skipped_direct == 0) {
565  /* old_id is assumed to not be used directly anymore... */
566  if (old_id->lib && (old_id->tag & LIB_TAG_EXTERN)) {
567  old_id->tag &= ~LIB_TAG_EXTERN;
568  old_id->tag |= LIB_TAG_INDIRECT;
569  }
570  }
571 
572  /* Some after-process updates.
573  * This is a bit ugly, but cannot see a way to avoid it.
574  * Maybe we should do a per-ID callback for this instead? */
575  switch (GS(old_id->name)) {
576  case ID_OB:
578  bmain, (Object *)old_id, (Object *)new_id, true);
579  break;
580  case ID_GR:
582  bmain, NULL, (Collection *)old_id, (Collection *)new_id);
583  break;
584  case ID_ME:
585  case ID_CU_LEGACY:
586  case ID_MB:
587  case ID_CV:
588  case ID_PT:
589  case ID_VO:
590  if (new_id) { /* Only affects us in case obdata was relinked (changed). */
591  for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
593  }
594  }
595  break;
596  default:
597  break;
598  }
599 
600  /* Node trees may virtually use any kind of data-block... */
601  /* XXX Yuck!!!! nodetree update can do pretty much any thing when talking about py nodes,
602  * including creating new data-blocks (see T50385), so we need to unlock main here. :(
603  * Why can't we have re-entrent locks? */
604  BKE_main_unlock(bmain);
606  BKE_main_lock(bmain);
607 
608  /* Full rebuild of DEG! */
610 
612 }
613 
615  struct IDRemapper *mappings,
616  const short remap_flags)
617 {
618  if (BKE_id_remapper_is_empty(mappings)) {
619  /* Early exit nothing to do. */
620  return;
621  }
622 
623  libblock_remap_data(bmain, NULL, ID_REMAP_TYPE_REMAP, mappings, remap_flags);
624 
626  user_data.bmain = bmain;
627  user_data.remap_flags = remap_flags;
628 
630 
631  /* We assume editors do not hold references to their IDs... This is false in some cases
632  * (Image is especially tricky here),
633  * editors' code is to handle refcount (id->us) itself then. */
636  }
637 
638  /* Full rebuild of DEG! */
640 }
641 
642 void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
643 {
644  struct IDRemapper *remapper = BKE_id_remapper_create();
645  ID *old_id = old_idv;
646  ID *new_id = new_idv;
647  BKE_id_remapper_add(remapper, old_id, new_id);
648  BKE_libblock_remap_multiple_locked(bmain, remapper, remap_flags);
649  BKE_id_remapper_free(remapper);
650 }
651 
652 void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
653 {
654  BKE_main_lock(bmain);
655 
656  BKE_libblock_remap_locked(bmain, old_idv, new_idv, remap_flags);
657 
658  BKE_main_unlock(bmain);
659 }
660 
661 void BKE_libblock_remap_multiple(Main *bmain, struct IDRemapper *mappings, const short remap_flags)
662 {
663  BKE_main_lock(bmain);
664 
665  BKE_libblock_remap_multiple_locked(bmain, mappings, remap_flags);
666 
667  BKE_main_unlock(bmain);
668 }
669 
671  void *idv,
672  const bool do_flag_never_null,
673  const bool do_skip_indirect)
674 {
675  const short remap_flags = (do_skip_indirect ? ID_REMAP_SKIP_INDIRECT_USAGE : 0) |
676  (do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0);
677 
678  BKE_main_lock(bmain);
679 
680  BKE_libblock_remap_locked(bmain, idv, NULL, remap_flags);
681 
682  BKE_main_unlock(bmain);
683 }
684 
685 /* XXX Arg! Naming... :(
686  * _relink? avoids confusion with _remap, but is confusing with _unlink
687  * _remap_used_ids?
688  * _remap_datablocks?
689  * BKE_id_remap maybe?
690  * ... sigh
691  */
692 
697 
698 static void libblock_relink_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_data)
699 {
701  Main *bmain = data->bmain;
702  LinkNode *ids = data->ids;
703 
704  BLI_assert(old_id != NULL);
705  BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
706  BLI_assert(old_id != new_id);
707 
708  bool is_object_update_processed = false;
709  for (LinkNode *ln_iter = ids; ln_iter != NULL; ln_iter = ln_iter->next) {
710  ID *id_iter = ln_iter->link;
711 
712  /* Some after-process updates.
713  * This is a bit ugly, but cannot see a way to avoid it.
714  * Maybe we should do a per-ID callback for this instead?
715  */
716  switch (GS(id_iter->name)) {
717  case ID_SCE:
718  case ID_GR: {
719  /* NOTE: here we know which collection we have affected, so at lest for NULL children
720  * detection we can only process that one.
721  * This is also a required fix in case `id` would not be in Main anymore, which can happen
722  * e.g. when called from `id_delete`. */
723  Collection *owner_collection = (GS(id_iter->name) == ID_GR) ?
724  (Collection *)id_iter :
725  ((Scene *)id_iter)->master_collection;
726  switch (GS(old_id->name)) {
727  case ID_OB:
728  if (!is_object_update_processed) {
730  bmain, (Object *)old_id, (Object *)new_id, true);
731  is_object_update_processed = true;
732  }
733  break;
734  case ID_GR:
736  bmain, owner_collection, (Collection *)old_id, (Collection *)new_id);
737  break;
738  default:
739  break;
740  }
741  break;
742  }
743  case ID_OB:
744  if (new_id != NULL) { /* Only affects us in case obdata was relinked (changed). */
745  libblock_remap_data_postprocess_obdata_relink(bmain, (Object *)id_iter, new_id);
746  }
747  break;
748  default:
749  break;
750  }
751  }
752 }
753 
755  LinkNode *ids,
756  const eIDRemapType remap_type,
757  struct IDRemapper *id_remapper,
758  const short remap_flags)
759 {
760  BLI_assert(remap_type == ID_REMAP_TYPE_REMAP || BKE_id_remapper_is_empty(id_remapper));
761 
762  for (LinkNode *ln_iter = ids; ln_iter != NULL; ln_iter = ln_iter->next) {
763  ID *id_iter = ln_iter->link;
764  libblock_remap_data(bmain, id_iter, remap_type, id_remapper, remap_flags);
765  }
766 
767  switch (remap_type) {
768  case ID_REMAP_TYPE_REMAP: {
770  user_data.bmain = bmain;
771  user_data.ids = ids;
772 
774  break;
775  }
776  case ID_REMAP_TYPE_CLEANUP: {
777  bool is_object_update_processed = false;
778  for (LinkNode *ln_iter = ids; ln_iter != NULL; ln_iter = ln_iter->next) {
779  ID *id_iter = ln_iter->link;
780 
781  switch (GS(id_iter->name)) {
782  case ID_SCE:
783  case ID_GR: {
784  /* NOTE: here we know which collection we have affected, so at lest for NULL children
785  * detection we can only process that one.
786  * This is also a required fix in case `id` would not be in Main anymore, which can
787  * happen e.g. when called from `id_delete`. */
788  Collection *owner_collection = (GS(id_iter->name) == ID_GR) ?
789  (Collection *)id_iter :
790  ((Scene *)id_iter)->master_collection;
791  /* No choice but to check whole objects once, and all children collections. */
792  if (!is_object_update_processed) {
793  /* We only want to affect Object pointers here, not Collection ones, LayerCollections
794  * will be resynced as part of the call to
795  * `libblock_remap_data_postprocess_collection_update` below. */
797  is_object_update_processed = true;
798  }
800  break;
801  }
802  default:
803  break;
804  }
805  }
806 
807  break;
808  }
809  default:
811  }
812 
814 }
815 
817  Main *bmain, void *idv, void *old_idv, void *new_idv, const short remap_flags)
818 {
819 
820  /* Should be able to replace all _relink() funcs (constraints, rigidbody, etc.) ? */
821 
822  ID *id = idv;
823  ID *old_id = old_idv;
824  ID *new_id = new_idv;
825  LinkNode ids = {.next = NULL, .link = idv};
826 
827  /* No need to lock here, we are only affecting given ID, not bmain database. */
828  struct IDRemapper *id_remapper = BKE_id_remapper_create();
829  eIDRemapType remap_type = ID_REMAP_TYPE_REMAP;
830 
831  BLI_assert(id != NULL);
832  UNUSED_VARS_NDEBUG(id);
833  if (old_id != NULL) {
834  BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
835  BLI_assert(old_id != new_id);
836  BKE_id_remapper_add(id_remapper, old_id, new_id);
837  }
838  else {
839  BLI_assert(new_id == NULL);
840  remap_type = ID_REMAP_TYPE_CLEANUP;
841  }
842 
843  BKE_libblock_relink_multiple(bmain, &ids, remap_type, id_remapper, remap_flags);
844 
845  BKE_id_remapper_free(id_remapper);
846 }
847 
848 typedef struct RelinkToNewIDData {
850  struct IDRemapper *id_remapper;
852 
854  ID *id,
855  RelinkToNewIDData *relink_data);
857 {
858  const int cb_flag = cb_data->cb_flag;
860  return IDWALK_RET_NOP;
861  }
862 
863  Main *bmain = cb_data->bmain;
864  ID **id_pointer = cb_data->id_pointer;
865  ID *id = *id_pointer;
866  RelinkToNewIDData *relink_data = (RelinkToNewIDData *)cb_data->user_data;
867 
868  if (id) {
869  /* See: NEW_ID macro */
870  if (id->newid != NULL) {
871  BKE_id_remapper_add(relink_data->id_remapper, id, id->newid);
872  id = id->newid;
873  }
874  if (id->tag & LIB_TAG_NEW) {
875  libblock_relink_to_newid_prepare_data(bmain, id, relink_data);
876  }
877  }
878  return IDWALK_RET_NOP;
879 }
880 
882  ID *id,
883  RelinkToNewIDData *relink_data)
884 {
885  if (ID_IS_LINKED(id)) {
886  return;
887  }
888 
889  id->tag &= ~LIB_TAG_NEW;
890  BLI_linklist_prepend(&relink_data->ids, id);
891  BKE_library_foreach_ID_link(bmain, id, id_relink_to_newid_looper, relink_data, 0);
892 }
893 
894 void BKE_libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag)
895 {
896  if (ID_IS_LINKED(id)) {
897  return;
898  }
899  /* We do not want to have those cached relationship data here. */
900  BLI_assert(bmain->relations == NULL);
901 
902  RelinkToNewIDData relink_data = {.ids = NULL, .id_remapper = BKE_id_remapper_create()};
903 
904  libblock_relink_to_newid_prepare_data(bmain, id, &relink_data);
905 
906  const short remap_flag_final = remap_flag | ID_REMAP_SKIP_INDIRECT_USAGE |
909  bmain, relink_data.ids, ID_REMAP_TYPE_REMAP, relink_data.id_remapper, remap_flag_final);
910 
911  BKE_id_remapper_free(relink_data.id_remapper);
912  BLI_linklist_free(relink_data.ids, NULL);
913 }
void BKE_pose_clear_pointers(struct bPose *pose)
Definition: armature.c:2324
void BKE_collections_child_remove_nulls(struct Main *bmain, struct Collection *parent_collection, struct Collection *child_collection)
Definition: collection.c:1322
void BKE_collections_object_remove_duplicates(struct Main *bmain)
Definition: collection.c:1289
void BKE_collections_object_remove_nulls(struct Main *bmain)
Definition: collection.c:1250
void BKE_main_collections_parent_relations_rebuild(struct Main *bmain)
Definition: collection.c:1658
void BKE_curve_type_test(struct Object *ob)
Definition: curve.cc:482
void BKE_main_collection_sync_remap(const struct Main *bmain)
void BKE_libblock_runtime_reset_remapping_status(struct ID *id) ATTR_NONNULL(1)
Definition: lib_id.c:1129
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void id_fake_user_set(struct ID *id)
Definition: lib_id.c:343
void id_us_ensure_real(struct ID *id)
Definition: lib_id.c:260
void id_us_clear_real(struct ID *id)
Definition: lib_id.c:278
void id_us_plus_no_lib(struct ID *id)
Definition: lib_id.c:289
void id_fake_user_clear(struct ID *id)
Definition: lib_id.c:351
void BKE_library_foreach_ID_link(struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
Definition: lib_query.c:350
@ IDWALK_NOP
@ IDWALK_DO_INTERNAL_RUNTIME_POINTERS
@ IDWALK_CB_NEVER_SELF
Definition: BKE_lib_query.h:35
@ IDWALK_CB_USER_ONE
Definition: BKE_lib_query.h:79
@ IDWALK_CB_USER
Definition: BKE_lib_query.h:73
@ IDWALK_CB_EMBEDDED
Definition: BKE_lib_query.h:48
@ IDWALK_CB_NEVER_NULL
Definition: BKE_lib_query.h:34
@ IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE
Definition: BKE_lib_query.h:57
@ IDWALK_CB_INDIRECT_USAGE
Definition: BKE_lib_query.h:41
@ IDWALK_RET_NOP
Definition: BKE_lib_query.h:83
uint64_t BKE_library_id_can_use_filter_id(const struct ID *id_owner)
void(* BKE_library_remap_editor_id_reference_cb)(const struct IDRemapper *mappings)
void(* BKE_library_free_notifier_reference_cb)(const void *)
IDRemapperApplyResult BKE_id_remapper_apply_ex(const struct IDRemapper *id_remapper, struct ID **r_id_ptr, IDRemapperApplyOptions options, struct ID *id_self)
@ ID_REMAP_SKIP_USER_CLEAR
Definition: BKE_lib_remap.h:63
@ ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS
Definition: BKE_lib_remap.h:70
@ ID_REMAP_SKIP_OVERRIDE_LIBRARY
Definition: BKE_lib_remap.h:59
@ ID_REMAP_FORCE_USER_REFCOUNT
Definition: BKE_lib_remap.h:74
@ ID_REMAP_SKIP_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:45
@ ID_REMAP_FLAG_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:50
@ ID_REMAP_FORCE_OBDATA_IN_EDITMODE
Definition: BKE_lib_remap.h:80
@ ID_REMAP_SKIP_INDIRECT_USAGE
Definition: BKE_lib_remap.h:36
@ ID_REMAP_FORCE_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:57
IDRemapperApplyResult
@ ID_REMAP_RESULT_SOURCE_REMAPPED
@ ID_REMAP_RESULT_SOURCE_UNASSIGNED
@ ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE
@ ID_REMAP_RESULT_SOURCE_UNAVAILABLE
bool BKE_id_remapper_has_mapping_for(const struct IDRemapper *id_remapper, uint64_t type_filter)
IDRemapperApplyResult BKE_id_remapper_get_mapping_result(const struct IDRemapper *id_remapper, struct ID *id, IDRemapperApplyOptions options, const struct ID *id_self)
void BKE_id_remapper_add(struct IDRemapper *id_remapper, struct ID *old_id, struct ID *new_id)
void BKE_id_remapper_clear(struct IDRemapper *id_remapper)
IDRemapperApplyOptions
@ ID_REMAP_APPLY_UNMAP_WHEN_REMAPPING_TO_SELF
@ ID_REMAP_APPLY_DEFAULT
eIDRemapType
Definition: BKE_lib_remap.h:83
@ ID_REMAP_TYPE_REMAP
Definition: BKE_lib_remap.h:85
@ ID_REMAP_TYPE_CLEANUP
Definition: BKE_lib_remap.h:88
const char * BKE_id_remapper_result_string(const IDRemapperApplyResult result)
bool BKE_id_remapper_is_empty(const struct IDRemapper *id_remapper)
struct IDRemapper * BKE_id_remapper_create(void)
void BKE_id_remapper_iter(const struct IDRemapper *id_remapper, IDRemapperIterFunction func, void *user_data)
void BKE_id_remapper_free(struct IDRemapper *id_remapper)
#define FOREACH_MAIN_ID_END
Definition: BKE_main.h:367
void BKE_main_unlock(struct Main *bmain)
Definition: main.c:219
void BKE_main_lock(struct Main *bmain)
Definition: main.c:214
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition: BKE_main.h:361
General operations, lookup, etc. for materials.
void BKE_object_materials_test(struct Main *bmain, struct Object *ob, struct ID *id)
Definition: material.c:864
bool BKE_mball_is_basis_for(const struct Object *ob1, const struct Object *ob2)
bool BKE_mball_is_basis(const struct Object *ob)
void BKE_modifiers_test_object(struct Object *ob)
void multires_force_sculpt_rebuild(struct Object *object)
Definition: multires.c:437
void ntreeUpdateAllUsers(struct Main *main, struct ID *id)
Definition: node.cc:4202
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const struct Object *ob)
#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_NONNULL(...)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define ELEM(...)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define FILTER_ID_AR
Definition: DNA_ID.h:900
@ LIB_TAG_EXTRAUSER_SET
Definition: DNA_ID.h:700
@ LIB_TAG_INDIRECT
Definition: DNA_ID.h:677
@ LIB_TAG_NEW
Definition: DNA_ID.h:704
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ LIB_TAG_EXTERN
Definition: DNA_ID.h:674
@ LIB_TAG_NO_MAIN
Definition: DNA_ID.h:744
@ LIB_EMBEDDED_DATA
Definition: DNA_ID.h:635
@ LIB_FAKEUSER
Definition: DNA_ID.h:630
@ LIB_INDIRECT_WEAK_LINK
Definition: DNA_ID.h:641
@ ID_REMAP_IS_LINKED_DIRECT
Definition: DNA_ID.h:342
@ ID_REMAP_IS_USER_ONE_SKIPPED
Definition: DNA_ID.h:344
@ ID_VO
Definition: DNA_ID_enums.h:83
@ ID_SCE
Definition: DNA_ID_enums.h:45
@ ID_CV
Definition: DNA_ID_enums.h:81
@ ID_CU_LEGACY
Definition: DNA_ID_enums.h:49
@ ID_ME
Definition: DNA_ID_enums.h:48
@ ID_GR
Definition: DNA_ID_enums.h:65
@ ID_MB
Definition: DNA_ID_enums.h:50
@ ID_OB
Definition: DNA_ID_enums.h:47
@ ID_PT
Definition: DNA_ID_enums.h:82
@ POSE_RECALC
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
@ OB_MBALL
@ OB_ARMATURE
void * user_data
#define GS(x)
Definition: iris.c:225
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, const int remap_flag)
Definition: lib_remap.c:894
static void libblock_remap_data_postprocess_collection_update(Main *bmain, Collection *owner_collection, Collection *UNUSED(old_collection), Collection *new_collection)
Definition: lib_remap.c:360
BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb
Definition: lib_remap.c:46
static int id_relink_to_newid_looper(LibraryIDLinkCallbackData *cb_data)
Definition: lib_remap.c:856
void BKE_library_callback_remap_editor_id_reference_set(BKE_library_remap_editor_id_reference_cb func)
Definition: lib_remap.c:48
struct IDRemap IDRemap
void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
Definition: lib_remap.c:652
void BKE_libblock_relink_multiple(Main *bmain, LinkNode *ids, const eIDRemapType remap_type, struct IDRemapper *id_remapper, const short remap_flags)
Definition: lib_remap.c:754
void BKE_libblock_relink_ex(Main *bmain, void *idv, void *old_idv, void *new_idv, const short remap_flags)
Definition: lib_remap.c:816
static void libblock_relink_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_data)
Definition: lib_remap.c:698
void BKE_libblock_unlink(Main *bmain, void *idv, const bool do_flag_never_null, const bool do_skip_indirect)
Definition: lib_remap.c:670
static void foreach_libblock_remap_callback_apply(ID *id_owner, ID *id_self, ID **id_ptr, IDRemap *id_remap_data, const struct IDRemapper *mappings, const IDRemapperApplyOptions id_remapper_options, const int cb_flag, const bool is_indirect, const bool violates_never_null, const bool force_user_refcount)
Definition: lib_remap.c:98
static void libblock_relink_to_newid_prepare_data(Main *bmain, ID *id, RelinkToNewIDData *relink_data)
Definition: lib_remap.c:881
void BKE_libblock_remap_multiple(Main *bmain, struct IDRemapper *mappings, const short remap_flags)
Definition: lib_remap.c:661
static void libblock_remap_data_update_tags(ID *old_id, ID *new_id, void *user_data)
Definition: lib_remap.c:406
static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_data)
Definition: lib_remap.c:527
void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func)
Definition: lib_remap.c:41
static void libblock_remap_data_preprocess_ob(Object *ob, eIDRemapType remap_type, const struct IDRemapper *id_remapper)
Definition: lib_remap.c:268
struct LibblockRemapMultipleUserData LibBlockRemapMultipleUserData
struct RelinkToNewIDData RelinkToNewIDData
static void libblock_remap_data(Main *bmain, ID *id, eIDRemapType remap_type, struct IDRemapper *id_remapper, const short remap_flags)
Definition: lib_remap.c:463
static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *ob, ID *new_id)
Definition: lib_remap.c:382
void BKE_libblock_remap_multiple_locked(Main *bmain, struct IDRemapper *mappings, const short remap_flags)
Definition: lib_remap.c:614
void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
Definition: lib_remap.c:642
struct LibblockRelinkMultipleUserData LibBlockRelinkMultipleUserData
static CLG_LogRef LOG
Definition: lib_remap.c:37
BKE_library_free_notifier_reference_cb free_notifier_reference_cb
Definition: lib_remap.c:39
static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *old_ob, Object *new_ob, const bool do_sync_collection)
Definition: lib_remap.c:320
static void libblock_remap_data_preprocess(ID *id_owner, eIDRemapType remap_type, const struct IDRemapper *id_remapper)
Definition: lib_remap.c:301
static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
Definition: lib_remap.c:150
static void libblock_remap_data_postprocess_nodetree_update(Main *bmain, ID *new_id)
Definition: lib_remap.c:400
static void foreach_libblock_remap_callback_skip(const ID *UNUSED(id_owner), ID **id_ptr, const int cb_flag, const bool is_indirect, const bool is_reference, const bool violates_never_null, const bool UNUSED(is_obj), const bool is_obj_editmode)
Definition: lib_remap.c:67
static void libblock_remap_reset_remapping_status_callback(ID *old_id, ID *new_id, void *UNUSED(user_data))
Definition: lib_remap.c:430
unsigned __int64 uint64_t
Definition: stdint.h:90
const char * identifier
Definition: CLG_log.h:105
struct IDRemapper * id_remapper
Definition: lib_remap.c:58
eIDRemapType type
Definition: lib_remap.c:55
short flag
Definition: lib_remap.c:62
ID * id_owner
Definition: lib_remap.c:61
Main * bmain
Definition: lib_remap.c:56
int skipped_refcounted
Definition: DNA_ID.h:352
int skipped_direct
Definition: DNA_ID.h:357
ID_Runtime_Remap remap
Definition: DNA_ID.h:363
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
struct Library * lib
Definition: DNA_ID.h:372
int us
Definition: DNA_ID.h:388
struct ID * newid
Definition: DNA_ID.h:370
short flag
Definition: DNA_ID.h:383
char name[66]
Definition: DNA_ID.h:378
struct ID_Runtime runtime
Definition: DNA_ID.h:445
struct LinkNode * next
Definition: BLI_linklist.h:23
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct MainIDRelations * relations
Definition: BKE_main.h:218
ListBase objects
Definition: BKE_main.h:170
struct bPose * pose
void * data
LinkNode * ids
Definition: lib_remap.c:849
struct IDRemapper * id_remapper
Definition: lib_remap.c:850
short flag