Blender V4.3
main.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <cstring>
12#include <iostream>
13
14#include "CLG_log.h"
15
16#include "MEM_guardedalloc.h"
17
18#include "BLI_blenlib.h"
19#include "BLI_ghash.h"
20#include "BLI_map.hh"
21#include "BLI_mempool.h"
22#include "BLI_threads.h"
23#include "BLI_vector.hh"
24
25#include "DNA_ID.h"
26
27#include "BKE_bpath.hh"
28#include "BKE_global.hh"
29#include "BKE_idtype.hh"
30#include "BKE_lib_id.hh"
31#include "BKE_lib_query.hh"
32#include "BKE_lib_remap.hh"
33#include "BKE_main.hh"
34#include "BKE_main_idmap.hh"
35#include "BKE_main_namemap.hh"
36#include "BKE_report.hh"
37
38#include "IMB_imbuf.hh"
39#include "IMB_imbuf_types.hh"
40
41using namespace blender::bke;
42
43static CLG_LogRef LOG = {"bke.main"};
44
46{
47 Main *bmain = static_cast<Main *>(MEM_callocN(sizeof(Main), "new main"));
48 BKE_main_init(*bmain);
49 return bmain;
50}
51
52void BKE_main_init(Main &bmain)
53{
54 bmain.lock = static_cast<MainLock *>(MEM_mallocN(sizeof(SpinLock), "main lock"));
55 BLI_spin_init(reinterpret_cast<SpinLock *>(bmain.lock));
56 bmain.is_global_main = false;
57
58 /* Just rebuilding the Action Slot to ID* map once is likely cheaper than,
59 * for every ID, when it's loaded from disk, check whether it's animated or
60 * not, and then figure out which Main it went into, and then set the flag. */
62}
63
64void BKE_main_clear(Main &bmain)
65{
66 /* Also call when reading a file, erase all, etc */
67 ListBase *lbarray[INDEX_ID_MAX];
68 int a;
69
70 /* Since we are removing whole main, no need to bother 'properly' (and slowly) removing each ID
71 * from it. */
72 const int free_flag = (LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_UI_USER |
74
76
77 a = set_listbasepointers(&bmain, lbarray);
78 while (a--) {
79 ListBase *lb = lbarray[a];
80 ID *id, *id_next;
81
82 for (id = static_cast<ID *>(lb->first); id != nullptr; id = id_next) {
83 id_next = static_cast<ID *>(id->next);
84#if 1
85 BKE_id_free_ex(&bmain, id, free_flag, false);
86#else
87 /* Errors freeing ID's can be hard to track down,
88 * enable this so VALGRIND or ASAN will give the line number in its error log. */
89
90# define CASE_ID_INDEX(id_index) \
91 case id_index: \
92 BKE_id_free_ex(&bmain, id, free_flag, false); \
93 break
94
95 switch ((eID_Index)a) {
96 CASE_ID_INDEX(INDEX_ID_LI);
97 CASE_ID_INDEX(INDEX_ID_IP);
98 CASE_ID_INDEX(INDEX_ID_AC);
99 CASE_ID_INDEX(INDEX_ID_GD_LEGACY);
100 CASE_ID_INDEX(INDEX_ID_NT);
101 CASE_ID_INDEX(INDEX_ID_VF);
102 CASE_ID_INDEX(INDEX_ID_TXT);
103 CASE_ID_INDEX(INDEX_ID_SO);
104 CASE_ID_INDEX(INDEX_ID_MSK);
105 CASE_ID_INDEX(INDEX_ID_IM);
106 CASE_ID_INDEX(INDEX_ID_MC);
107 CASE_ID_INDEX(INDEX_ID_TE);
108 CASE_ID_INDEX(INDEX_ID_MA);
109 CASE_ID_INDEX(INDEX_ID_LS);
110 CASE_ID_INDEX(INDEX_ID_WO);
111 CASE_ID_INDEX(INDEX_ID_CF);
112 CASE_ID_INDEX(INDEX_ID_SIM);
113 CASE_ID_INDEX(INDEX_ID_PA);
114 CASE_ID_INDEX(INDEX_ID_KE);
115 CASE_ID_INDEX(INDEX_ID_AR);
116 CASE_ID_INDEX(INDEX_ID_ME);
117 CASE_ID_INDEX(INDEX_ID_CU_LEGACY);
118 CASE_ID_INDEX(INDEX_ID_MB);
119 CASE_ID_INDEX(INDEX_ID_CV);
120 CASE_ID_INDEX(INDEX_ID_PT);
121 CASE_ID_INDEX(INDEX_ID_VO);
122 CASE_ID_INDEX(INDEX_ID_LT);
123 CASE_ID_INDEX(INDEX_ID_LA);
124 CASE_ID_INDEX(INDEX_ID_CA);
125 CASE_ID_INDEX(INDEX_ID_SPK);
126 CASE_ID_INDEX(INDEX_ID_LP);
127 CASE_ID_INDEX(INDEX_ID_OB);
128 CASE_ID_INDEX(INDEX_ID_GR);
129 CASE_ID_INDEX(INDEX_ID_PAL);
130 CASE_ID_INDEX(INDEX_ID_PC);
131 CASE_ID_INDEX(INDEX_ID_BR);
132 CASE_ID_INDEX(INDEX_ID_SCE);
133 CASE_ID_INDEX(INDEX_ID_SCR);
134 CASE_ID_INDEX(INDEX_ID_WS);
135 CASE_ID_INDEX(INDEX_ID_WM);
136 case INDEX_ID_NULL: {
138 break;
139 }
140 }
141
142# undef CASE_ID_INDEX
143
144#endif
145 }
147 }
148
149 if (bmain.relations) {
151 }
152
153 if (bmain.id_map) {
155 }
156
157 /* NOTE: `name_map` in libraries are freed together with the library IDs above. */
158 if (bmain.name_map) {
160 }
161 if (bmain.name_map_global) {
163 }
164}
165
167{
168 BKE_main_clear(bmain);
169
170 BLI_spin_end(reinterpret_cast<SpinLock *>(bmain.lock));
171 MEM_freeN(bmain.lock);
172 bmain.lock = nullptr;
173}
174
175void BKE_main_free(Main *bmain)
176{
177 /* In case this is called on a 'split-by-libraries' list of mains.
178 *
179 * Should not happen in typical usages, but can occur e.g. if a file reading is aborted. */
180 if (bmain->next) {
181 BKE_main_free(bmain->next);
182 }
183
184 /* Include this check here as the path may be manipulated after creation. */
185 BLI_assert_msg(!(bmain->filepath[0] == '/' && bmain->filepath[1] == '/'),
186 "'.blend' relative \"//\" must not be used in Main!");
187
188 BKE_main_destroy(*bmain);
189 MEM_freeN(bmain);
190}
191
192static bool are_ids_from_different_mains_matching(Main *bmain_1, ID *id_1, Main *bmain_2, ID *id_2)
193{
194 /* Both IDs should not be null at the same time.
195 *
196 * NOTE: E.g. `id_1` may be null, in case `id_2` is a Library ID which path is the filepath of
197 * `bmain_1`. */
198 BLI_assert(id_1 || id_2);
199
200 /* Special handling for libraries, since their filepaths is used then, not their ID names.
201 *
202 * NOTE: In library case, this call should always return true, since given data should always
203 * match. The asserts below merely ensure that expected conditions are always met:
204 * - A given library absolute filepath should never match its own bmain filepath.
205 * - If both given libraries are non-null:
206 * - Their absolute filepath should match.
207 * - Neither of their absolute filepaths should match any of the bmain filepaths.
208 * - If one of the library is null:
209 * - The other library should match the bmain filepath of the null library. */
210 if ((!id_1 && GS(id_2->name) == ID_LI) || GS(id_1->name) == ID_LI) {
211 BLI_assert(!id_1 || !ID_IS_LINKED(id_1));
212 BLI_assert(!id_2 || !ID_IS_LINKED(id_2));
213
214 Library *lib_1 = reinterpret_cast<Library *>(id_1);
215 Library *lib_2 = reinterpret_cast<Library *>(id_2);
216
217 if (lib_1 && lib_2) {
219 }
220 if (lib_1) {
221 BLI_assert(!STREQ(lib_1->runtime.filepath_abs, bmain_1->filepath));
222 if (lib_2) {
223 BLI_assert(!STREQ(lib_1->runtime.filepath_abs, bmain_2->filepath));
224 }
225 else {
226 BLI_assert(STREQ(lib_1->runtime.filepath_abs, bmain_2->filepath));
227 }
228 }
229 if (lib_2) {
230 BLI_assert(!STREQ(lib_2->runtime.filepath_abs, bmain_2->filepath));
231 if (lib_1) {
232 BLI_assert(!STREQ(lib_2->runtime.filepath_abs, bmain_1->filepath));
233 }
234 else {
235 BLI_assert(STREQ(lib_2->runtime.filepath_abs, bmain_1->filepath));
236 }
237 }
238
239 return true;
240 }
241
242 /* Now both IDs are expected to be valid data, and caller is expected to have ensured already
243 * that they have the same name. */
244 BLI_assert(id_1 && id_2);
245 BLI_assert(STREQ(id_1->name, id_2->name));
246
247 if (!id_1->lib && !id_2->lib) {
248 return true;
249 }
250
251 if (id_1->lib && id_2->lib) {
252 if (id_1->lib == id_2->lib) {
253 return true;
254 }
255 if (STREQ(id_1->lib->runtime.filepath_abs, id_2->lib->runtime.filepath_abs)) {
256 return true;
257 }
258 return false;
259 }
260
261 /* In case one Main is the library of the ID from the other Main. */
262
263 if (id_1->lib) {
264 if (STREQ(id_1->lib->runtime.filepath_abs, bmain_2->filepath)) {
265 return true;
266 }
267 return false;
268 }
269
270 if (id_2->lib) {
271 if (STREQ(id_2->lib->runtime.filepath_abs, bmain_1->filepath)) {
272 return true;
273 }
274 return false;
275 }
276
278 return false;
279}
280
281static void main_merge_add_id_to_move(Main *bmain_dst,
282 blender::Map<std::string, blender::Vector<ID *>> &id_map_dst,
283 ID *id_src,
284 id::IDRemapper &id_remapper,
285 blender::Vector<ID *> &ids_to_move,
286 const bool is_library,
287 MainMergeReport &reports)
288{
289 const bool is_id_src_linked(id_src->lib);
290 bool is_id_src_from_bmain_dst = false;
291 if (is_id_src_linked) {
292 BLI_assert(!is_library);
293 UNUSED_VARS_NDEBUG(is_library);
294 blender::Vector<ID *> id_src_lib_dst = id_map_dst.lookup_default(
295 id_src->lib->runtime.filepath_abs, {});
296 /* The current library of the source ID would be remapped to null, which means that it comes
297 * from the destination Main. */
298 is_id_src_from_bmain_dst = !id_src_lib_dst.is_empty() && !id_src_lib_dst[0];
299 }
300 std::cout << id_src->name << " is linked from dst Main: " << is_id_src_from_bmain_dst << "\n";
301 std::cout.flush();
302
303 if (is_id_src_from_bmain_dst) {
304 /* Do not move an ID supposed to be from `bmain_dst` (used as library in `bmain_src`) into
305 * `bmain_src`. Fact that no match was found is worth a warning, although it could happen
306 * e.g. in case `bmain_dst` has been updated since it file was loaded as library in
307 * `bmain_src`. */
308 CLOG_WARN(&LOG,
309 "ID '%s' defined in source Main as linked from destination Main (file '%s') not "
310 "found in given destination Main",
311 id_src->name,
312 bmain_dst->filepath);
313 id_remapper.add(id_src, nullptr);
314 reports.num_unknown_ids++;
315 }
316 else {
317 ids_to_move.append(id_src);
318 }
319}
320
321void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &reports)
322{
323 Main *bmain_src = *r_bmain_src;
324 /* NOTE: Dedicated mapping type is needed here, to handle properly the library cases. */
326 ID *id_iter_dst, *id_iter_src;
327 FOREACH_MAIN_ID_BEGIN (bmain_dst, id_iter_dst) {
328 if (GS(id_iter_dst->name) == ID_LI) {
329 /* Libraries need specific handling, as we want to check them by their filepath, not the IDs
330 * themselves. */
331 Library *lib_dst = reinterpret_cast<Library *>(id_iter_dst);
332 BLI_assert(!id_map_dst.contains(lib_dst->runtime.filepath_abs));
333 id_map_dst.add(lib_dst->runtime.filepath_abs, {id_iter_dst});
334 }
335 else {
336 id_map_dst.lookup_or_add(id_iter_dst->name, {}).append(id_iter_dst);
337 }
338 }
340 /* Add the current `bmain_dst` filepath in the mapping as well, as it may be a library of the
341 * `bmain_src` Main. */
342 id_map_dst.add(bmain_dst->filepath, {nullptr});
343
344 /* A dedicated remapper for libraries is needed because these need to be remapped _before_ IDs
345 * are moved from `bmain_src` to `bmain_dst`, to avoid having to fix naming and ordering of IDs
346 * afterwards (especially in case some source linked IDs become local in `bmain_dst`). */
347 id::IDRemapper id_remapper;
348 id::IDRemapper id_remapper_libraries;
349 blender::Vector<ID *> ids_to_move;
350
351 FOREACH_MAIN_ID_BEGIN (bmain_src, id_iter_src) {
352 const bool is_library = GS(id_iter_src->name) == ID_LI;
353
354 blender::Vector<ID *> ids_dst = id_map_dst.lookup_default(
355 is_library ? reinterpret_cast<Library *>(id_iter_src)->runtime.filepath_abs :
356 id_iter_src->name,
357 {});
358 if (is_library) {
359 BLI_assert(ids_dst.size() <= 1);
360 }
361 if (ids_dst.is_empty()) {
363 bmain_dst, id_map_dst, id_iter_src, id_remapper, ids_to_move, is_library, reports);
364 continue;
365 }
366
367 bool src_has_match_in_dst = false;
368 for (ID *id_iter_dst : ids_dst) {
369 if (are_ids_from_different_mains_matching(bmain_dst, id_iter_dst, bmain_src, id_iter_src)) {
370 /* There should only ever be one potential match, never more. */
371 BLI_assert(!src_has_match_in_dst);
372 if (!src_has_match_in_dst) {
373 if (is_library) {
374 id_remapper_libraries.add(id_iter_src, id_iter_dst);
375 reports.num_remapped_libraries++;
376 }
377 else {
378 id_remapper.add(id_iter_src, id_iter_dst);
379 reports.num_remapped_ids++;
380 }
381 src_has_match_in_dst = true;
382 }
383#ifdef NDEBUG /* In DEBUG builds, keep looping to ensure there is only one match. */
384 break;
385#endif
386 }
387 }
388 if (!src_has_match_in_dst) {
390 bmain_dst, id_map_dst, id_iter_src, id_remapper, ids_to_move, is_library, reports);
391 }
392 }
394
395 reports.num_merged_ids = int(ids_to_move.size());
396
397 /* Rebase relative filepaths in `bmain_src` using `bmain_dst` path as new reference, or make them
398 * absolute if destination bmain has no filepath. */
399 if (bmain_src->filepath[0] != '\0') {
400 char dir_src[FILE_MAXDIR];
401 BLI_path_split_dir_part(bmain_src->filepath, dir_src, sizeof(dir_src));
403
404 if (bmain_dst->filepath[0] != '\0') {
405 char dir_dst[FILE_MAXDIR];
406 BLI_path_split_dir_part(bmain_dst->filepath, dir_dst, sizeof(dir_dst));
408 BKE_bpath_relative_rebase(bmain_src, dir_src, dir_dst, reports.reports);
409 }
410 else {
411 BKE_bpath_absolute_convert(bmain_src, dir_src, reports.reports);
412 }
413 }
414
415 /* Libraries need to be remapped before moving IDs into `bmain_dst`, to ensure that the sorting
416 * of inserted IDs is correct. Note that no bmain is given here, so this is only a 'raw'
417 * remapping. */
419 ids_to_move,
421 id_remapper_libraries,
423
424 for (ID *id_iter_src : ids_to_move) {
425 BKE_libblock_management_main_remove(bmain_src, id_iter_src);
426 BKE_libblock_management_main_add(bmain_dst, id_iter_src);
427 }
428
429 /* The other data has to be remapped once all IDs are in `bmain_dst`, to ensure that additional
430 * update process (e.g. collection hierarchy handling) happens as expected with the correct set
431 * of data. */
432 BKE_libblock_relink_multiple(bmain_dst, ids_to_move, ID_REMAP_TYPE_REMAP, id_remapper, 0);
433
435 reports.reports,
436 RPT_INFO,
437 "Merged %d IDs from '%s' Main into '%s' Main; %d IDs and %d Libraries already existed as "
438 "part of the destination Main, and %d IDs missing from destination Main, were freed "
439 "together with the source Main",
440 reports.num_merged_ids,
441 bmain_src->filepath,
442 bmain_dst->filepath,
443 reports.num_remapped_ids,
445 reports.num_unknown_ids);
446
447 /* Remapping above may have made some IDs local. So namemap needs to be cleared, and moved IDs
448 * need to be re-sorted. */
449 BKE_main_namemap_clear(bmain_dst);
450
452
453 BKE_main_free(bmain_src);
454 *r_bmain_src = nullptr;
455}
456
458{
459 bool result = true;
460 ID *id_iter;
461 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
462 result = false;
463 break;
464 }
466 return result;
467}
468
469bool BKE_main_has_issues(const Main *bmain)
470{
472}
473
475{
477}
478
479void BKE_main_lock(Main *bmain)
480{
481 BLI_spin_lock((SpinLock *)bmain->lock);
482}
483
485{
486 BLI_spin_unlock((SpinLock *)bmain->lock);
487}
488
490{
491 MainIDRelations *bmain_relations = static_cast<MainIDRelations *>(cb_data->user_data);
492 ID *self_id = cb_data->self_id;
493 ID **id_pointer = cb_data->id_pointer;
494 const int cb_flag = cb_data->cb_flag;
495
496 if (*id_pointer) {
497 MainIDRelationsEntry **entry_p;
498
499 /* Add `id_pointer` as child of `self_id`. */
500 {
502 bmain_relations->relations_from_pointers, self_id, (void ***)&entry_p))
503 {
504 *entry_p = static_cast<MainIDRelationsEntry *>(MEM_callocN(sizeof(**entry_p), __func__));
505 (*entry_p)->session_uid = self_id->session_uid;
506 }
507 else {
508 BLI_assert((*entry_p)->session_uid == self_id->session_uid);
509 }
510 MainIDRelationsEntryItem *to_id_entry = static_cast<MainIDRelationsEntryItem *>(
511 BLI_mempool_alloc(bmain_relations->entry_items_pool));
512 to_id_entry->next = (*entry_p)->to_ids;
513 to_id_entry->id_pointer.to = id_pointer;
514 to_id_entry->session_uid = (*id_pointer != nullptr) ? (*id_pointer)->session_uid :
516 to_id_entry->usage_flag = cb_flag;
517 (*entry_p)->to_ids = to_id_entry;
518 }
519
520 /* Add `self_id` as parent of `id_pointer`. */
521 if (*id_pointer != nullptr) {
523 bmain_relations->relations_from_pointers, *id_pointer, (void ***)&entry_p))
524 {
525 *entry_p = static_cast<MainIDRelationsEntry *>(MEM_callocN(sizeof(**entry_p), __func__));
526 (*entry_p)->session_uid = (*id_pointer)->session_uid;
527 }
528 else {
529 BLI_assert((*entry_p)->session_uid == (*id_pointer)->session_uid);
530 }
531 MainIDRelationsEntryItem *from_id_entry = static_cast<MainIDRelationsEntryItem *>(
532 BLI_mempool_alloc(bmain_relations->entry_items_pool));
533 from_id_entry->next = (*entry_p)->from_ids;
534 from_id_entry->id_pointer.from = self_id;
535 from_id_entry->session_uid = self_id->session_uid;
536 from_id_entry->usage_flag = cb_flag;
537 (*entry_p)->from_ids = from_id_entry;
538 }
539 }
540
541 return IDWALK_RET_NOP;
542}
543
544void BKE_main_relations_create(Main *bmain, const short flag)
545{
546 if (bmain->relations != nullptr) {
548 }
549
550 bmain->relations = static_cast<MainIDRelations *>(
551 MEM_mallocN(sizeof(*bmain->relations), __func__));
555 sizeof(MainIDRelationsEntryItem), 128, 128, BLI_MEMPOOL_NOP);
556
557 bmain->relations->flag = flag;
558
559 ID *id;
560 FOREACH_MAIN_ID_BEGIN (bmain, id) {
561 const int idwalk_flag = IDWALK_READONLY |
563
564 /* Ensure all IDs do have an entry, even if they are not connected to any other. */
565 MainIDRelationsEntry **entry_p;
566 if (!BLI_ghash_ensure_p(bmain->relations->relations_from_pointers, id, (void ***)&entry_p)) {
567 *entry_p = static_cast<MainIDRelationsEntry *>(MEM_callocN(sizeof(**entry_p), __func__));
568 (*entry_p)->session_uid = id->session_uid;
569 }
570 else {
571 BLI_assert((*entry_p)->session_uid == id->session_uid);
572 }
573
575 nullptr, id, main_relations_create_idlink_cb, bmain->relations, idwalk_flag);
576 }
578}
579
581{
582 if (bmain->relations != nullptr) {
583 if (bmain->relations->relations_from_pointers != nullptr) {
585 }
587 MEM_freeN(bmain->relations);
588 bmain->relations = nullptr;
589 }
590}
591
592void BKE_main_relations_tag_set(Main *bmain, const eMainIDRelationsEntryTags tag, const bool value)
593{
594 if (bmain->relations == nullptr) {
595 return;
596 }
597
598 GHashIterator *gh_iter;
600 !BLI_ghashIterator_done(gh_iter);
601 BLI_ghashIterator_step(gh_iter))
602 {
603 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
605 if (value) {
606 entry->tags |= tag;
607 }
608 else {
609 entry->tags &= ~tag;
610 }
611 }
612 BLI_ghashIterator_free(gh_iter);
613}
614
616{
617 if (gset == nullptr) {
619 }
620
621 ID *id;
622 FOREACH_MAIN_ID_BEGIN (bmain, id) {
623 BLI_gset_add(gset, id);
624 }
626 return gset;
627}
628
629/* Utils for ID's library weak reference API. */
633
634 LibWeakRefKey(const char *lib_path, const char *id_name)
635 {
636 STRNCPY(this->filepath, lib_path);
637 STRNCPY(this->id_name, id_name);
638 }
639
640 friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
641 {
642 return STREQ(a.filepath, b.filepath) && STREQ(a.id_name, b.id_name);
643 }
644
646 {
647 return blender::get_default_hash(blender::StringRef(this->filepath),
648 blender::StringRef(this->id_name));
649 }
650};
651
655
657{
658 auto *library_weak_reference_mapping = MEM_new<MainLibraryWeakReferenceMap>(__func__);
659
660 ListBase *lb;
661 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
662 ID *id_iter = static_cast<ID *>(lb->first);
663 if (id_iter == nullptr) {
664 continue;
665 }
667 continue;
668 }
670
671 FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) {
672 if (id_iter->library_weak_reference == nullptr) {
673 continue;
674 }
677 library_weak_reference_mapping->map.add(key, id_iter);
678 }
680 }
682
683 return library_weak_reference_mapping;
684}
685
687 MainLibraryWeakReferenceMap *library_weak_reference_mapping)
688{
689 MEM_delete(library_weak_reference_mapping);
690}
691
693 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
694 const char *library_filepath,
695 const char *library_id_name)
696{
697 const LibWeakRefKey key{library_filepath, library_id_name};
698 return library_weak_reference_mapping->map.lookup_default(key, nullptr);
699}
700
702 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
703 const char *library_filepath,
704 const char *library_id_name,
705 ID *new_id)
706{
707 BLI_assert(GS(library_id_name) == GS(new_id->name));
708 BLI_assert(new_id->library_weak_reference == nullptr);
710
711 new_id->library_weak_reference = static_cast<LibraryWeakReference *>(
712 MEM_mallocN(sizeof(*(new_id->library_weak_reference)), __func__));
713
714 const LibWeakRefKey key{library_filepath, library_id_name};
715 library_weak_reference_mapping->map.add_new(key, new_id);
716
717 STRNCPY(new_id->library_weak_reference->library_filepath, library_filepath);
718 STRNCPY(new_id->library_weak_reference->library_id_name, library_id_name);
719}
720
722 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
723 const char *library_filepath,
724 const char *library_id_name,
725 ID *old_id,
726 ID *new_id)
727{
728 BLI_assert(GS(library_id_name) == GS(old_id->name));
729 BLI_assert(GS(library_id_name) == GS(new_id->name));
730 BLI_assert(old_id->library_weak_reference != nullptr);
731 BLI_assert(new_id->library_weak_reference == nullptr);
732 BLI_assert(STREQ(old_id->library_weak_reference->library_filepath, library_filepath));
733 BLI_assert(STREQ(old_id->library_weak_reference->library_id_name, library_id_name));
734
735 const LibWeakRefKey key{library_filepath, library_id_name};
736 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
737 library_weak_reference_mapping->map.add_overwrite(key, new_id);
738
740 old_id->library_weak_reference = nullptr;
741}
742
744 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
745 const char *library_filepath,
746 const char *library_id_name,
747 ID *old_id)
748{
749 BLI_assert(GS(library_id_name) == GS(old_id->name));
750 BLI_assert(old_id->library_weak_reference != nullptr);
751
752 const LibWeakRefKey key{library_filepath, library_id_name};
753
754 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
755 library_weak_reference_mapping->map.remove(key);
756
758}
759
760BlendThumbnail *BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
761{
762 BlendThumbnail *data = nullptr;
763
764 if (bmain) {
766 }
767
768 if (rect) {
769 const size_t data_size = BLEN_THUMB_MEMSIZE(size[0], size[1]);
770 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
771 data->width = size[0];
772 data->height = size[1];
773 memcpy(data->rect, rect, data_size - sizeof(*data));
774 }
775
776 if (bmain) {
777 bmain->blen_thumb = data;
778 }
779 return data;
780}
781
783{
784 BlendThumbnail *data = nullptr;
785
786 if (bmain) {
788 }
789
790 if (img) {
791 const size_t data_size = BLEN_THUMB_MEMSIZE(img->x, img->y);
792 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
793
794 IMB_rect_from_float(img); /* Just in case... */
795 data->width = img->x;
796 data->height = img->y;
797 memcpy(data->rect, img->byte_buffer.data, data_size - sizeof(*data));
798 }
799
800 if (bmain) {
801 bmain->blen_thumb = data;
802 }
803 return data;
804}
805
807{
808 ImBuf *img = nullptr;
809
810 if (!data && bmain) {
811 data = bmain->blen_thumb;
812 }
813
814 if (data) {
816 (const uint8_t *)data->rect, nullptr, uint(data->width), uint(data->height), 4);
817 }
818
819 return img;
820}
821
823{
825
826 bmain->blen_thumb = static_cast<BlendThumbnail *>(
830}
831
832const char *BKE_main_blendfile_path(const Main *bmain)
833{
834 return bmain->filepath;
835}
836
841
842ListBase *which_libbase(Main *bmain, short type)
843{
844 switch ((ID_Type)type) {
845 case ID_SCE:
846 return &(bmain->scenes);
847 case ID_LI:
848 return &(bmain->libraries);
849 case ID_OB:
850 return &(bmain->objects);
851 case ID_ME:
852 return &(bmain->meshes);
853 case ID_CU_LEGACY:
854 return &(bmain->curves);
855 case ID_MB:
856 return &(bmain->metaballs);
857 case ID_MA:
858 return &(bmain->materials);
859 case ID_TE:
860 return &(bmain->textures);
861 case ID_IM:
862 return &(bmain->images);
863 case ID_LT:
864 return &(bmain->lattices);
865 case ID_LA:
866 return &(bmain->lights);
867 case ID_CA:
868 return &(bmain->cameras);
869 case ID_IP:
870 return &(bmain->ipo);
871 case ID_KE:
872 return &(bmain->shapekeys);
873 case ID_WO:
874 return &(bmain->worlds);
875 case ID_SCR:
876 return &(bmain->screens);
877 case ID_VF:
878 return &(bmain->fonts);
879 case ID_TXT:
880 return &(bmain->texts);
881 case ID_SPK:
882 return &(bmain->speakers);
883 case ID_LP:
884 return &(bmain->lightprobes);
885 case ID_SO:
886 return &(bmain->sounds);
887 case ID_GR:
888 return &(bmain->collections);
889 case ID_AR:
890 return &(bmain->armatures);
891 case ID_AC:
892 return &(bmain->actions);
893 case ID_NT:
894 return &(bmain->nodetrees);
895 case ID_BR:
896 return &(bmain->brushes);
897 case ID_PA:
898 return &(bmain->particles);
899 case ID_WM:
900 return &(bmain->wm);
901 case ID_GD_LEGACY:
902 return &(bmain->gpencils);
903 case ID_GP:
904 return &(bmain->grease_pencils);
905 case ID_MC:
906 return &(bmain->movieclips);
907 case ID_MSK:
908 return &(bmain->masks);
909 case ID_LS:
910 return &(bmain->linestyles);
911 case ID_PAL:
912 return &(bmain->palettes);
913 case ID_PC:
914 return &(bmain->paintcurves);
915 case ID_CF:
916 return &(bmain->cachefiles);
917 case ID_WS:
918 return &(bmain->workspaces);
919 case ID_CV:
920 return &(bmain->hair_curves);
921 case ID_PT:
922 return &(bmain->pointclouds);
923 case ID_VO:
924 return &(bmain->volumes);
925 }
926 return nullptr;
927}
928
929int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
930{
931 /* Libraries may be accessed from pretty much any other ID. */
932 lb[INDEX_ID_LI] = &(bmain->libraries);
933
934 lb[INDEX_ID_IP] = &(bmain->ipo);
935
936 /* Moved here to avoid problems when freeing with animato (aligorith). */
937 lb[INDEX_ID_AC] = &(bmain->actions);
938
939 lb[INDEX_ID_KE] = &(bmain->shapekeys);
940
941 /* Referenced by gpencil, so needs to be before that to avoid crashes. */
942 lb[INDEX_ID_PAL] = &(bmain->palettes);
943
944 /* Referenced by nodes, objects, view, scene etc, before to free after. */
945 lb[INDEX_ID_GD_LEGACY] = &(bmain->gpencils);
946 lb[INDEX_ID_GP] = &(bmain->grease_pencils);
947
948 lb[INDEX_ID_NT] = &(bmain->nodetrees);
949 lb[INDEX_ID_IM] = &(bmain->images);
950 lb[INDEX_ID_TE] = &(bmain->textures);
951 lb[INDEX_ID_MA] = &(bmain->materials);
952 lb[INDEX_ID_VF] = &(bmain->fonts);
953
954 /* Important!: When adding a new object type,
955 * the specific data should be inserted here. */
956
957 lb[INDEX_ID_AR] = &(bmain->armatures);
958
959 lb[INDEX_ID_CF] = &(bmain->cachefiles);
960 lb[INDEX_ID_ME] = &(bmain->meshes);
961 lb[INDEX_ID_CU_LEGACY] = &(bmain->curves);
962 lb[INDEX_ID_MB] = &(bmain->metaballs);
963 lb[INDEX_ID_CV] = &(bmain->hair_curves);
964 lb[INDEX_ID_PT] = &(bmain->pointclouds);
965 lb[INDEX_ID_VO] = &(bmain->volumes);
966
967 lb[INDEX_ID_LT] = &(bmain->lattices);
968 lb[INDEX_ID_LA] = &(bmain->lights);
969 lb[INDEX_ID_CA] = &(bmain->cameras);
970
971 lb[INDEX_ID_TXT] = &(bmain->texts);
972 lb[INDEX_ID_SO] = &(bmain->sounds);
973 lb[INDEX_ID_GR] = &(bmain->collections);
974 lb[INDEX_ID_PAL] = &(bmain->palettes);
975 lb[INDEX_ID_PC] = &(bmain->paintcurves);
976 lb[INDEX_ID_BR] = &(bmain->brushes);
977 lb[INDEX_ID_PA] = &(bmain->particles);
978 lb[INDEX_ID_SPK] = &(bmain->speakers);
979 lb[INDEX_ID_LP] = &(bmain->lightprobes);
980
981 lb[INDEX_ID_WO] = &(bmain->worlds);
982 lb[INDEX_ID_MC] = &(bmain->movieclips);
983 lb[INDEX_ID_SCR] = &(bmain->screens);
984 lb[INDEX_ID_OB] = &(bmain->objects);
985 lb[INDEX_ID_LS] = &(bmain->linestyles); /* referenced by scenes */
986 lb[INDEX_ID_SCE] = &(bmain->scenes);
987 lb[INDEX_ID_WS] = &(bmain->workspaces); /* before wm, so it's freed after it! */
988 lb[INDEX_ID_WM] = &(bmain->wm);
989 lb[INDEX_ID_MSK] = &(bmain->masks);
990
991 lb[INDEX_ID_NULL] = nullptr;
992
993 return (INDEX_ID_MAX - 1);
994}
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports, BPathSummary *r_summary=nullptr)
Definition bpath.cc:624
void BKE_bpath_relative_rebase(Main *bmain, const char *basedir_src, const char *basedir_dst, ReportList *reports, BPathSummary *r_summary=nullptr)
Definition bpath.cc:475
#define G_MAIN
bool BKE_idtype_idcode_is_linkable(short idcode)
Definition idtype.cc:201
bool BKE_idtype_idcode_append_is_reusable(short idcode)
Definition idtype.cc:220
void BKE_libblock_management_main_remove(Main *bmain, void *idv)
Definition lib_id.cc:1130
#define MAIN_ID_SESSION_UID_UNSET
@ LIB_ID_FREE_NO_UI_USER
@ LIB_ID_FREE_NO_DEG_TAG
@ LIB_ID_FREE_NO_USER_REFCOUNT
@ LIB_ID_FREE_NO_MAIN
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:1097
@ IDWALK_RET_NOP
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, int flag)
Definition lib_query.cc:416
@ IDWALK_INCLUDE_UI
@ IDWALK_READONLY
@ ID_REMAP_DO_LIBRARY_POINTERS
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:782
@ ID_REMAP_TYPE_REMAP
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:500
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:469
@ MAINIDRELATIONS_INCLUDE_UI
Definition BKE_main.hh:119
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:463
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:481
#define BLEN_THUMB_SIZE
Definition BKE_main.hh:595
eMainIDRelationsEntryTags
Definition BKE_main.hh:79
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:474
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:494
#define BLEN_THUMB_MEMSIZE(_x, _y)
Definition BKE_main.hh:597
void BKE_main_idmap_destroy(IDNameLib_Map *id_map) ATTR_NONNULL()
void BKE_main_namemap_destroy(UniqueName_Map **r_name_map) ATTR_NONNULL()
void BKE_main_namemap_clear(Main *bmain) ATTR_NONNULL()
bool BKE_main_namemap_validate(Main *bmain) ATTR_NONNULL()
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
struct GSet GSet
Definition BLI_ghash.h:341
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition BLI_ghash.c:911
unsigned int BLI_ghashutil_ptrhash(const void *key)
void BLI_ghashIterator_free(GHashIterator *ghi)
Definition BLI_ghash.c:925
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:303
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:686
GHashIterator * BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:888
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:944
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.c:860
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.c:752
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.c:966
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:311
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void * BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(1)
BLI_mempool * BLI_mempool_create(unsigned int esize, unsigned int elem_num, unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
@ BLI_MEMPOOL_NOP
Definition BLI_mempool.h:86
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
#define FILE_MAX
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
int BLI_path_normalize_native(char *path) ATTR_NONNULL(1)
#define FILE_MAXDIR
#define STRNCPY(dst, src)
Definition BLI_string.h:593
unsigned int uint
pthread_spinlock_t SpinLock
void BLI_spin_init(SpinLock *spin)
Definition threads.cc:391
void BLI_spin_unlock(SpinLock *spin)
Definition threads.cc:430
void BLI_spin_lock(SpinLock *spin)
Definition threads.cc:405
void BLI_spin_end(SpinLock *spin)
Definition threads.cc:445
#define UNUSED_VARS_NDEBUG(...)
#define STREQ(a, b)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
ID and Library types, which are fundamental for SDNA.
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:654
#define MAX_ID_NAME
Definition DNA_ID.h:377
#define INDEX_ID_MAX
Definition DNA_ID.h:1328
eID_Index
Definition DNA_ID.h:1246
@ INDEX_ID_TXT
Definition DNA_ID.h:1269
@ INDEX_ID_WM
Definition DNA_ID.h:1322
@ INDEX_ID_VO
Definition DNA_ID.h:1298
@ INDEX_ID_NULL
Definition DNA_ID.h:1325
@ INDEX_ID_CF
Definition DNA_ID.h:1285
@ INDEX_ID_CV
Definition DNA_ID.h:1296
@ INDEX_ID_PT
Definition DNA_ID.h:1297
@ INDEX_ID_GR
Definition DNA_ID.h:1308
@ INDEX_ID_LA
Definition DNA_ID.h:1300
@ INDEX_ID_LT
Definition DNA_ID.h:1299
@ INDEX_ID_PC
Definition DNA_ID.h:1313
@ INDEX_ID_MA
Definition DNA_ID.h:1280
@ INDEX_ID_IM
Definition DNA_ID.h:1275
@ INDEX_ID_OB
Definition DNA_ID.h:1307
@ INDEX_ID_ME
Definition DNA_ID.h:1293
@ INDEX_ID_SO
Definition DNA_ID.h:1270
@ INDEX_ID_VF
Definition DNA_ID.h:1268
@ INDEX_ID_MC
Definition DNA_ID.h:1276
@ INDEX_ID_MSK
Definition DNA_ID.h:1274
@ INDEX_ID_BR
Definition DNA_ID.h:1314
@ INDEX_ID_WS
Definition DNA_ID.h:1321
@ INDEX_ID_SCR
Definition DNA_ID.h:1320
@ INDEX_ID_SPK
Definition DNA_ID.h:1302
@ INDEX_ID_MB
Definition DNA_ID.h:1295
@ INDEX_ID_CU_LEGACY
Definition DNA_ID.h:1294
@ INDEX_ID_LI
Definition DNA_ID.h:1248
@ INDEX_ID_IP
Definition DNA_ID.h:1251
@ INDEX_ID_NT
Definition DNA_ID.h:1264
@ INDEX_ID_WO
Definition DNA_ID.h:1282
@ INDEX_ID_TE
Definition DNA_ID.h:1279
@ INDEX_ID_PAL
Definition DNA_ID.h:1312
@ INDEX_ID_GP
Definition DNA_ID.h:1304
@ INDEX_ID_LS
Definition DNA_ID.h:1281
@ INDEX_ID_SCE
Definition DNA_ID.h:1317
@ INDEX_ID_GD_LEGACY
Definition DNA_ID.h:1258
@ INDEX_ID_LP
Definition DNA_ID.h:1303
@ INDEX_ID_AC
Definition DNA_ID.h:1252
@ INDEX_ID_CA
Definition DNA_ID.h:1301
@ INDEX_ID_AR
Definition DNA_ID.h:1292
@ INDEX_ID_PA
Definition DNA_ID.h:1286
@ INDEX_ID_KE
Definition DNA_ID.h:1289
ID_Type
@ ID_WM
@ ID_CA
@ ID_AR
@ ID_MC
@ ID_CF
@ ID_LI
@ ID_TE
@ ID_IM
@ ID_VO
@ ID_WS
@ ID_NT
@ ID_LA
@ ID_KE
@ ID_TXT
@ ID_SO
@ ID_SCE
@ ID_LS
@ ID_MSK
@ ID_CV
@ ID_PAL
@ ID_BR
@ ID_LP
@ ID_WO
@ ID_MA
@ ID_AC
@ ID_SCR
@ ID_CU_LEGACY
@ ID_GD_LEGACY
@ ID_VF
@ ID_ME
@ ID_IP
@ ID_GR
@ ID_SPK
@ ID_MB
@ ID_LT
@ ID_OB
@ ID_GP
@ ID_PA
@ ID_PT
@ ID_PC
void IMB_rect_from_float(ImBuf *ibuf)
Definition divers.cc:694
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
bool add_overwrite(const Key &key, const Value &value)
Definition BLI_map.hh:301
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
const Value & lookup(const Key &key) const
Definition BLI_map.hh:506
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:531
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:241
bool remove(const Key &key)
Definition BLI_map.hh:344
bool contains(const Key &key) const
Definition BLI_map.hh:329
Value & lookup_or_add(const Key &key, const Value &value)
Definition BLI_map.hh:551
int64_t size() const
void append(const T &value)
bool is_empty() const
void add(ID *old_id, ID *new_id)
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
struct ImBuf * IMB_allocFromBuffer(const uint8_t *, const float *, unsigned int, unsigned int, unsigned int)
#define GS(x)
Definition iris.cc:202
ID * BKE_main_library_weak_reference_search_item(MainLibraryWeakReferenceMap *library_weak_reference_mapping, const char *library_filepath, const char *library_id_name)
Definition main.cc:692
BlendThumbnail * BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
Definition main.cc:782
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:842
void BKE_main_clear(Main &bmain)
Definition main.cc:64
void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &reports)
Definition main.cc:321
void BKE_main_library_weak_reference_remove_item(MainLibraryWeakReferenceMap *library_weak_reference_mapping, const char *library_filepath, const char *library_id_name, ID *old_id)
Definition main.cc:743
void BKE_main_destroy(Main &bmain)
Definition main.cc:166
bool BKE_main_needs_overwrite_confirm(const Main *bmain)
Definition main.cc:474
bool BKE_main_has_issues(const Main *bmain)
Definition main.cc:469
Main * BKE_main_new()
Definition main.cc:45
void BKE_main_lock(Main *bmain)
Definition main.cc:479
void BKE_main_relations_tag_set(Main *bmain, const eMainIDRelationsEntryTags tag, const bool value)
Definition main.cc:592
int set_listbasepointers(Main *bmain, ListBase *lb[])
Definition main.cc:929
void BKE_main_thumbnail_create(Main *bmain)
Definition main.cc:822
ImBuf * BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
Definition main.cc:806
void BKE_main_init(Main &bmain)
Definition main.cc:52
void BKE_main_relations_create(Main *bmain, const short flag)
Definition main.cc:544
MainLibraryWeakReferenceMap * BKE_main_library_weak_reference_create(Main *bmain)
Definition main.cc:656
void BKE_main_library_weak_reference_add_item(MainLibraryWeakReferenceMap *library_weak_reference_mapping, const char *library_filepath, const char *library_id_name, ID *new_id)
Definition main.cc:701
void BKE_main_free(Main *bmain)
Definition main.cc:175
void BKE_main_library_weak_reference_destroy(MainLibraryWeakReferenceMap *library_weak_reference_mapping)
Definition main.cc:686
void BKE_main_library_weak_reference_update_item(MainLibraryWeakReferenceMap *library_weak_reference_mapping, const char *library_filepath, const char *library_id_name, ID *old_id, ID *new_id)
Definition main.cc:721
BlendThumbnail * BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
Definition main.cc:760
const char * BKE_main_blendfile_path(const Main *bmain)
Definition main.cc:832
static CLG_LogRef LOG
Definition main.cc:43
void BKE_main_unlock(Main *bmain)
Definition main.cc:484
static bool are_ids_from_different_mains_matching(Main *bmain_1, ID *id_1, Main *bmain_2, ID *id_2)
Definition main.cc:192
static void main_merge_add_id_to_move(Main *bmain_dst, blender::Map< std::string, blender::Vector< ID * > > &id_map_dst, ID *id_src, id::IDRemapper &id_remapper, blender::Vector< ID * > &ids_to_move, const bool is_library, MainMergeReport &reports)
Definition main.cc:281
bool BKE_main_is_empty(Main *bmain)
Definition main.cc:457
static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
Definition main.cc:489
GSet * BKE_main_gset_create(Main *bmain, GSet *gset)
Definition main.cc:615
void BKE_main_relations_free(Main *bmain)
Definition main.cc:580
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:837
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
uint64_t get_default_hash(const T &v)
Definition BLI_hash.hh:219
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90
Definition DNA_ID.h:413
struct Library * lib
Definition DNA_ID.h:419
char name[66]
Definition DNA_ID.h:425
unsigned int session_uid
Definition DNA_ID.h:454
struct LibraryWeakReference * library_weak_reference
Definition DNA_ID.h:490
ImBufByteBuffer byte_buffer
friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
Definition main.cc:640
char filepath[FILE_MAX]
Definition main.cc:631
uint64_t hash() const
Definition main.cc:645
LibWeakRefKey(const char *lib_path, const char *id_name)
Definition main.cc:634
char id_name[MAX_ID_NAME]
Definition main.cc:632
char library_filepath[1024]
Definition DNA_ID.h:571
char library_id_name[66]
Definition DNA_ID.h:574
char filepath_abs[1024]
Definition DNA_ID.h:509
struct Library_Runtime runtime
Definition DNA_ID.h:535
void * first
union MainIDRelationsEntryItem::@41 id_pointer
MainIDRelationsEntryItem * next
Definition BKE_main.hh:51
GHash * relations_from_pointers
Definition BKE_main.hh:108
BLI_mempool * entry_items_pool
Definition BKE_main.hh:114
blender::Map< LibWeakRefKey, ID * > map
Definition main.cc:653
int num_remapped_libraries
Definition BKE_main.hh:329
ReportList * reports
Definition BKE_main.hh:316
ListBase volumes
Definition BKE_main.hh:253
ListBase lightprobes
Definition BKE_main.hh:229
ListBase brushes
Definition BKE_main.hh:235
ListBase masks
Definition BKE_main.hh:243
ListBase scenes
Definition BKE_main.hh:210
ListBase grease_pencils
Definition BKE_main.hh:241
UniqueName_Map * name_map_global
Definition BKE_main.hh:270
ListBase wm
Definition BKE_main.hh:239
bool is_asset_edit_file
Definition BKE_main.hh:151
bool has_forward_compatibility_issues
Definition BKE_main.hh:144
ListBase textures
Definition BKE_main.hh:217
ListBase actions
Definition BKE_main.hh:233
UniqueName_Map * name_map
Definition BKE_main.hh:266
ListBase texts
Definition BKE_main.hh:227
ListBase meshes
Definition BKE_main.hh:213
char filepath[1024]
Definition BKE_main.hh:136
ListBase movieclips
Definition BKE_main.hh:242
ListBase ipo
Definition BKE_main.hh:222
ListBase hair_curves
Definition BKE_main.hh:251
ListBase lights
Definition BKE_main.hh:220
ListBase paintcurves
Definition BKE_main.hh:238
ListBase fonts
Definition BKE_main.hh:226
ListBase nodetrees
Definition BKE_main.hh:234
BlendThumbnail * blen_thumb
Definition BKE_main.hh:207
ListBase particles
Definition BKE_main.hh:236
ListBase materials
Definition BKE_main.hh:216
bool is_action_slot_to_id_map_dirty
Definition BKE_main.hh:205
ListBase linestyles
Definition BKE_main.hh:244
ListBase pointclouds
Definition BKE_main.hh:252
ListBase lattices
Definition BKE_main.hh:219
ListBase sounds
Definition BKE_main.hh:230
ListBase shapekeys
Definition BKE_main.hh:223
ListBase libraries
Definition BKE_main.hh:211
ListBase cameras
Definition BKE_main.hh:221
IDNameLib_Map * id_map
Definition BKE_main.hh:263
ListBase armatures
Definition BKE_main.hh:232
ListBase speakers
Definition BKE_main.hh:228
MainLock * lock
Definition BKE_main.hh:272
ListBase curves
Definition BKE_main.hh:214
Main * next
Definition BKE_main.hh:123
ListBase worlds
Definition BKE_main.hh:224
ListBase screens
Definition BKE_main.hh:225
ListBase workspaces
Definition BKE_main.hh:246
ListBase palettes
Definition BKE_main.hh:237
ListBase metaballs
Definition BKE_main.hh:215
bool is_global_main
Definition BKE_main.hh:191
ListBase collections
Definition BKE_main.hh:231
ListBase images
Definition BKE_main.hh:218
ListBase gpencils
Definition BKE_main.hh:240
MainIDRelations * relations
Definition BKE_main.hh:260
ListBase objects
Definition BKE_main.hh:212
ListBase cachefiles
Definition BKE_main.hh:245
uint8_t flag
Definition wm_window.cc:138