Cleanup: unused headers
[blender.git] / source / blender / blenkernel / intern / lib_remap.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup bke
19  *
20  * Contains management of ID's for remapping.
21  */
22
23 #include "CLG_log.h"
24
25 #include "BLI_utildefines.h"
26
27 #include "DNA_object_types.h"
28
29 #include "BKE_armature.h"
30 #include "BKE_collection.h"
31 #include "BKE_curve.h"
32 #include "BKE_layer.h"
33 #include "BKE_lib_id.h"
34 #include "BKE_lib_query.h"
35 #include "BKE_lib_remap.h"
36 #include "BKE_material.h"
37 #include "BKE_main.h"
38 #include "BKE_mball.h"
39 #include "BKE_modifier.h"
40 #include "BKE_multires.h"
41 #include "BKE_node.h"
42 #include "BKE_object.h"
43
44 #include "DEG_depsgraph.h"
45 #include "DEG_depsgraph_build.h"
46
47 #include "lib_intern.h" /* own include */
48
49 static CLG_LogRef LOG = {.identifier = "bke.lib_remap"};
50
51 BKE_library_free_window_manager_cb free_windowmanager_cb = NULL;
52
53 void BKE_library_callback_free_window_manager_set(BKE_library_free_window_manager_cb func)
54 {
55   free_windowmanager_cb = func;
56 }
57
58 BKE_library_free_notifier_reference_cb free_notifier_reference_cb = NULL;
59
60 void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func)
61 {
62   free_notifier_reference_cb = func;
63 }
64
65 BKE_library_remap_editor_id_reference_cb remap_editor_id_reference_cb = NULL;
66
67 void BKE_library_callback_remap_editor_id_reference_set(
68     BKE_library_remap_editor_id_reference_cb func)
69 {
70   remap_editor_id_reference_cb = func;
71 }
72
73 typedef struct IDRemap {
74   Main *bmain; /* Only used to trigger depsgraph updates in the right bmain. */
75   ID *old_id;
76   ID *new_id;
77   /** The ID in which we are replacing old_id by new_id usages. */
78   ID *id;
79   short flag;
80
81   /* 'Output' data. */
82   short status;
83   /** Number of direct usecases that could not be remapped (e.g.: obdata when in edit mode). */
84   int skipped_direct;
85   /** Number of indirect usecases that could not be remapped. */
86   int skipped_indirect;
87   /** Number of skipped usecases that refcount the datablock. */
88   int skipped_refcounted;
89 } IDRemap;
90
91 /* IDRemap->flag enums defined in BKE_lib.h */
92
93 /* IDRemap->status */
94 enum {
95   /* *** Set by callback. *** */
96   ID_REMAP_IS_LINKED_DIRECT = 1 << 0,    /* new_id is directly linked in current .blend. */
97   ID_REMAP_IS_USER_ONE_SKIPPED = 1 << 1, /* There was some skipped 'user_one' usages of old_id. */
98 };
99
100 static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id_p, int cb_flag)
101 {
102   if (cb_flag & IDWALK_CB_PRIVATE) {
103     return IDWALK_RET_NOP;
104   }
105
106   IDRemap *id_remap_data = user_data;
107   ID *old_id = id_remap_data->old_id;
108   ID *new_id = id_remap_data->new_id;
109   ID *id = id_remap_data->id;
110
111   if (!old_id) { /* Used to cleanup all IDs used by a specific one. */
112     BLI_assert(!new_id);
113     old_id = *id_p;
114   }
115
116   if (*id_p && (*id_p == old_id)) {
117     /* Better remap to NULL than not remapping at all,
118      * then we can handle it as a regular remap-to-NULL case. */
119     if ((cb_flag & IDWALK_CB_NEVER_SELF) && (new_id == id_self)) {
120       new_id = NULL;
121     }
122
123     const bool is_reference = (cb_flag & IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE) != 0;
124     const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
125     const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
126     /* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
127      * on the other hand since they get reset to lib data on file open/reload it is indirect too.
128      * Edit Mode is also a 'skip direct' case. */
129     const bool is_obj = (GS(id->name) == ID_OB);
130     const bool is_obj_proxy = (is_obj && (((Object *)id)->proxy || ((Object *)id)->proxy_group));
131     const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
132     const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
133                                 (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
134     const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_OVERRIDE_LIBRARY) != 0;
135     const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
136
137 #ifdef DEBUG_PRINT
138     printf(
139         "In %s (lib %p): Remapping %s (%p) to %s (%p) "
140         "(is_indirect: %d, skip_indirect: %d, is_reference: %d, skip_reference: %d)\n",
141         id->name,
142         id->lib,
143         old_id->name,
144         old_id,
145         new_id ? new_id->name : "<NONE>",
146         new_id,
147         is_indirect,
148         skip_indirect,
149         is_reference,
150         skip_reference);
151 #endif
152
153     if ((id_remap_data->flag & ID_REMAP_FLAG_NEVER_NULL_USAGE) &&
154         (cb_flag & IDWALK_CB_NEVER_NULL)) {
155       id->tag |= LIB_TAG_DOIT;
156     }
157
158     /* Special hack in case it's Object->data and we are in edit mode, and new_id is not NULL
159      * (otherwise, we follow common NEVER_NULL flags).
160      * (skipped_indirect too). */
161     if ((is_never_null && skip_never_null) ||
162         (is_obj_editmode && (((Object *)id)->data == *id_p) && new_id != NULL) ||
163         (skip_indirect && is_indirect) || (is_reference && skip_reference)) {
164       if (is_indirect) {
165         id_remap_data->skipped_indirect++;
166         if (is_obj) {
167           Object *ob = (Object *)id;
168           if (ob->data == *id_p && ob->proxy != NULL) {
169             /* And another 'Proudly brought to you by Proxy Hell' hack!
170              * This will allow us to avoid clearing 'LIB_EXTERN' flag of obdata of proxies... */
171             id_remap_data->skipped_direct++;
172           }
173         }
174       }
175       else if (is_never_null || is_obj_editmode || is_reference) {
176         id_remap_data->skipped_direct++;
177       }
178       else {
179         BLI_assert(0);
180       }
181       if (cb_flag & IDWALK_CB_USER) {
182         id_remap_data->skipped_refcounted++;
183       }
184       else if (cb_flag & IDWALK_CB_USER_ONE) {
185         /* No need to count number of times this happens, just a flag is enough. */
186         id_remap_data->status |= ID_REMAP_IS_USER_ONE_SKIPPED;
187       }
188     }
189     else {
190       if (!is_never_null) {
191         *id_p = new_id;
192         DEG_id_tag_update_ex(id_remap_data->bmain,
193                              id_self,
194                              ID_RECALC_COPY_ON_WRITE | ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
195       }
196       if (cb_flag & IDWALK_CB_USER) {
197         /* NOTE: We don't user-count IDs which are not in the main database.
198          * This is because in certain conditions we can have data-blocks in
199          * the main which are referencing data-blocks outside of it.
200          * For example, BKE_mesh_new_from_object() called on an evaluated
201          * object will cause such situation.
202          */
203         if ((old_id->tag & LIB_TAG_NO_MAIN) == 0) {
204           id_us_min(old_id);
205         }
206         if (new_id != NULL && (new_id->tag & LIB_TAG_NO_MAIN) == 0) {
207           /* We do not want to handle LIB_TAG_INDIRECT/LIB_TAG_EXTERN here. */
208           new_id->us++;
209         }
210       }
211       else if (cb_flag & IDWALK_CB_USER_ONE) {
212         id_us_ensure_real(new_id);
213         /* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET)
214          * are assumed to be set as needed, that extra user is processed in final handling. */
215       }
216       if (!is_indirect || is_obj_proxy) {
217         id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
218       }
219       /* We need to remap proxy_from pointer of remapped proxy... sigh. */
220       if (is_obj_proxy && new_id != NULL) {
221         Object *ob = (Object *)id;
222         if (ob->proxy == (Object *)new_id) {
223           ob->proxy->proxy_from = ob;
224         }
225       }
226     }
227   }
228
229   return IDWALK_RET_NOP;
230 }
231
232 static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
233 {
234   switch (GS(r_id_remap_data->id->name)) {
235     case ID_OB: {
236       ID *old_id = r_id_remap_data->old_id;
237       if (!old_id || GS(old_id->name) == ID_AR) {
238         Object *ob = (Object *)r_id_remap_data->id;
239         /* Object's pose holds reference to armature bones... sic */
240         /* Note that in theory, we should have to bother about
241          * linked/non-linked/never-null/etc. flags/states.
242          * Fortunately, this is just a tag, so we can accept to 'over-tag' a bit for pose recalc,
243          * and avoid another complex and risky condition nightmare like the one we have in
244          * foreach_libblock_remap_callback()... */
245         if (ob->pose && (!old_id || ob->data == old_id)) {
246           BLI_assert(ob->type == OB_ARMATURE);
247           ob->pose->flag |= POSE_RECALC;
248           /* We need to clear pose bone pointers immediately, things like undo writefile may be
249            * called before pose is actually recomputed, can lead to segfault... */
250           BKE_pose_clear_pointers(ob->pose);
251         }
252       }
253       break;
254     }
255     default:
256       break;
257   }
258 }
259
260 /**
261  * Can be called with both old_ob and new_ob being NULL,
262  * this means we have to check whole Main database then.
263  */
264 static void libblock_remap_data_postprocess_object_update(Main *bmain,
265                                                           Object *old_ob,
266                                                           Object *new_ob)
267 {
268   if (new_ob == NULL) {
269     /* In case we unlinked old_ob (new_ob is NULL), the object has already
270      * been removed from the scenes and their collections. We still have
271      * to remove the NULL children from collections not used in any scene. */
272     BKE_collections_object_remove_nulls(bmain);
273   }
274
275   BKE_main_collection_sync_remap(bmain);
276
277   if (old_ob == NULL) {
278     for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) {
279       if (ob->type == OB_MBALL && BKE_mball_is_basis(ob)) {
280         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
281       }
282     }
283   }
284   else {
285     for (Object *ob = bmain->objects.first; ob != NULL; ob = ob->id.next) {
286       if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) {
287         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
288         break; /* There is only one basis... */
289       }
290     }
291   }
292 }
293
294 /* Can be called with both old_collection and new_collection being NULL,
295  * this means we have to check whole Main database then. */
296 static void libblock_remap_data_postprocess_collection_update(Main *bmain,
297                                                               Collection *UNUSED(old_collection),
298                                                               Collection *new_collection)
299 {
300   if (new_collection == NULL) {
301     /* XXX Complex cases can lead to NULL pointers in other collections than old_collection,
302      * and BKE_main_collection_sync_remap() does not tolerate any of those, so for now always check
303      * whole existing collections for NULL pointers.
304      * I'd consider optimizing that whole collection remapping process a TODO for later. */
305     BKE_collections_child_remove_nulls(bmain, NULL /*old_collection*/);
306   }
307   else {
308     /* Temp safe fix, but a "tad" brute force... We should probably be able to use parents from
309      * old_collection instead? */
310     BKE_main_collections_parent_relations_rebuild(bmain);
311   }
312
313   BKE_main_collection_sync_remap(bmain);
314 }
315
316 static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *ob, ID *new_id)
317 {
318   if (ob->data == new_id) {
319     switch (GS(new_id->name)) {
320       case ID_ME:
321         multires_force_sculpt_rebuild(ob);
322         break;
323       case ID_CU:
324         BKE_curve_type_test(ob);
325         break;
326       default:
327         break;
328     }
329     test_object_modifiers(ob);
330     BKE_object_materials_test(bmain, ob, new_id);
331   }
332 }
333
334 static void libblock_remap_data_postprocess_nodetree_update(Main *bmain, ID *new_id)
335 {
336   /* Update all group nodes using a node group. */
337   ntreeUpdateAllUsers(bmain, new_id);
338 }
339
340 /**
341  * Execute the 'data' part of the remapping (that is, all ID pointers from other ID data-blocks).
342  *
343  * Behavior differs depending on whether given \a id is NULL or not:
344  * - \a id NULL: \a old_id must be non-NULL, \a new_id may be NULL (unlinking \a old_id) or not
345  *   (remapping \a old_id to \a new_id).
346  *   The whole \a bmain database is checked, and all pointers to \a old_id
347  *   are remapped to \a new_id.
348  * - \a id is non-NULL:
349  *   + If \a old_id is NULL, \a new_id must also be NULL,
350  *     and all ID pointers from \a id are cleared
351  *     (i.e. \a id does not references any other data-block anymore).
352  *   + If \a old_id is non-NULL, behavior is as with a NULL \a id, but only within given \a id.
353  *
354  * \param bmain: the Main data storage to operate on (must never be NULL).
355  * \param id: the data-block to operate on
356  * (can be NULL, in which case we operate over all IDs from given bmain).
357  * \param old_id: the data-block to dereference (may be NULL if \a id is non-NULL).
358  * \param new_id: the new data-block to replace \a old_id references with (may be NULL).
359  * \param r_id_remap_data: if non-NULL, the IDRemap struct to use
360  * (uselful to retrieve info about remapping process).
361  */
362 ATTR_NONNULL(1)
363 static void libblock_remap_data(
364     Main *bmain, ID *id, ID *old_id, ID *new_id, const short remap_flags, IDRemap *r_id_remap_data)
365 {
366   IDRemap id_remap_data;
367   const int foreach_id_flags = (remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ?
368                                    IDWALK_NO_INDIRECT_PROXY_DATA_USAGE :
369                                    IDWALK_NOP;
370
371   if (r_id_remap_data == NULL) {
372     r_id_remap_data = &id_remap_data;
373   }
374   r_id_remap_data->bmain = bmain;
375   r_id_remap_data->old_id = old_id;
376   r_id_remap_data->new_id = new_id;
377   r_id_remap_data->id = NULL;
378   r_id_remap_data->flag = remap_flags;
379   r_id_remap_data->status = 0;
380   r_id_remap_data->skipped_direct = 0;
381   r_id_remap_data->skipped_indirect = 0;
382   r_id_remap_data->skipped_refcounted = 0;
383
384   if (id) {
385 #ifdef DEBUG_PRINT
386     printf("\tchecking id %s (%p, %p)\n", id->name, id, id->lib);
387 #endif
388     r_id_remap_data->id = id;
389     libblock_remap_data_preprocess(r_id_remap_data);
390     BKE_library_foreach_ID_link(
391         NULL, id, foreach_libblock_remap_callback, (void *)r_id_remap_data, foreach_id_flags);
392   }
393   else {
394     /* Note that this is a very 'brute force' approach,
395      * maybe we could use some depsgraph to only process objects actually using given old_id...
396      * sounds rather unlikely currently, though, so this will do for now. */
397     ID *id_curr;
398
399     FOREACH_MAIN_ID_BEGIN (bmain, id_curr) {
400       if (BKE_library_id_can_use_idtype(id_curr, GS(old_id->name))) {
401         /* Note that we cannot skip indirect usages of old_id here (if requested),
402          * we still need to check it for the user count handling...
403          * XXX No more true (except for debug usage of those skipping counters). */
404         r_id_remap_data->id = id_curr;
405         libblock_remap_data_preprocess(r_id_remap_data);
406         BKE_library_foreach_ID_link(NULL,
407                                     id_curr,
408                                     foreach_libblock_remap_callback,
409                                     (void *)r_id_remap_data,
410                                     foreach_id_flags);
411       }
412     }
413     FOREACH_MAIN_ID_END;
414   }
415
416   /* XXX We may not want to always 'transfer' fake-user from old to new id...
417    *     Think for now it's desired behavior though,
418    *     we can always add an option (flag) to control this later if needed. */
419   if (old_id && (old_id->flag & LIB_FAKEUSER)) {
420     id_fake_user_clear(old_id);
421     id_fake_user_set(new_id);
422   }
423
424   id_us_clear_real(old_id);
425
426   if (new_id && (new_id->tag & LIB_TAG_INDIRECT) &&
427       (r_id_remap_data->status & ID_REMAP_IS_LINKED_DIRECT)) {
428     new_id->tag &= ~LIB_TAG_INDIRECT;
429     new_id->flag &= ~LIB_INDIRECT_WEAK_LINK;
430     new_id->tag |= LIB_TAG_EXTERN;
431   }
432
433 #ifdef DEBUG_PRINT
434   printf("%s: %d occurrences skipped (%d direct and %d indirect ones)\n",
435          __func__,
436          r_id_remap_data->skipped_direct + r_id_remap_data->skipped_indirect,
437          r_id_remap_data->skipped_direct,
438          r_id_remap_data->skipped_indirect);
439 #endif
440 }
441
442 /**
443  * Replace all references in given Main to \a old_id by \a new_id
444  * (if \a new_id is NULL, it unlinks \a old_id).
445  */
446 void BKE_libblock_remap_locked(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
447 {
448   IDRemap id_remap_data;
449   ID *old_id = old_idv;
450   ID *new_id = new_idv;
451   int skipped_direct, skipped_refcounted;
452
453   BLI_assert(old_id != NULL);
454   BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
455   BLI_assert(old_id != new_id);
456
457   libblock_remap_data(bmain, NULL, old_id, new_id, remap_flags, &id_remap_data);
458
459   if (free_notifier_reference_cb) {
460     free_notifier_reference_cb(old_id);
461   }
462
463   /* We assume editors do not hold references to their IDs... This is false in some cases
464    * (Image is especially tricky here),
465    * editors' code is to handle refcount (id->us) itself then. */
466   if (remap_editor_id_reference_cb) {
467     remap_editor_id_reference_cb(old_id, new_id);
468   }
469
470   skipped_direct = id_remap_data.skipped_direct;
471   skipped_refcounted = id_remap_data.skipped_refcounted;
472
473   /* If old_id was used by some ugly 'user_one' stuff (like Image or Clip editors...), and user
474    * count has actually been incremented for that, we have to decrease once more its user count...
475    * unless we had to skip some 'user_one' cases. */
476   if ((old_id->tag & LIB_TAG_EXTRAUSER_SET) &&
477       !(id_remap_data.status & ID_REMAP_IS_USER_ONE_SKIPPED)) {
478     id_us_clear_real(old_id);
479   }
480
481   if (old_id->us - skipped_refcounted < 0) {
482     CLOG_ERROR(&LOG,
483                "Error in remapping process from '%s' (%p) to '%s' (%p): "
484                "wrong user count in old ID after process (summing up to %d)",
485                old_id->name,
486                old_id,
487                new_id ? new_id->name : "<NULL>",
488                new_id,
489                old_id->us - skipped_refcounted);
490     BLI_assert(0);
491   }
492
493   if (skipped_direct == 0) {
494     /* old_id is assumed to not be used directly anymore... */
495     if (old_id->lib && (old_id->tag & LIB_TAG_EXTERN)) {
496       old_id->tag &= ~LIB_TAG_EXTERN;
497       old_id->tag |= LIB_TAG_INDIRECT;
498     }
499   }
500
501   /* Some after-process updates.
502    * This is a bit ugly, but cannot see a way to avoid it.
503    * Maybe we should do a per-ID callback for this instead? */
504   switch (GS(old_id->name)) {
505     case ID_OB:
506       libblock_remap_data_postprocess_object_update(bmain, (Object *)old_id, (Object *)new_id);
507       break;
508     case ID_GR:
509       libblock_remap_data_postprocess_collection_update(
510           bmain, (Collection *)old_id, (Collection *)new_id);
511       break;
512     case ID_ME:
513     case ID_CU:
514     case ID_MB:
515       if (new_id) { /* Only affects us in case obdata was relinked (changed). */
516         for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
517           libblock_remap_data_postprocess_obdata_relink(bmain, ob, new_id);
518         }
519       }
520       break;
521     default:
522       break;
523   }
524
525   /* Node trees may virtually use any kind of data-block... */
526   /* XXX Yuck!!!! nodetree update can do pretty much any thing when talking about py nodes,
527    *     including creating new data-blocks (see T50385), so we need to unlock main here. :(
528    *     Why can't we have re-entrent locks? */
529   BKE_main_unlock(bmain);
530   libblock_remap_data_postprocess_nodetree_update(bmain, new_id);
531   BKE_main_lock(bmain);
532
533   /* Full rebuild of DEG! */
534   DEG_relations_tag_update(bmain);
535 }
536
537 void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short remap_flags)
538 {
539   BKE_main_lock(bmain);
540
541   BKE_libblock_remap_locked(bmain, old_idv, new_idv, remap_flags);
542
543   BKE_main_unlock(bmain);
544 }
545
546 /**
547  * Unlink given \a id from given \a bmain
548  * (does not touch to indirect, i.e. library, usages of the ID).
549  *
550  * \param do_flag_never_null: If true, all IDs using \a idv in a 'non-NULL' way are flagged by
551  * #LIB_TAG_DOIT flag (quite obviously, 'non-NULL' usages can never be unlinked by this function).
552  */
553 void BKE_libblock_unlink(Main *bmain,
554                          void *idv,
555                          const bool do_flag_never_null,
556                          const bool do_skip_indirect)
557 {
558   const short remap_flags = (do_skip_indirect ? ID_REMAP_SKIP_INDIRECT_USAGE : 0) |
559                             (do_flag_never_null ? ID_REMAP_FLAG_NEVER_NULL_USAGE : 0);
560
561   BKE_main_lock(bmain);
562
563   BKE_libblock_remap_locked(bmain, idv, NULL, remap_flags);
564
565   BKE_main_unlock(bmain);
566 }
567
568 /**
569  * Similar to libblock_remap, but only affects IDs used by given \a idv ID.
570  *
571  * \param old_idv: Unlike BKE_libblock_remap, can be NULL,
572  * in which case all ID usages by given \a idv will be cleared.
573  * \param us_min_never_null: If \a true and new_id is NULL,
574  * 'NEVER_NULL' ID usages keep their old id, but this one still gets its user count decremented
575  * (needed when given \a idv is going to be deleted right after being unlinked).
576  */
577 /* Should be able to replace all _relink() funcs (constraints, rigidbody, etc.) ? */
578 /* XXX Arg! Naming... :(
579  *     _relink? avoids confusion with _remap, but is confusing with _unlink
580  *     _remap_used_ids?
581  *     _remap_datablocks?
582  *     BKE_id_remap maybe?
583  *     ... sigh
584  */
585 void BKE_libblock_relink_ex(
586     Main *bmain, void *idv, void *old_idv, void *new_idv, const short remap_flags)
587 {
588   ID *id = idv;
589   ID *old_id = old_idv;
590   ID *new_id = new_idv;
591
592   /* No need to lock here, we are only affecting given ID, not bmain database. */
593
594   BLI_assert(id);
595   if (old_id) {
596     BLI_assert((new_id == NULL) || GS(old_id->name) == GS(new_id->name));
597     BLI_assert(old_id != new_id);
598   }
599   else {
600     BLI_assert(new_id == NULL);
601   }
602
603   libblock_remap_data(bmain, id, old_id, new_id, remap_flags, NULL);
604
605   /* Some after-process updates.
606    * This is a bit ugly, but cannot see a way to avoid it.
607    * Maybe we should do a per-ID callback for this instead?
608    */
609   switch (GS(id->name)) {
610     case ID_SCE:
611     case ID_GR: {
612       if (old_id) {
613         switch (GS(old_id->name)) {
614           case ID_OB:
615             libblock_remap_data_postprocess_object_update(
616                 bmain, (Object *)old_id, (Object *)new_id);
617             break;
618           case ID_GR:
619             libblock_remap_data_postprocess_collection_update(
620                 bmain, (Collection *)old_id, (Collection *)new_id);
621             break;
622           default:
623             break;
624         }
625       }
626       else {
627         /* No choice but to check whole objects/collections. */
628         libblock_remap_data_postprocess_collection_update(bmain, NULL, NULL);
629         libblock_remap_data_postprocess_object_update(bmain, NULL, NULL);
630       }
631       break;
632     }
633     case ID_OB:
634       if (new_id) { /* Only affects us in case obdata was relinked (changed). */
635         libblock_remap_data_postprocess_obdata_relink(bmain, (Object *)id, new_id);
636       }
637       break;
638     default:
639       break;
640   }
641
642   DEG_relations_tag_update(bmain);
643 }
644
645 static int id_relink_to_newid_looper(void *UNUSED(user_data),
646                                      ID *UNUSED(self_id),
647                                      ID **id_pointer,
648                                      const int cb_flag)
649 {
650   if (cb_flag & IDWALK_CB_PRIVATE) {
651     return IDWALK_RET_NOP;
652   }
653
654   ID *id = *id_pointer;
655   if (id) {
656     /* See: NEW_ID macro */
657     if (id->newid) {
658       BKE_library_update_ID_link_user(id->newid, id, cb_flag);
659       *id_pointer = id->newid;
660     }
661     else if (id->tag & LIB_TAG_NEW) {
662       id->tag &= ~LIB_TAG_NEW;
663       BKE_libblock_relink_to_newid(id);
664     }
665   }
666   return IDWALK_RET_NOP;
667 }
668
669 /**
670  * Similar to #libblock_relink_ex,
671  * but is remapping IDs to their newid value if non-NULL, in given \a id.
672  *
673  * Very specific usage, not sure we'll keep it on the long run,
674  * currently only used in Object/Collection duplication code...
675  */
676 void BKE_libblock_relink_to_newid(ID *id)
677 {
678   if (ID_IS_LINKED(id)) {
679     return;
680   }
681
682   BKE_library_foreach_ID_link(NULL, id, id_relink_to_newid_looper, NULL, 0);
683 }