Blender V4.5
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
10
11#include <cstring>
12#include <iostream>
13
14#include "CLG_log.h"
15
16#include "MEM_guardedalloc.h"
17
18#include "BLI_ghash.h"
19#include "BLI_listbase.h"
20#include "BLI_map.hh"
21#include "BLI_mempool.h"
22#include "BLI_path_utils.hh"
23#include "BLI_string.h"
24#include "BLI_threads.h"
25#include "BLI_vector.hh"
26
27#include "DNA_ID.h"
28
29#include "BKE_bpath.hh"
30#include "BKE_global.hh"
31#include "BKE_idtype.hh"
32#include "BKE_lib_id.hh"
33#include "BKE_lib_query.hh"
34#include "BKE_lib_remap.hh"
35#include "BKE_library.hh"
36#include "BKE_main.hh"
37#include "BKE_main_idmap.hh"
38#include "BKE_main_namemap.hh"
39#include "BKE_report.hh"
40
41#include "IMB_imbuf.hh"
42#include "IMB_imbuf_types.hh"
43
44using namespace blender::bke;
45
46static CLG_LogRef LOG = {"bke.main"};
47
49{
50 Main *bmain = MEM_callocN<Main>("new main");
51 BKE_main_init(*bmain);
52 return bmain;
53}
54
55void BKE_main_init(Main &bmain)
56{
57 SpinLock *main_lock = MEM_mallocN<SpinLock>("main lock");
58 BLI_spin_init(main_lock);
59 bmain.lock = (MainLock *)main_lock;
60 bmain.is_global_main = false;
61
62 /* Just rebuilding the Action Slot to ID* map once is likely cheaper than,
63 * for every ID, when it's loaded from disk, check whether it's animated or
64 * not, and then figure out which Main it went into, and then set the flag. */
66}
67
68void BKE_main_clear(Main &bmain)
69{
70 /* Also call when reading a file, erase all, etc */
71
72 /* Since we are removing whole main, no need to bother 'properly' (and slowly) removing each ID
73 * from it. */
74 const int free_flag = (LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_UI_USER |
76
78
79 MainListsArray lbarray = BKE_main_lists_get(bmain);
80 int a = lbarray.size();
81 while (a--) {
82 ListBase *lb = lbarray[a];
83 ID *id, *id_next;
84
85 for (id = static_cast<ID *>(lb->first); id != nullptr; id = id_next) {
86 id_next = static_cast<ID *>(id->next);
87#if 1
88 BKE_id_free_ex(&bmain, id, free_flag, false);
89#else
90 /* Errors freeing ID's can be hard to track down,
91 * enable this so VALGRIND or ASAN will give the line number in its error log. */
92
93# define CASE_ID_INDEX(id_index) \
94 case id_index: \
95 BKE_id_free_ex(&bmain, id, free_flag, false); \
96 break
97
98 switch ((eID_Index)a) {
99 CASE_ID_INDEX(INDEX_ID_LI);
100 CASE_ID_INDEX(INDEX_ID_IP);
101 CASE_ID_INDEX(INDEX_ID_AC);
102 CASE_ID_INDEX(INDEX_ID_GD_LEGACY);
103 CASE_ID_INDEX(INDEX_ID_NT);
104 CASE_ID_INDEX(INDEX_ID_VF);
105 CASE_ID_INDEX(INDEX_ID_TXT);
106 CASE_ID_INDEX(INDEX_ID_SO);
107 CASE_ID_INDEX(INDEX_ID_MSK);
108 CASE_ID_INDEX(INDEX_ID_IM);
109 CASE_ID_INDEX(INDEX_ID_MC);
110 CASE_ID_INDEX(INDEX_ID_TE);
111 CASE_ID_INDEX(INDEX_ID_MA);
112 CASE_ID_INDEX(INDEX_ID_LS);
113 CASE_ID_INDEX(INDEX_ID_WO);
114 CASE_ID_INDEX(INDEX_ID_CF);
115 CASE_ID_INDEX(INDEX_ID_SIM);
116 CASE_ID_INDEX(INDEX_ID_PA);
117 CASE_ID_INDEX(INDEX_ID_KE);
118 CASE_ID_INDEX(INDEX_ID_AR);
119 CASE_ID_INDEX(INDEX_ID_ME);
120 CASE_ID_INDEX(INDEX_ID_CU_LEGACY);
121 CASE_ID_INDEX(INDEX_ID_MB);
122 CASE_ID_INDEX(INDEX_ID_CV);
123 CASE_ID_INDEX(INDEX_ID_PT);
124 CASE_ID_INDEX(INDEX_ID_VO);
125 CASE_ID_INDEX(INDEX_ID_LT);
126 CASE_ID_INDEX(INDEX_ID_LA);
127 CASE_ID_INDEX(INDEX_ID_CA);
128 CASE_ID_INDEX(INDEX_ID_SPK);
129 CASE_ID_INDEX(INDEX_ID_LP);
130 CASE_ID_INDEX(INDEX_ID_OB);
131 CASE_ID_INDEX(INDEX_ID_GR);
132 CASE_ID_INDEX(INDEX_ID_PAL);
133 CASE_ID_INDEX(INDEX_ID_PC);
134 CASE_ID_INDEX(INDEX_ID_BR);
135 CASE_ID_INDEX(INDEX_ID_SCE);
136 CASE_ID_INDEX(INDEX_ID_SCR);
137 CASE_ID_INDEX(INDEX_ID_WS);
138 CASE_ID_INDEX(INDEX_ID_WM);
139 case INDEX_ID_NULL: {
141 break;
142 }
143 }
144
145# undef CASE_ID_INDEX
146
147#endif
148 }
150 }
151
152 if (bmain.relations) {
154 }
155
156 if (bmain.id_map) {
158 }
159
160 /* NOTE: `name_map` in libraries are freed together with the library IDs above. */
163}
164
166{
167 BKE_main_clear(bmain);
168
169 BLI_spin_end(reinterpret_cast<SpinLock *>(bmain.lock));
170 /* The void cast is needed when building without TBB. */
171 MEM_freeN((void *)reinterpret_cast<SpinLock *>(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) {
218 BLI_assert(STREQ(lib_1->runtime->filepath_abs, lib_2->runtime->filepath_abs));
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,
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,
444 reports.num_remapped_libraries,
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 LibraryForeachIDCallbackFlag 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 = MEM_callocN<MainIDRelationsEntry>(__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 = MEM_callocN<MainIDRelationsEntry>(__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 = MEM_mallocN<MainIDRelations>(__func__);
554 sizeof(MainIDRelationsEntryItem), 128, 128, BLI_MEMPOOL_NOP);
555
556 bmain->relations->flag = flag;
557
558 ID *id;
559 FOREACH_MAIN_ID_BEGIN (bmain, id) {
560 const LibraryForeachIDFlag idwalk_flag = IDWALK_READONLY |
563 IDWALK_NOP);
564
565 /* Ensure all IDs do have an entry, even if they are not connected to any other. */
566 MainIDRelationsEntry **entry_p;
567 if (!BLI_ghash_ensure_p(bmain->relations->relations_from_pointers, id, (void ***)&entry_p)) {
568 *entry_p = MEM_callocN<MainIDRelationsEntry>(__func__);
569 (*entry_p)->session_uid = id->session_uid;
570 }
571 else {
572 BLI_assert((*entry_p)->session_uid == id->session_uid);
573 }
574
576 nullptr, id, main_relations_create_idlink_cb, bmain->relations, idwalk_flag);
577 }
579}
580
582{
583 if (bmain->relations != nullptr) {
584 if (bmain->relations->relations_from_pointers != nullptr) {
586 }
588 MEM_freeN(bmain->relations);
589 bmain->relations = nullptr;
590 }
591}
592
593void BKE_main_relations_tag_set(Main *bmain, const eMainIDRelationsEntryTags tag, const bool value)
594{
595 if (bmain->relations == nullptr) {
596 return;
597 }
598
599 GHashIterator *gh_iter;
601 !BLI_ghashIterator_done(gh_iter);
602 BLI_ghashIterator_step(gh_iter))
603 {
604 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
606 if (value) {
607 entry->tags |= tag;
608 }
609 else {
610 entry->tags &= ~tag;
611 }
612 }
613 BLI_ghashIterator_free(gh_iter);
614}
615
617{
618 if (gset == nullptr) {
620 }
621
622 ID *id;
623 FOREACH_MAIN_ID_BEGIN (bmain, id) {
624 BLI_gset_add(gset, id);
625 }
627 return gset;
628}
629
630/* Utils for ID's library weak reference API. */
634
635 LibWeakRefKey(const char *lib_path, const char *id_name)
636 {
637 STRNCPY(this->filepath, lib_path);
638 STRNCPY(this->id_name, id_name);
639 }
640
641 friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
642 {
643 return STREQ(a.filepath, b.filepath) && STREQ(a.id_name, b.id_name);
644 }
645
647 {
648 return blender::get_default_hash(blender::StringRef(this->filepath),
649 blender::StringRef(this->id_name));
650 }
651};
652
656
658{
659 auto *library_weak_reference_mapping = MEM_new<MainLibraryWeakReferenceMap>(__func__);
660
661 ListBase *lb;
662 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
663 ID *id_iter = static_cast<ID *>(lb->first);
664 if (id_iter == nullptr) {
665 continue;
666 }
668 continue;
669 }
671
672 FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) {
673 if (id_iter->library_weak_reference == nullptr) {
674 continue;
675 }
678 library_weak_reference_mapping->map.add(key, id_iter);
679 }
681 }
683
684 return library_weak_reference_mapping;
685}
686
688 MainLibraryWeakReferenceMap *library_weak_reference_mapping)
689{
690 MEM_delete(library_weak_reference_mapping);
691}
692
694 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
695 const char *library_filepath,
696 const char *library_id_name)
697{
698 const LibWeakRefKey key{library_filepath, library_id_name};
699 return library_weak_reference_mapping->map.lookup_default(key, nullptr);
700}
701
703 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
704 const char *library_filepath,
705 const char *library_id_name,
706 ID *new_id)
707{
708 BLI_assert(GS(library_id_name) == GS(new_id->name));
709 BLI_assert(new_id->library_weak_reference == nullptr);
711
712 const LibWeakRefKey key{library_filepath, library_id_name};
713 library_weak_reference_mapping->map.add_new(key, new_id);
714
715 BKE_main_library_weak_reference_add(new_id, library_filepath, library_id_name);
716}
717
719 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
720 const char *library_filepath,
721 const char *library_id_name,
722 ID *old_id,
723 ID *new_id)
724{
725 BLI_assert(GS(library_id_name) == GS(old_id->name));
726 BLI_assert(GS(library_id_name) == GS(new_id->name));
727 BLI_assert(old_id->library_weak_reference != nullptr);
728 BLI_assert(new_id->library_weak_reference == nullptr);
729 BLI_assert(STREQ(old_id->library_weak_reference->library_filepath, library_filepath));
730 BLI_assert(STREQ(old_id->library_weak_reference->library_id_name, library_id_name));
731
732 const LibWeakRefKey key{library_filepath, library_id_name};
733 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
734 library_weak_reference_mapping->map.add_overwrite(key, new_id);
735
737 old_id->library_weak_reference = nullptr;
738}
739
741 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
742 const char *library_filepath,
743 const char *library_id_name,
744 ID *old_id)
745{
746 BLI_assert(GS(library_id_name) == GS(old_id->name));
747 BLI_assert(old_id->library_weak_reference != nullptr);
748
749 const LibWeakRefKey key{library_filepath, library_id_name};
750
751 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
752 library_weak_reference_mapping->map.remove(key);
753
755}
756
758 const char *library_filepath,
759 const char *library_id_name)
760{
761 /* Make filepath absolute so we can compare filepaths that may be either relative or absolute. */
762 char library_filepath_abs[FILE_MAX];
763 STRNCPY(library_filepath_abs, library_filepath);
764 BLI_path_abs(library_filepath_abs, BKE_main_blendfile_path(bmain));
765
766 ListBase *id_list = which_libbase(bmain, GS(library_id_name));
767 LISTBASE_FOREACH (ID *, existing_id, id_list) {
768 if (!(existing_id->library_weak_reference &&
769 STREQ(existing_id->library_weak_reference->library_id_name, library_id_name)))
770 {
771 continue;
772 }
773
774 char existing_filepath_abs[FILE_MAX];
775 STRNCPY(existing_filepath_abs, existing_id->library_weak_reference->library_filepath);
776 BLI_path_abs(existing_filepath_abs, BKE_main_blendfile_path(bmain));
777
778 if (!STREQ(existing_filepath_abs, library_filepath_abs)) {
779 continue;
780 }
781
782 return existing_id;
783 }
784
785 return nullptr;
786}
787
789 const char *library_filepath,
790 const char *library_id_name)
791{
792 if (local_id->library_weak_reference == nullptr) {
794 }
795
796 STRNCPY(local_id->library_weak_reference->library_filepath, library_filepath);
797 STRNCPY(local_id->library_weak_reference->library_id_name, library_id_name);
798}
799
800BlendThumbnail *BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
801{
802 BlendThumbnail *data = nullptr;
803
804 if (bmain) {
806 }
807
808 if (rect) {
809 const size_t data_size = BLEN_THUMB_MEMSIZE(size[0], size[1]);
810 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
811 data->width = size[0];
812 data->height = size[1];
813 memcpy(data->rect, rect, data_size - sizeof(*data));
814 }
815
816 if (bmain) {
817 bmain->blen_thumb = data;
818 }
819 return data;
820}
821
823{
824 BlendThumbnail *data = nullptr;
825
826 if (bmain) {
828 }
829
830 if (img) {
831 const size_t data_size = BLEN_THUMB_MEMSIZE(img->x, img->y);
832 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
833
834 IMB_byte_from_float(img); /* Just in case... */
835 data->width = img->x;
836 data->height = img->y;
837 memcpy(data->rect, img->byte_buffer.data, data_size - sizeof(*data));
838 }
839
840 if (bmain) {
841 bmain->blen_thumb = data;
842 }
843 return data;
844}
845
847{
848 ImBuf *img = nullptr;
849
850 if (!data && bmain) {
851 data = bmain->blen_thumb;
852 }
853
854 if (data) {
856 (const uint8_t *)data->rect, nullptr, uint(data->width), uint(data->height), 4);
857 }
858
859 return img;
860}
861
863{
865
866 bmain->blen_thumb = static_cast<BlendThumbnail *>(
870}
871
872const char *BKE_main_blendfile_path(const Main *bmain)
873{
874 return bmain->filepath;
875}
876
881
882ListBase *which_libbase(Main *bmain, short type)
883{
884 switch ((ID_Type)type) {
885 case ID_SCE:
886 return &(bmain->scenes);
887 case ID_LI:
888 return &(bmain->libraries);
889 case ID_OB:
890 return &(bmain->objects);
891 case ID_ME:
892 return &(bmain->meshes);
893 case ID_CU_LEGACY:
894 return &(bmain->curves);
895 case ID_MB:
896 return &(bmain->metaballs);
897 case ID_MA:
898 return &(bmain->materials);
899 case ID_TE:
900 return &(bmain->textures);
901 case ID_IM:
902 return &(bmain->images);
903 case ID_LT:
904 return &(bmain->lattices);
905 case ID_LA:
906 return &(bmain->lights);
907 case ID_CA:
908 return &(bmain->cameras);
909 case ID_IP:
910 return &(bmain->ipo);
911 case ID_KE:
912 return &(bmain->shapekeys);
913 case ID_WO:
914 return &(bmain->worlds);
915 case ID_SCR:
916 return &(bmain->screens);
917 case ID_VF:
918 return &(bmain->fonts);
919 case ID_TXT:
920 return &(bmain->texts);
921 case ID_SPK:
922 return &(bmain->speakers);
923 case ID_LP:
924 return &(bmain->lightprobes);
925 case ID_SO:
926 return &(bmain->sounds);
927 case ID_GR:
928 return &(bmain->collections);
929 case ID_AR:
930 return &(bmain->armatures);
931 case ID_AC:
932 return &(bmain->actions);
933 case ID_NT:
934 return &(bmain->nodetrees);
935 case ID_BR:
936 return &(bmain->brushes);
937 case ID_PA:
938 return &(bmain->particles);
939 case ID_WM:
940 return &(bmain->wm);
941 case ID_GD_LEGACY:
942 return &(bmain->gpencils);
943 case ID_GP:
944 return &(bmain->grease_pencils);
945 case ID_MC:
946 return &(bmain->movieclips);
947 case ID_MSK:
948 return &(bmain->masks);
949 case ID_LS:
950 return &(bmain->linestyles);
951 case ID_PAL:
952 return &(bmain->palettes);
953 case ID_PC:
954 return &(bmain->paintcurves);
955 case ID_CF:
956 return &(bmain->cachefiles);
957 case ID_WS:
958 return &(bmain->workspaces);
959 case ID_CV:
960 return &(bmain->hair_curves);
961 case ID_PT:
962 return &(bmain->pointclouds);
963 case ID_VO:
964 return &(bmain->volumes);
965 }
966 return nullptr;
967}
968
970{
971 MainListsArray lb{};
972 /* Libraries may be accessed from pretty much any other ID. */
973 lb[INDEX_ID_LI] = &bmain.libraries;
974
975 lb[INDEX_ID_IP] = &bmain.ipo;
976
977 /* Moved here to avoid problems when freeing with animato (aligorith). */
978 lb[INDEX_ID_AC] = &bmain.actions;
979
980 lb[INDEX_ID_KE] = &bmain.shapekeys;
981
982 /* Referenced by gpencil, so needs to be before that to avoid crashes. */
983 lb[INDEX_ID_PAL] = &bmain.palettes;
984
985 /* Referenced by nodes, objects, view, scene etc, before to free after. */
986 lb[INDEX_ID_GD_LEGACY] = &bmain.gpencils;
987 lb[INDEX_ID_GP] = &bmain.grease_pencils;
988
989 lb[INDEX_ID_NT] = &bmain.nodetrees;
990 lb[INDEX_ID_IM] = &bmain.images;
991 lb[INDEX_ID_TE] = &bmain.textures;
992 lb[INDEX_ID_MA] = &bmain.materials;
993 lb[INDEX_ID_VF] = &bmain.fonts;
994
995 /* Important!: When adding a new object type,
996 * the specific data should be inserted here. */
997
998 lb[INDEX_ID_AR] = &bmain.armatures;
999
1000 lb[INDEX_ID_CF] = &bmain.cachefiles;
1001 lb[INDEX_ID_ME] = &bmain.meshes;
1002 lb[INDEX_ID_CU_LEGACY] = &bmain.curves;
1003 lb[INDEX_ID_MB] = &bmain.metaballs;
1004 lb[INDEX_ID_CV] = &bmain.hair_curves;
1005 lb[INDEX_ID_PT] = &bmain.pointclouds;
1006 lb[INDEX_ID_VO] = &bmain.volumes;
1007
1008 lb[INDEX_ID_LT] = &bmain.lattices;
1009 lb[INDEX_ID_LA] = &bmain.lights;
1010 lb[INDEX_ID_CA] = &bmain.cameras;
1011
1012 lb[INDEX_ID_TXT] = &bmain.texts;
1013 lb[INDEX_ID_SO] = &bmain.sounds;
1014 lb[INDEX_ID_GR] = &bmain.collections;
1015 lb[INDEX_ID_PAL] = &bmain.palettes;
1016 lb[INDEX_ID_PC] = &bmain.paintcurves;
1017 lb[INDEX_ID_BR] = &bmain.brushes;
1018 lb[INDEX_ID_PA] = &bmain.particles;
1019 lb[INDEX_ID_SPK] = &bmain.speakers;
1020 lb[INDEX_ID_LP] = &bmain.lightprobes;
1021
1022 lb[INDEX_ID_WO] = &bmain.worlds;
1023 lb[INDEX_ID_MC] = &bmain.movieclips;
1024 lb[INDEX_ID_SCR] = &bmain.screens;
1025 lb[INDEX_ID_OB] = &bmain.objects;
1026 /* referenced by scenes */
1027 lb[INDEX_ID_LS] = &bmain.linestyles;
1028 lb[INDEX_ID_SCE] = &bmain.scenes;
1029 /* before wm, so it's freed after it! */
1030 lb[INDEX_ID_WS] = &bmain.workspaces;
1031 lb[INDEX_ID_WM] = &bmain.wm;
1032 lb[INDEX_ID_MSK] = &bmain.masks;
1033
1034 return lb;
1035}
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports, BPathSummary *r_summary=nullptr)
Definition bpath.cc:626
void BKE_bpath_relative_rebase(Main *bmain, const char *basedir_src, const char *basedir_dst, ReportList *reports, BPathSummary *r_summary=nullptr)
Definition bpath.cc:477
#define G_MAIN
bool BKE_idtype_idcode_is_linkable(short idcode)
Definition idtype.cc:198
bool BKE_idtype_idcode_append_is_reusable(short idcode)
Definition idtype.cc:217
void BKE_libblock_management_main_remove(Main *bmain, void *idv)
Definition lib_id.cc:1146
#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:1113
LibraryForeachIDCallbackFlag
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag)
Definition lib_query.cc:431
@ IDWALK_RET_NOP
LibraryForeachIDFlag
@ IDWALK_INCLUDE_UI
@ IDWALK_NOP
@ IDWALK_READONLY
void BKE_libblock_relink_multiple(Main *bmain, const blender::Span< ID * > ids, eIDRemapType remap_type, blender::bke::id::IDRemapper &id_remapper, int remap_flags)
Definition lib_remap.cc:780
@ ID_REMAP_TYPE_REMAP
@ ID_REMAP_DO_LIBRARY_POINTERS
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:563
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:532
std::array< ListBase *, INDEX_ID_MAX - 1 > MainListsArray
Definition BKE_main.hh:621
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:526
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:544
@ MAINIDRELATIONS_INCLUDE_UI
Definition BKE_main.hh:138
#define BLEN_THUMB_SIZE
Definition BKE_main.hh:657
eMainIDRelationsEntryTags
Definition BKE_main.hh:84
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:537
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:557
#define BLEN_THUMB_MEMSIZE(_x, _y)
Definition BKE_main.hh:659
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)
bool BKE_main_namemap_validate(Main &bmain)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
struct GSet GSet
Definition BLI_ghash.h:337
void BLI_ghashIterator_step(GHashIterator *ghi)
Definition BLI_ghash.cc:911
unsigned int BLI_ghashutil_ptrhash(const void *key)
void BLI_ghashIterator_free(GHashIterator *ghi)
Definition BLI_ghash.cc:925
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:299
GHash * BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:686
GHashIterator * BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:888
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:944
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:752
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.cc:966
BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.h:307
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(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
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) 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
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
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.
eID_Index
Definition DNA_ID.h:1187
@ INDEX_ID_TXT
Definition DNA_ID.h:1210
@ INDEX_ID_WM
Definition DNA_ID.h:1263
@ INDEX_ID_VO
Definition DNA_ID.h:1239
@ INDEX_ID_NULL
Definition DNA_ID.h:1266
@ INDEX_ID_CF
Definition DNA_ID.h:1226
@ INDEX_ID_CV
Definition DNA_ID.h:1237
@ INDEX_ID_PT
Definition DNA_ID.h:1238
@ INDEX_ID_GR
Definition DNA_ID.h:1249
@ INDEX_ID_LA
Definition DNA_ID.h:1241
@ INDEX_ID_LT
Definition DNA_ID.h:1240
@ INDEX_ID_PC
Definition DNA_ID.h:1254
@ INDEX_ID_MA
Definition DNA_ID.h:1221
@ INDEX_ID_IM
Definition DNA_ID.h:1216
@ INDEX_ID_OB
Definition DNA_ID.h:1248
@ INDEX_ID_ME
Definition DNA_ID.h:1234
@ INDEX_ID_SO
Definition DNA_ID.h:1211
@ INDEX_ID_VF
Definition DNA_ID.h:1209
@ INDEX_ID_MC
Definition DNA_ID.h:1217
@ INDEX_ID_MSK
Definition DNA_ID.h:1215
@ INDEX_ID_BR
Definition DNA_ID.h:1255
@ INDEX_ID_WS
Definition DNA_ID.h:1262
@ INDEX_ID_SCR
Definition DNA_ID.h:1261
@ INDEX_ID_SPK
Definition DNA_ID.h:1243
@ INDEX_ID_MB
Definition DNA_ID.h:1236
@ INDEX_ID_CU_LEGACY
Definition DNA_ID.h:1235
@ INDEX_ID_LI
Definition DNA_ID.h:1189
@ INDEX_ID_IP
Definition DNA_ID.h:1192
@ INDEX_ID_NT
Definition DNA_ID.h:1205
@ INDEX_ID_WO
Definition DNA_ID.h:1223
@ INDEX_ID_TE
Definition DNA_ID.h:1220
@ INDEX_ID_PAL
Definition DNA_ID.h:1253
@ INDEX_ID_GP
Definition DNA_ID.h:1245
@ INDEX_ID_LS
Definition DNA_ID.h:1222
@ INDEX_ID_SCE
Definition DNA_ID.h:1258
@ INDEX_ID_GD_LEGACY
Definition DNA_ID.h:1199
@ INDEX_ID_LP
Definition DNA_ID.h:1244
@ INDEX_ID_AC
Definition DNA_ID.h:1193
@ INDEX_ID_CA
Definition DNA_ID.h:1242
@ INDEX_ID_AR
Definition DNA_ID.h:1233
@ INDEX_ID_PA
Definition DNA_ID.h:1227
@ INDEX_ID_KE
Definition DNA_ID.h:1230
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
ImBuf * IMB_allocFromBuffer(const uint8_t *byte_buffer, const float *float_buffer, unsigned int w, unsigned int h, unsigned int channels)
void IMB_byte_from_float(ImBuf *ibuf)
Read Guarded memory(de)allocation.
ReportList * reports
Definition WM_types.hh:1025
BMesh const char void * data
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool add_overwrite(const Key &key, const Value &value)
Definition BLI_map.hh:325
const Value & lookup(const Key &key) const
Definition BLI_map.hh:545
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:570
void add_new(const Key &key, const Value &value)
Definition BLI_map.hh:265
bool remove(const Key &key)
Definition BLI_map.hh:368
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:570
bool contains(const Key &key) const
Definition BLI_map.hh:353
Value & lookup_or_add(const Key &key, const Value &value)
Definition BLI_map.hh:588
int64_t size() const
void append(const T &value)
bool is_empty() const
void add(ID *old_id, ID *new_id)
#define MEM_SAFE_FREE(v)
#define ID_IS_LINKED(_id)
#define MAX_ID_NAME
#define GS(a)
#define LOG(severity)
Definition log.h:32
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:693
MainListsArray BKE_main_lists_get(Main &bmain)
Definition main.cc:969
BlendThumbnail * BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
Definition main.cc:822
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:882
void BKE_main_clear(Main &bmain)
Definition main.cc:68
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:740
void BKE_main_library_weak_reference_add(ID *local_id, const char *library_filepath, const char *library_id_name)
Definition main.cc:788
void BKE_main_destroy(Main &bmain)
Definition main.cc:165
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:48
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:593
void BKE_main_thumbnail_create(Main *bmain)
Definition main.cc:862
ImBuf * BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
Definition main.cc:846
void BKE_main_init(Main &bmain)
Definition main.cc:55
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:657
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:702
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:687
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:718
BlendThumbnail * BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
Definition main.cc:800
const char * BKE_main_blendfile_path(const Main *bmain)
Definition main.cc:872
ID * BKE_main_library_weak_reference_find(Main *bmain, const char *library_filepath, const char *library_id_name)
Definition main.cc:757
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:616
void BKE_main_relations_free(Main *bmain)
Definition main.cc:581
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:877
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
Definition DNA_ID.h:404
struct Library * lib
Definition DNA_ID.h:410
char name[66]
Definition DNA_ID.h:415
unsigned int session_uid
Definition DNA_ID.h:444
struct LibraryWeakReference * library_weak_reference
Definition DNA_ID.h:491
ImBufByteBuffer byte_buffer
friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
Definition main.cc:641
char filepath[FILE_MAX]
Definition main.cc:632
uint64_t hash() const
Definition main.cc:646
LibWeakRefKey(const char *lib_path, const char *id_name)
Definition main.cc:635
char id_name[MAX_ID_NAME]
Definition main.cc:633
LibraryForeachIDCallbackFlag cb_flag
char library_filepath[1024]
Definition DNA_ID.h:531
char library_id_name[66]
Definition DNA_ID.h:534
LibraryRuntimeHandle * runtime
Definition DNA_ID.h:516
void * first
MainIDRelationsEntryItem * next
Definition BKE_main.hh:55
union MainIDRelationsEntryItem::@263053341106070124206137216357307200115112076047 id_pointer
LibraryForeachIDCallbackFlag usage_flag
Definition BKE_main.hh:67
GHash * relations_from_pointers
Definition BKE_main.hh:127
BLI_mempool * entry_items_pool
Definition BKE_main.hh:133
blender::Map< LibWeakRefKey, ID * > map
Definition main.cc:654
ListBase volumes
Definition BKE_main.hh:291
ListBase lightprobes
Definition BKE_main.hh:265
ListBase brushes
Definition BKE_main.hh:271
ListBase masks
Definition BKE_main.hh:281
ListBase scenes
Definition BKE_main.hh:245
ListBase grease_pencils
Definition BKE_main.hh:279
UniqueName_Map * name_map_global
Definition BKE_main.hh:310
ListBase wm
Definition BKE_main.hh:276
bool is_asset_edit_file
Definition BKE_main.hh:171
bool has_forward_compatibility_issues
Definition BKE_main.hh:164
ListBase textures
Definition BKE_main.hh:252
ListBase actions
Definition BKE_main.hh:269
UniqueName_Map * name_map
Definition BKE_main.hh:304
ListBase texts
Definition BKE_main.hh:263
ListBase meshes
Definition BKE_main.hh:248
char filepath[1024]
Definition BKE_main.hh:155
ListBase movieclips
Definition BKE_main.hh:280
ListBase ipo
Definition BKE_main.hh:258
ListBase hair_curves
Definition BKE_main.hh:289
ListBase lights
Definition BKE_main.hh:255
ListBase paintcurves
Definition BKE_main.hh:274
ListBase fonts
Definition BKE_main.hh:262
ListBase nodetrees
Definition BKE_main.hh:270
BlendThumbnail * blen_thumb
Definition BKE_main.hh:231
ListBase particles
Definition BKE_main.hh:272
ListBase materials
Definition BKE_main.hh:251
bool is_action_slot_to_id_map_dirty
Definition BKE_main.hh:225
ListBase linestyles
Definition BKE_main.hh:282
ListBase pointclouds
Definition BKE_main.hh:290
ListBase lattices
Definition BKE_main.hh:254
ListBase sounds
Definition BKE_main.hh:266
ListBase shapekeys
Definition BKE_main.hh:259
ListBase libraries
Definition BKE_main.hh:246
ListBase cameras
Definition BKE_main.hh:256
IDNameLib_Map * id_map
Definition BKE_main.hh:301
ListBase armatures
Definition BKE_main.hh:268
ListBase speakers
Definition BKE_main.hh:264
MainLock * lock
Definition BKE_main.hh:312
ListBase curves
Definition BKE_main.hh:249
Main * next
Definition BKE_main.hh:142
ListBase worlds
Definition BKE_main.hh:260
ListBase screens
Definition BKE_main.hh:261
ListBase workspaces
Definition BKE_main.hh:284
ListBase palettes
Definition BKE_main.hh:273
ListBase metaballs
Definition BKE_main.hh:250
bool is_global_main
Definition BKE_main.hh:211
ListBase collections
Definition BKE_main.hh:267
ListBase images
Definition BKE_main.hh:253
ListBase gpencils
Definition BKE_main.hh:278
MainIDRelations * relations
Definition BKE_main.hh:298
ListBase objects
Definition BKE_main.hh:247
ListBase cachefiles
Definition BKE_main.hh:283
uint8_t flag
Definition wm_window.cc:139