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  * The Original Code is Copyright (C) 2014 by Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup bke
22  */
23 
24 #include <stdlib.h>
25 
26 #include "DNA_anim_types.h"
27 
28 #include "BLI_ghash.h"
29 #include "BLI_linklist_stack.h"
30 #include "BLI_listbase.h"
31 #include "BLI_utildefines.h"
32 
33 #include "BKE_anim_data.h"
34 #include "BKE_idprop.h"
35 #include "BKE_idtype.h"
36 #include "BKE_lib_id.h"
37 #include "BKE_lib_query.h"
38 #include "BKE_main.h"
39 #include "BKE_node.h"
40 
41 /* status */
42 enum {
43   IDWALK_STOP = 1 << 0,
44 };
45 
46 typedef struct LibraryForeachIDData {
47   Main *bmain;
48   /**
49    * 'Real' ID, the one that might be in bmain, only differs from self_id when the later is a
50    * private one.
51    */
52   ID *owner_id;
53   /**
54    * ID from which the current ID pointer is being processed. It may be an embedded ID like master
55    * collection or root node tree.
56    */
57   ID *self_id;
58 
59   int flag;
60   int cb_flag;
61   int cb_flag_clear;
62   LibraryIDLinkCallback callback;
63   void *user_data;
64   int status;
65 
66   /* To handle recursion. */
67   GSet *ids_handled; /* All IDs that are either already done, or still in ids_todo stack. */
68   BLI_LINKSTACK_DECLARE(ids_todo, ID *);
69 } LibraryForeachIDData;
70 
BKE_lib_query_foreachid_process(LibraryForeachIDData * data,ID ** id_pp,int cb_flag)71 bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag)
72 {
73   if (!(data->status & IDWALK_STOP)) {
74     const int flag = data->flag;
75     ID *old_id = *id_pp;
76     const int callback_return = data->callback(&(struct LibraryIDLinkCallbackData){
77         .user_data = data->user_data,
78         .bmain = data->bmain,
79         .id_owner = data->owner_id,
80         .id_self = data->self_id,
81         .id_pointer = id_pp,
82         .cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear)});
83     if (flag & IDWALK_READONLY) {
84       BLI_assert(*(id_pp) == old_id);
85     }
86     if (old_id && (flag & IDWALK_RECURSE)) {
87       if (BLI_gset_add((data)->ids_handled, old_id)) {
88         if (!(callback_return & IDWALK_RET_STOP_RECURSION)) {
89           BLI_LINKSTACK_PUSH(data->ids_todo, old_id);
90         }
91       }
92     }
93     if (callback_return & IDWALK_RET_STOP_ITER) {
94       data->status |= IDWALK_STOP;
95       return false;
96     }
97     return true;
98   }
99 
100   return false;
101 }
102 
BKE_lib_query_foreachid_process_flags_get(LibraryForeachIDData * data)103 int BKE_lib_query_foreachid_process_flags_get(LibraryForeachIDData *data)
104 {
105   return data->flag;
106 }
107 
BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData * data,const int cb_flag,const bool do_replace)108 int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData *data,
109                                                            const int cb_flag,
110                                                            const bool do_replace)
111 {
112   const int cb_flag_backup = data->cb_flag;
113   if (do_replace) {
114     data->cb_flag = cb_flag;
115   }
116   else {
117     data->cb_flag |= cb_flag;
118   }
119   return cb_flag_backup;
120 }
121 
122 static void library_foreach_ID_link(Main *bmain,
123                                     ID *id_owner,
124                                     ID *id,
125                                     LibraryIDLinkCallback callback,
126                                     void *user_data,
127                                     int flag,
128                                     LibraryForeachIDData *inherit_data);
129 
BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty * id_prop,void * user_data)130 void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void *user_data)
131 {
132   BLI_assert(id_prop->type == IDP_ID);
133 
134   LibraryForeachIDData *data = (LibraryForeachIDData *)user_data;
135   BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, IDWALK_CB_USER);
136 }
137 
BKE_library_foreach_ID_embedded(LibraryForeachIDData * data,ID ** id_pp)138 bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
139 {
140   /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */
141   ID *id = *id_pp;
142   const int flag = data->flag;
143 
144   if (!BKE_lib_query_foreachid_process(data, id_pp, IDWALK_CB_EMBEDDED)) {
145     return false;
146   }
147   BLI_assert(id == *id_pp);
148 
149   if (id == NULL) {
150     return true;
151   }
152 
153   if (flag & IDWALK_IGNORE_EMBEDDED_ID) {
154     /* Do Nothing. */
155   }
156   else if (flag & IDWALK_RECURSE) {
157     /* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in
158      * IDWALK_RECURSE case is troublesome, see T49553. */
159     /* XXX note that this breaks the 'owner id' thing now, we likely want to handle that
160      * differently at some point, but for now it should not be a problem in practice. */
161     if (BLI_gset_add(data->ids_handled, id)) {
162       BLI_LINKSTACK_PUSH(data->ids_todo, id);
163     }
164   }
165   else {
166     library_foreach_ID_link(
167         data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data);
168   }
169 
170   return true;
171 }
172 
library_foreach_ID_link(Main * bmain,ID * id_owner,ID * id,LibraryIDLinkCallback callback,void * user_data,int flag,LibraryForeachIDData * inherit_data)173 static void library_foreach_ID_link(Main *bmain,
174                                     ID *id_owner,
175                                     ID *id,
176                                     LibraryIDLinkCallback callback,
177                                     void *user_data,
178                                     int flag,
179                                     LibraryForeachIDData *inherit_data)
180 {
181   LibraryForeachIDData data = {.bmain = bmain};
182 
183   BLI_assert(inherit_data == NULL || data.bmain == inherit_data->bmain);
184 
185   if (flag & IDWALK_RECURSE) {
186     /* For now, recursion implies read-only. */
187     flag |= IDWALK_READONLY;
188 
189     data.ids_handled = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
190     BLI_LINKSTACK_INIT(data.ids_todo);
191 
192     BLI_gset_add(data.ids_handled, id);
193   }
194   else {
195     data.ids_handled = NULL;
196   }
197   data.flag = flag;
198   data.status = 0;
199   data.callback = callback;
200   data.user_data = user_data;
201 
202 #define CALLBACK_INVOKE_ID(check_id, cb_flag) \
203   BKE_LIB_FOREACHID_PROCESS_ID(&data, check_id, cb_flag)
204 
205 #define CALLBACK_INVOKE(check_id_super, cb_flag) \
206   BKE_LIB_FOREACHID_PROCESS(&data, check_id_super, cb_flag)
207 
208   for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) {
209     data.self_id = id;
210     /* Note that we may call this functions sometime directly on an embedded ID, without any
211      * knowledge of the owner ID then.
212      * While not great, and that should be probably sanitized at some point, we cal live with it
213      * for now. */
214     data.owner_id = ((id->flag & LIB_EMBEDDED_DATA) != 0 && id_owner != NULL) ? id_owner :
215                                                                                 data.self_id;
216 
217     /* inherit_data is non-NULL when this function is called for some sub-data ID
218      * (like root nodetree of a material).
219      * In that case, we do not want to generate those 'generic flags' from our current sub-data ID
220      * (the node tree), but re-use those generated for the 'owner' ID (the material). */
221     if (inherit_data == NULL) {
222       data.cb_flag = ID_IS_LINKED(id) ? IDWALK_CB_INDIRECT_USAGE : 0;
223       /* When an ID is not in Main database, it should never refcount IDs it is using.
224        * Exceptions: NodeTrees (yeah!) directly used by Materials. */
225       data.cb_flag_clear = (id->tag & LIB_TAG_NO_MAIN) ? IDWALK_CB_USER | IDWALK_CB_USER_ONE : 0;
226     }
227     else {
228       data.cb_flag = inherit_data->cb_flag;
229       data.cb_flag_clear = inherit_data->cb_flag_clear;
230     }
231 
232     if (bmain != NULL && bmain->relations != NULL && (flag & IDWALK_READONLY) &&
233         (((bmain->relations->flag & MAINIDRELATIONS_INCLUDE_UI) == 0) ==
234          ((data.flag & IDWALK_INCLUDE_UI) == 0))) {
235       /* Note that this is minor optimization, even in worst cases (like id being an object with
236        * lots of drivers and constraints and modifiers, or material etc. with huge node tree),
237        * but we might as well use it (Main->relations is always assumed valid,
238        * it's responsibility of code creating it to free it,
239        * especially if/when it starts modifying Main database). */
240       MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id);
241       for (; entry != NULL; entry = entry->next) {
242         BKE_lib_query_foreachid_process(&data, entry->id_pointer, entry->usage_flag);
243       }
244       continue;
245     }
246 
247     /* Note: ID.lib pointer is purposefully fully ignored here...
248      * We may want to add it at some point? */
249 
250     if (id->override_library != NULL) {
251       CALLBACK_INVOKE_ID(id->override_library->reference,
252                          IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE);
253       CALLBACK_INVOKE_ID(id->override_library->storage,
254                          IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE);
255     }
256 
257     IDP_foreach_property(id->properties,
258                          IDP_TYPE_FILTER_ID,
259                          BKE_lib_query_idpropertiesForeachIDLink_callback,
260                          &data);
261 
262     AnimData *adt = BKE_animdata_from_id(id);
263     if (adt) {
264       BKE_animdata_foreach_id(adt, &data);
265     }
266 
267     const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
268     if (id_type->foreach_id != NULL) {
269       id_type->foreach_id(id, &data);
270 
271       if (data.status & IDWALK_STOP) {
272         break;
273       }
274     }
275   }
276 
277   if (data.ids_handled) {
278     BLI_gset_free(data.ids_handled, NULL);
279     BLI_LINKSTACK_FREE(data.ids_todo);
280   }
281 
282 #undef CALLBACK_INVOKE_ID
283 #undef CALLBACK_INVOKE
284 }
285 
286 /**
287  * Loop over all of the ID's this data-block links to.
288  */
BKE_library_foreach_ID_link(Main * bmain,ID * id,LibraryIDLinkCallback callback,void * user_data,int flag)289 void BKE_library_foreach_ID_link(
290     Main *bmain, ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
291 {
292   library_foreach_ID_link(bmain, NULL, id, callback, user_data, flag, NULL);
293 }
294 
295 /**
296  * re-usable function, use when replacing ID's
297  */
BKE_library_update_ID_link_user(ID * id_dst,ID * id_src,const int cb_flag)298 void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
299 {
300   if (cb_flag & IDWALK_CB_USER) {
301     id_us_min(id_src);
302     id_us_plus(id_dst);
303   }
304   else if (cb_flag & IDWALK_CB_USER_ONE) {
305     id_us_ensure_real(id_dst);
306   }
307 }
308 
309 /**
310  * Say whether given \a id_owner may use (in any way) a data-block of \a id_type_used.
311  *
312  * This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above,
313  * quite useful to reduce useless iterations in some cases.
314  */
BKE_library_id_can_use_idtype(ID * id_owner,const short id_type_used)315 bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
316 {
317   /* any type of ID can be used in custom props. */
318   if (id_owner->properties) {
319     return true;
320   }
321 
322   const short id_type_owner = GS(id_owner->name);
323 
324   /* IDProps of armature bones and nodes, and bNode->id can use virtually any type of ID. */
325   if (ELEM(id_type_owner, ID_NT, ID_AR)) {
326     return true;
327   }
328 
329   if (ntreeFromID(id_owner)) {
330     return true;
331   }
332 
333   if (BKE_animdata_from_id(id_owner)) {
334     /* AnimationData can use virtually any kind of data-blocks, through drivers especially. */
335     return true;
336   }
337 
338   switch ((ID_Type)id_type_owner) {
339     case ID_LI:
340       return ELEM(id_type_used, ID_LI);
341     case ID_SCE:
342       return (ELEM(id_type_used,
343                    ID_OB,
344                    ID_WO,
345                    ID_SCE,
346                    ID_MC,
347                    ID_MA,
348                    ID_GR,
349                    ID_TXT,
350                    ID_LS,
351                    ID_MSK,
352                    ID_SO,
353                    ID_GD,
354                    ID_BR,
355                    ID_PAL,
356                    ID_IM,
357                    ID_NT));
358     case ID_OB:
359       /* Could be more specific, but simpler to just always say 'yes' here. */
360       return true;
361     case ID_ME:
362       return ELEM(id_type_used, ID_ME, ID_KE, ID_MA, ID_IM);
363     case ID_CU:
364       return ELEM(id_type_used, ID_OB, ID_KE, ID_MA, ID_VF);
365     case ID_MB:
366       return ELEM(id_type_used, ID_MA);
367     case ID_MA:
368       return (ELEM(id_type_used, ID_TE, ID_GR));
369     case ID_TE:
370       return (ELEM(id_type_used, ID_IM, ID_OB));
371     case ID_LT:
372       return ELEM(id_type_used, ID_KE);
373     case ID_LA:
374       return (ELEM(id_type_used, ID_TE));
375     case ID_CA:
376       return ELEM(id_type_used, ID_OB);
377     case ID_KE:
378       /* Warning! key->from, could be more types in future? */
379       return ELEM(id_type_used, ID_ME, ID_CU, ID_LT);
380     case ID_SCR:
381       return ELEM(id_type_used, ID_SCE);
382     case ID_WO:
383       return (ELEM(id_type_used, ID_TE));
384     case ID_SPK:
385       return ELEM(id_type_used, ID_SO);
386     case ID_GR:
387       return ELEM(id_type_used, ID_OB, ID_GR);
388     case ID_NT:
389       /* Could be more specific, but node.id has no type restriction... */
390       return true;
391     case ID_BR:
392       return ELEM(id_type_used, ID_BR, ID_IM, ID_PC, ID_TE, ID_MA);
393     case ID_PA:
394       return ELEM(id_type_used, ID_OB, ID_GR, ID_TE);
395     case ID_MC:
396       return ELEM(id_type_used, ID_GD, ID_IM);
397     case ID_MSK:
398       /* WARNING! mask->parent.id, not typed. */
399       return ELEM(id_type_used, ID_MC);
400     case ID_LS:
401       return (ELEM(id_type_used, ID_TE, ID_OB));
402     case ID_LP:
403       return ELEM(id_type_used, ID_IM);
404     case ID_GD:
405       return ELEM(id_type_used, ID_MA);
406     case ID_WS:
407       return ELEM(id_type_used, ID_SCR, ID_SCE);
408     case ID_HA:
409       return ELEM(id_type_used, ID_MA);
410     case ID_PT:
411       return ELEM(id_type_used, ID_MA);
412     case ID_VO:
413       return ELEM(id_type_used, ID_MA);
414     case ID_SIM:
415       return ELEM(id_type_used, ID_OB, ID_IM);
416     case ID_IM:
417     case ID_VF:
418     case ID_TXT:
419     case ID_SO:
420     case ID_AR:
421     case ID_AC:
422     case ID_WM:
423     case ID_PAL:
424     case ID_PC:
425     case ID_CF:
426       /* Those types never use/reference other IDs... */
427       return false;
428     case ID_IP:
429       /* Deprecated... */
430       return false;
431   }
432   return false;
433 }
434 
435 /* ***** ID users iterator. ***** */
436 typedef struct IDUsersIter {
437   ID *id;
438 
439   ListBase *lb_array[MAX_LIBARRAY];
440   int lb_idx;
441 
442   ID *curr_id;
443   int count_direct, count_indirect; /* Set by callback. */
444 } IDUsersIter;
445 
foreach_libblock_id_users_callback(LibraryIDLinkCallbackData * cb_data)446 static int foreach_libblock_id_users_callback(LibraryIDLinkCallbackData *cb_data)
447 {
448   ID **id_p = cb_data->id_pointer;
449   const int cb_flag = cb_data->cb_flag;
450   IDUsersIter *iter = cb_data->user_data;
451 
452   if (*id_p) {
453     /* 'Loopback' ID pointers (the ugly 'from' ones, Object->proxy_from and Key->from).
454      * Those are not actually ID usage, we can ignore them here.
455      */
456     if (cb_flag & IDWALK_CB_LOOPBACK) {
457       return IDWALK_RET_NOP;
458     }
459 
460     if (*id_p == iter->id) {
461 #if 0
462       printf(
463           "%s uses %s (refcounted: %d, userone: %d, used_one: %d, used_one_active: %d, "
464           "indirect_usage: %d)\n",
465           iter->curr_id->name,
466           iter->id->name,
467           (cb_flag & IDWALK_USER) ? 1 : 0,
468           (cb_flag & IDWALK_USER_ONE) ? 1 : 0,
469           (iter->id->tag & LIB_TAG_EXTRAUSER) ? 1 : 0,
470           (iter->id->tag & LIB_TAG_EXTRAUSER_SET) ? 1 : 0,
471           (cb_flag & IDWALK_INDIRECT_USAGE) ? 1 : 0);
472 #endif
473       if (cb_flag & IDWALK_CB_INDIRECT_USAGE) {
474         iter->count_indirect++;
475       }
476       else {
477         iter->count_direct++;
478       }
479     }
480   }
481 
482   return IDWALK_RET_NOP;
483 }
484 
485 /**
486  * Return the number of times given \a id_user uses/references \a id_used.
487  *
488  * \note This only checks for pointer references of an ID, shallow usages
489  * (like e.g. by RNA paths, as done for FCurves) are not detected at all.
490  *
491  * \param id_user: the ID which is supposed to use (reference) \a id_used.
492  * \param id_used: the ID which is supposed to be used (referenced) by \a id_user.
493  * \return the number of direct usages/references of \a id_used by \a id_user.
494  */
BKE_library_ID_use_ID(ID * id_user,ID * id_used)495 int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
496 {
497   IDUsersIter iter;
498 
499   /* We do not care about iter.lb_array/lb_idx here... */
500   iter.id = id_used;
501   iter.curr_id = id_user;
502   iter.count_direct = iter.count_indirect = 0;
503 
504   BKE_library_foreach_ID_link(
505       NULL, iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_READONLY);
506 
507   return iter.count_direct + iter.count_indirect;
508 }
509 
library_ID_is_used(Main * bmain,void * idv,const bool check_linked)510 static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
511 {
512   IDUsersIter iter;
513   ListBase *lb_array[MAX_LIBARRAY];
514   ID *id = idv;
515   int i = set_listbasepointers(bmain, lb_array);
516   bool is_defined = false;
517 
518   iter.id = id;
519   iter.count_direct = iter.count_indirect = 0;
520   while (i-- && !is_defined) {
521     ID *id_curr = lb_array[i]->first;
522 
523     if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) {
524       continue;
525     }
526 
527     for (; id_curr && !is_defined; id_curr = id_curr->next) {
528       if (id_curr == id) {
529         /* We are not interested in self-usages (mostly from drivers or bone constraints...). */
530         continue;
531       }
532       iter.curr_id = id_curr;
533       BKE_library_foreach_ID_link(
534           bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
535 
536       is_defined = ((check_linked ? iter.count_indirect : iter.count_direct) != 0);
537     }
538   }
539 
540   return is_defined;
541 }
542 
543 /**
544  * Check whether given ID is used locally (i.e. by another non-linked ID).
545  */
BKE_library_ID_is_locally_used(Main * bmain,void * idv)546 bool BKE_library_ID_is_locally_used(Main *bmain, void *idv)
547 {
548   return library_ID_is_used(bmain, idv, false);
549 }
550 
551 /**
552  * Check whether given ID is used indirectly (i.e. by another linked ID).
553  */
BKE_library_ID_is_indirectly_used(Main * bmain,void * idv)554 bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
555 {
556   return library_ID_is_used(bmain, idv, true);
557 }
558 
559 /**
560  * Combine #BKE_library_ID_is_locally_used() and #BKE_library_ID_is_indirectly_used()
561  * in a single call.
562  */
BKE_library_ID_test_usages(Main * bmain,void * idv,bool * is_used_local,bool * is_used_linked)563 void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked)
564 {
565   IDUsersIter iter;
566   ListBase *lb_array[MAX_LIBARRAY];
567   ID *id = idv;
568   int i = set_listbasepointers(bmain, lb_array);
569   bool is_defined = false;
570 
571   iter.id = id;
572   iter.count_direct = iter.count_indirect = 0;
573   while (i-- && !is_defined) {
574     ID *id_curr = lb_array[i]->first;
575 
576     if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) {
577       continue;
578     }
579 
580     for (; id_curr && !is_defined; id_curr = id_curr->next) {
581       if (id_curr == id) {
582         /* We are not interested in self-usages (mostly from drivers or bone constraints...). */
583         continue;
584       }
585       iter.curr_id = id_curr;
586       BKE_library_foreach_ID_link(
587           bmain, id_curr, foreach_libblock_id_users_callback, &iter, IDWALK_READONLY);
588 
589       is_defined = (iter.count_direct != 0 && iter.count_indirect != 0);
590     }
591   }
592 
593   *is_used_local = (iter.count_direct != 0);
594   *is_used_linked = (iter.count_indirect != 0);
595 }
596 
597 /* ***** IDs usages.checking/tagging. ***** */
foreach_libblock_used_linked_data_tag_clear_cb(LibraryIDLinkCallbackData * cb_data)598 static int foreach_libblock_used_linked_data_tag_clear_cb(LibraryIDLinkCallbackData *cb_data)
599 {
600   ID *self_id = cb_data->id_self;
601   ID **id_p = cb_data->id_pointer;
602   const int cb_flag = cb_data->cb_flag;
603   bool *is_changed = cb_data->user_data;
604 
605   if (*id_p) {
606     /* The infamous 'from' pointers (Key.from, Object.proxy_from, ...).
607      * those are not actually ID usage, so we ignore them here. */
608     if (cb_flag & IDWALK_CB_LOOPBACK) {
609       return IDWALK_RET_NOP;
610     }
611 
612     /* If checked id is used by an assumed used ID,
613      * then it is also used and not part of any linked archipelago. */
614     if (!(self_id->tag & LIB_TAG_DOIT) && ((*id_p)->tag & LIB_TAG_DOIT)) {
615       (*id_p)->tag &= ~LIB_TAG_DOIT;
616       *is_changed = true;
617     }
618   }
619 
620   return IDWALK_RET_NOP;
621 }
622 
623 /**
624  * Detect orphaned linked data blocks (i.e. linked data not used (directly or indirectly)
625  * in any way by any local data), including complex cases like 'linked archipelagoes', i.e.
626  * linked data-blocks that use each other in loops,
627  * which prevents their deletion by 'basic' usage checks.
628  *
629  * \param do_init_tag: if \a true, all linked data are checked, if \a false,
630  * only linked data-blocks already tagged with #LIB_TAG_DOIT are checked.
631  */
BKE_library_unused_linked_data_set_tag(Main * bmain,const bool do_init_tag)632 void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
633 {
634   ID *id;
635 
636   if (do_init_tag) {
637     FOREACH_MAIN_ID_BEGIN (bmain, id) {
638       if (id->lib && (id->tag & LIB_TAG_INDIRECT) != 0) {
639         id->tag |= LIB_TAG_DOIT;
640       }
641       else {
642         id->tag &= ~LIB_TAG_DOIT;
643       }
644     }
645     FOREACH_MAIN_ID_END;
646   }
647 
648   for (bool do_loop = true; do_loop;) {
649     do_loop = false;
650     FOREACH_MAIN_ID_BEGIN (bmain, id) {
651       /* We only want to check that ID if it is currently known as used... */
652       if ((id->tag & LIB_TAG_DOIT) == 0) {
653         BKE_library_foreach_ID_link(
654             bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
655       }
656     }
657     FOREACH_MAIN_ID_END;
658   }
659 }
660 
661 /**
662  * Untag linked data blocks used by other untagged linked data-blocks.
663  * Used to detect data-blocks that we can forcefully make local
664  * (instead of copying them to later get rid of original):
665  * All data-blocks we want to make local are tagged by caller,
666  * after this function has ran caller knows data-blocks still tagged can directly be made local,
667  * since they are only used by other data-blocks that will also be made fully local.
668  */
BKE_library_indirectly_used_data_tag_clear(Main * bmain)669 void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
670 {
671   ListBase *lb_array[MAX_LIBARRAY];
672 
673   bool do_loop = true;
674   while (do_loop) {
675     int i = set_listbasepointers(bmain, lb_array);
676     do_loop = false;
677 
678     while (i--) {
679       LISTBASE_FOREACH (ID *, id, lb_array[i]) {
680         if (id->lib == NULL || id->tag & LIB_TAG_DOIT) {
681           /* Local or non-indirectly-used ID (so far), no need to check it further. */
682           continue;
683         }
684         BKE_library_foreach_ID_link(
685             bmain, id, foreach_libblock_used_linked_data_tag_clear_cb, &do_loop, IDWALK_READONLY);
686       }
687     }
688   }
689 }
690