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 for (ID *id_iter_src : ids_to_move) {
416 BKE_libblock_management_main_remove(bmain_src, id_iter_src);
417 /* Libraries need to be remapped:
418 * - _After_ removing IDs from the old source Main, to ensure that they get properly removed
419 * from the expected namemap.
420 * - _Before_ moving them into `bmain_dst`, to ensure that the sorting of inserted IDs is
421 * correct. */
422 if (ID_IS_LINKED(id_iter_src)) {
423 /* Note that no bmain is given here, so this is only a 'raw' remapping. */
425 blender::Span(&id_iter_src, 1),
427 id_remapper_libraries,
429 BLI_assert(id_iter_src->lib);
430 }
431 BKE_libblock_management_main_add(bmain_dst, id_iter_src);
432 }
433
434 /* The other data has to be remapped once all IDs are in `bmain_dst`, to ensure that additional
435 * update process (e.g. collection hierarchy handling) happens as expected with the correct set
436 * of data. */
437 BKE_libblock_relink_multiple(bmain_dst, ids_to_move, ID_REMAP_TYPE_REMAP, id_remapper, 0);
438
440 reports.reports,
441 RPT_INFO,
442 "Merged %d IDs from '%s' Main into '%s' Main; %d IDs and %d Libraries already existed as "
443 "part of the destination Main, and %d IDs missing from destination Main, were freed "
444 "together with the source Main",
445 reports.num_merged_ids,
446 bmain_src->filepath,
447 bmain_dst->filepath,
448 reports.num_remapped_ids,
449 reports.num_remapped_libraries,
450 reports.num_unknown_ids);
451
452 /* Remapping above may have made some IDs local. So namemap needs to be cleared, and moved IDs
453 * need to be re-sorted. */
454 BKE_main_namemap_clear(*bmain_dst);
455
457
458 BKE_main_free(bmain_src);
459 *r_bmain_src = nullptr;
460}
461
463{
464 bool result = true;
465 ID *id_iter;
466 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
467 result = false;
468 break;
469 }
471 return result;
472}
473
474bool BKE_main_has_issues(const Main *bmain)
475{
477}
478
480{
482}
483
484void BKE_main_lock(Main *bmain)
485{
486 BLI_spin_lock((SpinLock *)bmain->lock);
487}
488
490{
491 BLI_spin_unlock((SpinLock *)bmain->lock);
492}
493
495{
496 MainIDRelations *bmain_relations = static_cast<MainIDRelations *>(cb_data->user_data);
497 ID *self_id = cb_data->self_id;
498 ID **id_pointer = cb_data->id_pointer;
499 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
500
501 if (*id_pointer) {
502 MainIDRelationsEntry **entry_p;
503
504 /* Add `id_pointer` as child of `self_id`. */
505 {
507 bmain_relations->relations_from_pointers, self_id, (void ***)&entry_p))
508 {
509 *entry_p = MEM_callocN<MainIDRelationsEntry>(__func__);
510 (*entry_p)->session_uid = self_id->session_uid;
511 }
512 else {
513 BLI_assert((*entry_p)->session_uid == self_id->session_uid);
514 }
515 MainIDRelationsEntryItem *to_id_entry = static_cast<MainIDRelationsEntryItem *>(
516 BLI_mempool_alloc(bmain_relations->entry_items_pool));
517 to_id_entry->next = (*entry_p)->to_ids;
518 to_id_entry->id_pointer.to = id_pointer;
519 to_id_entry->session_uid = (*id_pointer != nullptr) ? (*id_pointer)->session_uid :
521 to_id_entry->usage_flag = cb_flag;
522 (*entry_p)->to_ids = to_id_entry;
523 }
524
525 /* Add `self_id` as parent of `id_pointer`. */
526 if (*id_pointer != nullptr) {
528 bmain_relations->relations_from_pointers, *id_pointer, (void ***)&entry_p))
529 {
530 *entry_p = MEM_callocN<MainIDRelationsEntry>(__func__);
531 (*entry_p)->session_uid = (*id_pointer)->session_uid;
532 }
533 else {
534 BLI_assert((*entry_p)->session_uid == (*id_pointer)->session_uid);
535 }
536 MainIDRelationsEntryItem *from_id_entry = static_cast<MainIDRelationsEntryItem *>(
537 BLI_mempool_alloc(bmain_relations->entry_items_pool));
538 from_id_entry->next = (*entry_p)->from_ids;
539 from_id_entry->id_pointer.from = self_id;
540 from_id_entry->session_uid = self_id->session_uid;
541 from_id_entry->usage_flag = cb_flag;
542 (*entry_p)->from_ids = from_id_entry;
543 }
544 }
545
546 return IDWALK_RET_NOP;
547}
548
549void BKE_main_relations_create(Main *bmain, const short flag)
550{
551 if (bmain->relations != nullptr) {
553 }
554
555 bmain->relations = MEM_mallocN<MainIDRelations>(__func__);
559 sizeof(MainIDRelationsEntryItem), 128, 128, BLI_MEMPOOL_NOP);
560
561 bmain->relations->flag = flag;
562
563 ID *id;
564 FOREACH_MAIN_ID_BEGIN (bmain, id) {
565 const LibraryForeachIDFlag idwalk_flag = IDWALK_READONLY |
568 IDWALK_NOP);
569
570 /* Ensure all IDs do have an entry, even if they are not connected to any other. */
571 MainIDRelationsEntry **entry_p;
572 if (!BLI_ghash_ensure_p(bmain->relations->relations_from_pointers, id, (void ***)&entry_p)) {
573 *entry_p = MEM_callocN<MainIDRelationsEntry>(__func__);
574 (*entry_p)->session_uid = id->session_uid;
575 }
576 else {
577 BLI_assert((*entry_p)->session_uid == id->session_uid);
578 }
579
581 nullptr, id, main_relations_create_idlink_cb, bmain->relations, idwalk_flag);
582 }
584}
585
587{
588 if (bmain->relations != nullptr) {
589 if (bmain->relations->relations_from_pointers != nullptr) {
591 }
593 MEM_freeN(bmain->relations);
594 bmain->relations = nullptr;
595 }
596}
597
598void BKE_main_relations_tag_set(Main *bmain, const eMainIDRelationsEntryTags tag, const bool value)
599{
600 if (bmain->relations == nullptr) {
601 return;
602 }
603
604 GHashIterator *gh_iter;
606 !BLI_ghashIterator_done(gh_iter);
607 BLI_ghashIterator_step(gh_iter))
608 {
609 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
611 if (value) {
612 entry->tags |= tag;
613 }
614 else {
615 entry->tags &= ~tag;
616 }
617 }
618 BLI_ghashIterator_free(gh_iter);
619}
620
622{
623 if (gset == nullptr) {
625 }
626
627 ID *id;
628 FOREACH_MAIN_ID_BEGIN (bmain, id) {
629 BLI_gset_add(gset, id);
630 }
632 return gset;
633}
634
635/* Utils for ID's library weak reference API. */
639
640 LibWeakRefKey(const char *lib_path, const char *id_name)
641 {
642 STRNCPY(this->filepath, lib_path);
643 STRNCPY(this->id_name, id_name);
644 }
645
646 friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
647 {
648 return STREQ(a.filepath, b.filepath) && STREQ(a.id_name, b.id_name);
649 }
650
652 {
653 return blender::get_default_hash(blender::StringRef(this->filepath),
654 blender::StringRef(this->id_name));
655 }
656};
657
661
663{
664 auto *library_weak_reference_mapping = MEM_new<MainLibraryWeakReferenceMap>(__func__);
665
666 ListBase *lb;
667 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
668 ID *id_iter = static_cast<ID *>(lb->first);
669 if (id_iter == nullptr) {
670 continue;
671 }
673 continue;
674 }
676
677 FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) {
678 if (id_iter->library_weak_reference == nullptr) {
679 continue;
680 }
683 library_weak_reference_mapping->map.add(key, id_iter);
684 }
686 }
688
689 return library_weak_reference_mapping;
690}
691
693 MainLibraryWeakReferenceMap *library_weak_reference_mapping)
694{
695 MEM_delete(library_weak_reference_mapping);
696}
697
699 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
700 const char *library_filepath,
701 const char *library_id_name)
702{
703 const LibWeakRefKey key{library_filepath, library_id_name};
704 return library_weak_reference_mapping->map.lookup_default(key, nullptr);
705}
706
708 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
709 const char *library_filepath,
710 const char *library_id_name,
711 ID *new_id)
712{
713 BLI_assert(GS(library_id_name) == GS(new_id->name));
714 BLI_assert(new_id->library_weak_reference == nullptr);
716
717 const LibWeakRefKey key{library_filepath, library_id_name};
718 library_weak_reference_mapping->map.add_new(key, new_id);
719
720 BKE_main_library_weak_reference_add(new_id, library_filepath, library_id_name);
721}
722
724 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
725 const char *library_filepath,
726 const char *library_id_name,
727 ID *old_id,
728 ID *new_id)
729{
730 BLI_assert(GS(library_id_name) == GS(old_id->name));
731 BLI_assert(GS(library_id_name) == GS(new_id->name));
732 BLI_assert(old_id->library_weak_reference != nullptr);
733 BLI_assert(new_id->library_weak_reference == nullptr);
734 BLI_assert(STREQ(old_id->library_weak_reference->library_filepath, library_filepath));
735 BLI_assert(STREQ(old_id->library_weak_reference->library_id_name, library_id_name));
736
737 const LibWeakRefKey key{library_filepath, library_id_name};
738 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
739 library_weak_reference_mapping->map.add_overwrite(key, new_id);
740
742 old_id->library_weak_reference = nullptr;
743}
744
746 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
747 const char *library_filepath,
748 const char *library_id_name,
749 ID *old_id)
750{
751 BLI_assert(GS(library_id_name) == GS(old_id->name));
752 BLI_assert(old_id->library_weak_reference != nullptr);
753
754 const LibWeakRefKey key{library_filepath, library_id_name};
755
756 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
757 library_weak_reference_mapping->map.remove(key);
758
760}
761
763 const char *library_filepath,
764 const char *library_id_name)
765{
766 /* Make filepath absolute so we can compare filepaths that may be either relative or absolute. */
767 char library_filepath_abs[FILE_MAX];
768 STRNCPY(library_filepath_abs, library_filepath);
769 BLI_path_abs(library_filepath_abs, BKE_main_blendfile_path(bmain));
770
771 ListBase *id_list = which_libbase(bmain, GS(library_id_name));
772 LISTBASE_FOREACH (ID *, existing_id, id_list) {
773 if (!(existing_id->library_weak_reference &&
774 STREQ(existing_id->library_weak_reference->library_id_name, library_id_name)))
775 {
776 continue;
777 }
778
779 char existing_filepath_abs[FILE_MAX];
780 STRNCPY(existing_filepath_abs, existing_id->library_weak_reference->library_filepath);
781 BLI_path_abs(existing_filepath_abs, BKE_main_blendfile_path(bmain));
782
783 if (!STREQ(existing_filepath_abs, library_filepath_abs)) {
784 continue;
785 }
786
787 return existing_id;
788 }
789
790 return nullptr;
791}
792
794 const char *library_filepath,
795 const char *library_id_name)
796{
797 if (local_id->library_weak_reference == nullptr) {
799 }
800
801 STRNCPY(local_id->library_weak_reference->library_filepath, library_filepath);
802 STRNCPY(local_id->library_weak_reference->library_id_name, library_id_name);
803}
804
805BlendThumbnail *BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
806{
807 BlendThumbnail *data = nullptr;
808
809 if (bmain) {
811 }
812
813 if (rect) {
814 const size_t data_size = BLEN_THUMB_MEMSIZE(size[0], size[1]);
815 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
816 data->width = size[0];
817 data->height = size[1];
818 memcpy(data->rect, rect, data_size - sizeof(*data));
819 }
820
821 if (bmain) {
822 bmain->blen_thumb = data;
823 }
824 return data;
825}
826
828{
829 BlendThumbnail *data = nullptr;
830
831 if (bmain) {
833 }
834
835 if (img) {
836 const size_t data_size = BLEN_THUMB_MEMSIZE(img->x, img->y);
837 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
838
839 IMB_byte_from_float(img); /* Just in case... */
840 data->width = img->x;
841 data->height = img->y;
842 memcpy(data->rect, img->byte_buffer.data, data_size - sizeof(*data));
843 }
844
845 if (bmain) {
846 bmain->blen_thumb = data;
847 }
848 return data;
849}
850
852{
853 ImBuf *img = nullptr;
854
855 if (!data && bmain) {
856 data = bmain->blen_thumb;
857 }
858
859 if (data) {
861 (const uint8_t *)data->rect, nullptr, uint(data->width), uint(data->height), 4);
862 }
863
864 return img;
865}
866
868{
870
871 bmain->blen_thumb = static_cast<BlendThumbnail *>(
875}
876
877const char *BKE_main_blendfile_path(const Main *bmain)
878{
879 return bmain->filepath;
880}
881
886
887ListBase *which_libbase(Main *bmain, short type)
888{
889 switch ((ID_Type)type) {
890 case ID_SCE:
891 return &(bmain->scenes);
892 case ID_LI:
893 return &(bmain->libraries);
894 case ID_OB:
895 return &(bmain->objects);
896 case ID_ME:
897 return &(bmain->meshes);
898 case ID_CU_LEGACY:
899 return &(bmain->curves);
900 case ID_MB:
901 return &(bmain->metaballs);
902 case ID_MA:
903 return &(bmain->materials);
904 case ID_TE:
905 return &(bmain->textures);
906 case ID_IM:
907 return &(bmain->images);
908 case ID_LT:
909 return &(bmain->lattices);
910 case ID_LA:
911 return &(bmain->lights);
912 case ID_CA:
913 return &(bmain->cameras);
914 case ID_IP:
915 return &(bmain->ipo);
916 case ID_KE:
917 return &(bmain->shapekeys);
918 case ID_WO:
919 return &(bmain->worlds);
920 case ID_SCR:
921 return &(bmain->screens);
922 case ID_VF:
923 return &(bmain->fonts);
924 case ID_TXT:
925 return &(bmain->texts);
926 case ID_SPK:
927 return &(bmain->speakers);
928 case ID_LP:
929 return &(bmain->lightprobes);
930 case ID_SO:
931 return &(bmain->sounds);
932 case ID_GR:
933 return &(bmain->collections);
934 case ID_AR:
935 return &(bmain->armatures);
936 case ID_AC:
937 return &(bmain->actions);
938 case ID_NT:
939 return &(bmain->nodetrees);
940 case ID_BR:
941 return &(bmain->brushes);
942 case ID_PA:
943 return &(bmain->particles);
944 case ID_WM:
945 return &(bmain->wm);
946 case ID_GD_LEGACY:
947 return &(bmain->gpencils);
948 case ID_GP:
949 return &(bmain->grease_pencils);
950 case ID_MC:
951 return &(bmain->movieclips);
952 case ID_MSK:
953 return &(bmain->masks);
954 case ID_LS:
955 return &(bmain->linestyles);
956 case ID_PAL:
957 return &(bmain->palettes);
958 case ID_PC:
959 return &(bmain->paintcurves);
960 case ID_CF:
961 return &(bmain->cachefiles);
962 case ID_WS:
963 return &(bmain->workspaces);
964 case ID_CV:
965 return &(bmain->hair_curves);
966 case ID_PT:
967 return &(bmain->pointclouds);
968 case ID_VO:
969 return &(bmain->volumes);
970 }
971 return nullptr;
972}
973
975{
976 MainListsArray lb{};
977 /* Libraries may be accessed from pretty much any other ID. */
978 lb[INDEX_ID_LI] = &bmain.libraries;
979
980 lb[INDEX_ID_IP] = &bmain.ipo;
981
982 /* Moved here to avoid problems when freeing with animato (aligorith). */
983 lb[INDEX_ID_AC] = &bmain.actions;
984
985 lb[INDEX_ID_KE] = &bmain.shapekeys;
986
987 /* Referenced by gpencil, so needs to be before that to avoid crashes. */
988 lb[INDEX_ID_PAL] = &bmain.palettes;
989
990 /* Referenced by nodes, objects, view, scene etc, before to free after. */
991 lb[INDEX_ID_GD_LEGACY] = &bmain.gpencils;
992 lb[INDEX_ID_GP] = &bmain.grease_pencils;
993
994 lb[INDEX_ID_NT] = &bmain.nodetrees;
995 lb[INDEX_ID_IM] = &bmain.images;
996 lb[INDEX_ID_TE] = &bmain.textures;
997 lb[INDEX_ID_MA] = &bmain.materials;
998 lb[INDEX_ID_VF] = &bmain.fonts;
999
1000 /* Important!: When adding a new object type,
1001 * the specific data should be inserted here. */
1002
1003 lb[INDEX_ID_AR] = &bmain.armatures;
1004
1005 lb[INDEX_ID_CF] = &bmain.cachefiles;
1006 lb[INDEX_ID_ME] = &bmain.meshes;
1007 lb[INDEX_ID_CU_LEGACY] = &bmain.curves;
1008 lb[INDEX_ID_MB] = &bmain.metaballs;
1009 lb[INDEX_ID_CV] = &bmain.hair_curves;
1010 lb[INDEX_ID_PT] = &bmain.pointclouds;
1011 lb[INDEX_ID_VO] = &bmain.volumes;
1012
1013 lb[INDEX_ID_LT] = &bmain.lattices;
1014 lb[INDEX_ID_LA] = &bmain.lights;
1015 lb[INDEX_ID_CA] = &bmain.cameras;
1016
1017 lb[INDEX_ID_TXT] = &bmain.texts;
1018 lb[INDEX_ID_SO] = &bmain.sounds;
1019 lb[INDEX_ID_GR] = &bmain.collections;
1020 lb[INDEX_ID_PAL] = &bmain.palettes;
1021 lb[INDEX_ID_PC] = &bmain.paintcurves;
1022 lb[INDEX_ID_BR] = &bmain.brushes;
1023 lb[INDEX_ID_PA] = &bmain.particles;
1024 lb[INDEX_ID_SPK] = &bmain.speakers;
1025 lb[INDEX_ID_LP] = &bmain.lightprobes;
1026
1027 lb[INDEX_ID_WO] = &bmain.worlds;
1028 lb[INDEX_ID_MC] = &bmain.movieclips;
1029 lb[INDEX_ID_SCR] = &bmain.screens;
1030 lb[INDEX_ID_OB] = &bmain.objects;
1031 /* referenced by scenes */
1032 lb[INDEX_ID_LS] = &bmain.linestyles;
1033 lb[INDEX_ID_SCE] = &bmain.scenes;
1034 /* before wm, so it's freed after it! */
1035 lb[INDEX_ID_WS] = &bmain.workspaces;
1036 lb[INDEX_ID_WM] = &bmain.wm;
1037 lb[INDEX_ID_MSK] = &bmain.masks;
1038
1039 return lb;
1040}
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
@ 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_libblock_management_main_remove(Main *bmain, void *idv)
Definition lib_id.cc:1146
#define MAIN_ID_SESSION_UID_UNSET
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
#define BLEN_THUMB_SIZE
Definition BKE_main.hh:657
eMainIDRelationsEntryTags
Definition BKE_main.hh:84
@ MAINIDRELATIONS_INCLUDE_UI
Definition BKE_main.hh:138
#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
void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1)
@ BLI_MEMPOOL_NOP
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:698
MainListsArray BKE_main_lists_get(Main &bmain)
Definition main.cc:974
BlendThumbnail * BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
Definition main.cc:827
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:887
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:745
void BKE_main_library_weak_reference_add(ID *local_id, const char *library_filepath, const char *library_id_name)
Definition main.cc:793
void BKE_main_destroy(Main &bmain)
Definition main.cc:165
bool BKE_main_needs_overwrite_confirm(const Main *bmain)
Definition main.cc:479
bool BKE_main_has_issues(const Main *bmain)
Definition main.cc:474
Main * BKE_main_new()
Definition main.cc:48
void BKE_main_lock(Main *bmain)
Definition main.cc:484
void BKE_main_relations_tag_set(Main *bmain, const eMainIDRelationsEntryTags tag, const bool value)
Definition main.cc:598
void BKE_main_thumbnail_create(Main *bmain)
Definition main.cc:867
ImBuf * BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
Definition main.cc:851
void BKE_main_init(Main &bmain)
Definition main.cc:55
void BKE_main_relations_create(Main *bmain, const short flag)
Definition main.cc:549
MainLibraryWeakReferenceMap * BKE_main_library_weak_reference_create(Main *bmain)
Definition main.cc:662
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:707
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:692
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:723
BlendThumbnail * BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
Definition main.cc:805
const char * BKE_main_blendfile_path(const Main *bmain)
Definition main.cc:877
ID * BKE_main_library_weak_reference_find(Main *bmain, const char *library_filepath, const char *library_id_name)
Definition main.cc:762
void BKE_main_unlock(Main *bmain)
Definition main.cc:489
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:462
static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
Definition main.cc:494
GSet * BKE_main_gset_create(Main *bmain, GSet *gset)
Definition main.cc:621
void BKE_main_relations_free(Main *bmain)
Definition main.cc:586
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:882
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:646
char filepath[FILE_MAX]
Definition main.cc:637
uint64_t hash() const
Definition main.cc:651
LibWeakRefKey(const char *lib_path, const char *id_name)
Definition main.cc:640
char id_name[MAX_ID_NAME]
Definition main.cc:638
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
LibraryForeachIDCallbackFlag usage_flag
Definition BKE_main.hh:67
union MainIDRelationsEntryItem::@151151347062204160353171246021363355316307354166 id_pointer
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:659
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