Blender V5.0
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
42#include "IMB_imbuf.hh"
43#include "IMB_imbuf_types.hh"
44
45using namespace blender::bke;
46
47static CLG_LogRef LOG = {"lib.main"};
48
50{
51 SpinLock *main_lock = MEM_mallocN<SpinLock>("main lock");
52 BLI_spin_init(main_lock);
53 /* Use C-style cast to workaround an issue casting away volatile for builds without TBB. */
54 this->lock = (MainLock *)main_lock;
55
56 /* Just rebuilding the Action Slot to ID* map once is likely cheaper than,
57 * for every ID, when it's loaded from disk, check whether it's animated or
58 * not, and then figure out which Main it went into, and then set the flag. */
60}
61
63{
64 /* In case this is called on a 'split-by-libraries' list of mains.
65 *
66 * Should not happen in typical usages, but can occur e.g. if a file reading is aborted. */
67 if (this->split_mains) {
68 for (Main *main_it : *this->split_mains) {
69 if (main_it == this) {
70 continue;
71 }
72 main_it->split_mains.reset();
73 MEM_delete(main_it);
74 }
75 }
76
77 /* Include this check here as the path may be manipulated after creation. */
78 BLI_assert_msg(!(this->filepath[0] == '/' && this->filepath[1] == '/'),
79 "'.blend' relative \"//\" must not be used in Main!");
80
81 BKE_main_clear(*this);
82
83 BLI_spin_end(reinterpret_cast<SpinLock *>(this->lock));
84 /* The void cast is needed when building without TBB. */
85 MEM_freeN((void *)reinterpret_cast<SpinLock *>(this->lock));
86 this->lock = nullptr;
87}
88
90{
91 Main *bmain = MEM_new<Main>(__func__);
93 return bmain;
94}
95
96void BKE_main_clear(Main &bmain)
97{
98 /* Also call when reading a file, erase all, etc */
99
100 /* Since we are removing whole main, no need to bother 'properly' (and slowly) removing each ID
101 * from it. */
102 const int free_flag = (LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_UI_USER |
104
106
107 MainListsArray lbarray = BKE_main_lists_get(bmain);
108 int a = lbarray.size();
109 while (a--) {
110 ListBase *lb = lbarray[a];
111 ID *id, *id_next;
112
113 for (id = static_cast<ID *>(lb->first); id != nullptr; id = id_next) {
114 id_next = static_cast<ID *>(id->next);
115#if 1
116 BKE_id_free_ex(&bmain, id, free_flag, false);
117#else
118 /* Errors freeing ID's can be hard to track down,
119 * enable this so VALGRIND or ASAN will give the line number in its error log. */
120
121# define CASE_ID_INDEX(id_index) \
122 case id_index: \
123 BKE_id_free_ex(&bmain, id, free_flag, false); \
124 break
125
126 switch ((eID_Index)a) {
127 CASE_ID_INDEX(INDEX_ID_LI);
128 CASE_ID_INDEX(INDEX_ID_AC);
129 CASE_ID_INDEX(INDEX_ID_GD_LEGACY);
130 CASE_ID_INDEX(INDEX_ID_NT);
131 CASE_ID_INDEX(INDEX_ID_VF);
132 CASE_ID_INDEX(INDEX_ID_TXT);
133 CASE_ID_INDEX(INDEX_ID_SO);
134 CASE_ID_INDEX(INDEX_ID_MSK);
135 CASE_ID_INDEX(INDEX_ID_IM);
136 CASE_ID_INDEX(INDEX_ID_MC);
137 CASE_ID_INDEX(INDEX_ID_TE);
138 CASE_ID_INDEX(INDEX_ID_MA);
139 CASE_ID_INDEX(INDEX_ID_LS);
140 CASE_ID_INDEX(INDEX_ID_WO);
141 CASE_ID_INDEX(INDEX_ID_CF);
142 CASE_ID_INDEX(INDEX_ID_SIM);
143 CASE_ID_INDEX(INDEX_ID_PA);
144 CASE_ID_INDEX(INDEX_ID_KE);
145 CASE_ID_INDEX(INDEX_ID_AR);
146 CASE_ID_INDEX(INDEX_ID_ME);
147 CASE_ID_INDEX(INDEX_ID_CU_LEGACY);
148 CASE_ID_INDEX(INDEX_ID_MB);
149 CASE_ID_INDEX(INDEX_ID_CV);
150 CASE_ID_INDEX(INDEX_ID_PT);
151 CASE_ID_INDEX(INDEX_ID_VO);
152 CASE_ID_INDEX(INDEX_ID_LT);
153 CASE_ID_INDEX(INDEX_ID_LA);
154 CASE_ID_INDEX(INDEX_ID_CA);
155 CASE_ID_INDEX(INDEX_ID_SPK);
156 CASE_ID_INDEX(INDEX_ID_LP);
157 CASE_ID_INDEX(INDEX_ID_OB);
158 CASE_ID_INDEX(INDEX_ID_GR);
159 CASE_ID_INDEX(INDEX_ID_PAL);
160 CASE_ID_INDEX(INDEX_ID_PC);
161 CASE_ID_INDEX(INDEX_ID_BR);
162 CASE_ID_INDEX(INDEX_ID_SCE);
163 CASE_ID_INDEX(INDEX_ID_SCR);
164 CASE_ID_INDEX(INDEX_ID_WS);
165 CASE_ID_INDEX(INDEX_ID_WM);
166 case INDEX_ID_NULL: {
168 break;
169 }
170 }
171
172# undef CASE_ID_INDEX
173
174#endif
175 }
177 }
178
179 if (bmain.relations) {
181 }
182
183 if (bmain.id_map) {
185 }
186
187 /* NOTE: `name_map` in libraries are freed together with the library IDs above. */
190}
191
192void BKE_main_free(Main *bmain)
193{
194 MEM_delete(bmain);
195}
196
197static bool are_ids_from_different_mains_matching(Main *bmain_1, ID *id_1, Main *bmain_2, ID *id_2)
198{
199 /* Both IDs should not be null at the same time.
200 *
201 * NOTE: E.g. `id_1` may be null, in case `id_2` is a Library ID which path is the filepath of
202 * `bmain_1`. */
203 BLI_assert(id_1 || id_2);
204
205 /* Special handling for libraries, since their filepaths is used then, not their ID names.
206 *
207 * NOTE: In library case, this call should always return true, since given data should always
208 * match. The asserts below merely ensure that expected conditions are always met:
209 * - A given library absolute filepath should never match its own bmain filepath.
210 * - If both given libraries are non-null:
211 * - Their absolute filepath should match.
212 * - Neither of their absolute filepaths should match any of the bmain filepaths.
213 * - If one of the library is null:
214 * - The other library should match the bmain filepath of the null library. */
215 if ((!id_1 && GS(id_2->name) == ID_LI) || GS(id_1->name) == ID_LI) {
216 BLI_assert(!id_1 || !ID_IS_LINKED(id_1));
217 BLI_assert(!id_2 || !ID_IS_LINKED(id_2));
218
219 Library *lib_1 = reinterpret_cast<Library *>(id_1);
220 Library *lib_2 = reinterpret_cast<Library *>(id_2);
221
222 if (lib_1 && lib_2) {
223 BLI_assert(STREQ(lib_1->runtime->filepath_abs, lib_2->runtime->filepath_abs));
224 }
225 if (lib_1) {
226 BLI_assert(!STREQ(lib_1->runtime->filepath_abs, bmain_1->filepath));
227 if (lib_2) {
228 BLI_assert(!STREQ(lib_1->runtime->filepath_abs, bmain_2->filepath));
229 }
230 else {
231 BLI_assert(STREQ(lib_1->runtime->filepath_abs, bmain_2->filepath));
232 }
233 }
234 if (lib_2) {
235 BLI_assert(!STREQ(lib_2->runtime->filepath_abs, bmain_2->filepath));
236 if (lib_1) {
237 BLI_assert(!STREQ(lib_2->runtime->filepath_abs, bmain_1->filepath));
238 }
239 else {
240 BLI_assert(STREQ(lib_2->runtime->filepath_abs, bmain_1->filepath));
241 }
242 }
243
244 return true;
245 }
246
247 /* Now both IDs are expected to be valid data, and caller is expected to have ensured already
248 * that they have the same name. */
249 BLI_assert(id_1 && id_2);
250 BLI_assert(STREQ(id_1->name, id_2->name));
251
252 if (!id_1->lib && !id_2->lib) {
253 return true;
254 }
255
256 if (id_1->lib && id_2->lib) {
257 if (id_1->lib == id_2->lib) {
258 return true;
259 }
260 if (STREQ(id_1->lib->runtime->filepath_abs, id_2->lib->runtime->filepath_abs)) {
261 return true;
262 }
263 return false;
264 }
265
266 /* In case one Main is the library of the ID from the other Main. */
267
268 if (id_1->lib) {
269 if (STREQ(id_1->lib->runtime->filepath_abs, bmain_2->filepath)) {
270 return true;
271 }
272 return false;
273 }
274
275 if (id_2->lib) {
276 if (STREQ(id_2->lib->runtime->filepath_abs, bmain_1->filepath)) {
277 return true;
278 }
279 return false;
280 }
281
283 return false;
284}
285
286static void main_merge_add_id_to_move(Main *bmain_dst,
287 blender::Map<std::string, blender::Vector<ID *>> &id_map_dst,
288 ID *id_src,
289 id::IDRemapper &id_remapper,
290 blender::Vector<ID *> &ids_to_move,
291 const bool is_library,
292 MainMergeReport &reports)
293{
294 const bool is_id_src_linked(id_src->lib);
295 bool is_id_src_from_bmain_dst = false;
296 if (is_id_src_linked) {
297 BLI_assert(!is_library);
298 UNUSED_VARS_NDEBUG(is_library);
299 blender::Vector<ID *> id_src_lib_dst = id_map_dst.lookup_default(
300 id_src->lib->runtime->filepath_abs, {});
301 /* The current library of the source ID would be remapped to null, which means that it comes
302 * from the destination Main. */
303 is_id_src_from_bmain_dst = !id_src_lib_dst.is_empty() && !id_src_lib_dst[0];
304 }
305 std::cout << id_src->name << " is linked from dst Main: " << is_id_src_from_bmain_dst << "\n";
306 std::cout.flush();
307
308 if (is_id_src_from_bmain_dst) {
309 /* Do not move an ID supposed to be from `bmain_dst` (used as library in `bmain_src`) into
310 * `bmain_src`. Fact that no match was found is worth a warning, although it could happen
311 * e.g. in case `bmain_dst` has been updated since it file was loaded as library in
312 * `bmain_src`. */
313 CLOG_WARN(&LOG,
314 "ID '%s' defined in source Main as linked from destination Main (file '%s') not "
315 "found in given destination Main",
316 id_src->name,
317 bmain_dst->filepath);
318 id_remapper.add(id_src, nullptr);
319 reports.num_unknown_ids++;
320 }
321 else {
322 ids_to_move.append(id_src);
323 }
324}
325
326void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &reports)
327{
328 Main *bmain_src = *r_bmain_src;
329 /* NOTE: Dedicated mapping type is needed here, to handle properly the library cases. */
331 ID *id_iter_dst, *id_iter_src;
332 FOREACH_MAIN_ID_BEGIN (bmain_dst, id_iter_dst) {
333 if (GS(id_iter_dst->name) == ID_LI) {
334 /* Libraries need specific handling, as we want to check them by their filepath, not the IDs
335 * themselves. */
336 Library *lib_dst = reinterpret_cast<Library *>(id_iter_dst);
337 BLI_assert(!id_map_dst.contains(lib_dst->runtime->filepath_abs));
338 id_map_dst.add(lib_dst->runtime->filepath_abs, {id_iter_dst});
339 }
340 else {
341 id_map_dst.lookup_or_add(id_iter_dst->name, {}).append(id_iter_dst);
342 }
343 }
345 /* Add the current `bmain_dst` filepath in the mapping as well, as it may be a library of the
346 * `bmain_src` Main. */
347 id_map_dst.add(bmain_dst->filepath, {nullptr});
348
349 /* A dedicated remapper for libraries is needed because these need to be remapped _before_ IDs
350 * are moved from `bmain_src` to `bmain_dst`, to avoid having to fix naming and ordering of IDs
351 * afterwards (especially in case some source linked IDs become local in `bmain_dst`). */
352 id::IDRemapper id_remapper;
353 id::IDRemapper id_remapper_libraries;
354 blender::Vector<ID *> ids_to_move;
355
356 FOREACH_MAIN_ID_BEGIN (bmain_src, id_iter_src) {
357 const bool is_library = GS(id_iter_src->name) == ID_LI;
358
359 blender::Vector<ID *> ids_dst = id_map_dst.lookup_default(
360 is_library ? reinterpret_cast<Library *>(id_iter_src)->runtime->filepath_abs :
361 id_iter_src->name,
362 {});
363 if (is_library) {
364 BLI_assert(ids_dst.size() <= 1);
365 }
366 if (ids_dst.is_empty()) {
368 bmain_dst, id_map_dst, id_iter_src, id_remapper, ids_to_move, is_library, reports);
369 continue;
370 }
371
372 bool src_has_match_in_dst = false;
373 for (ID *id_iter_dst : ids_dst) {
374 if (are_ids_from_different_mains_matching(bmain_dst, id_iter_dst, bmain_src, id_iter_src)) {
375 /* There should only ever be one potential match, never more. */
376 BLI_assert(!src_has_match_in_dst);
377 if (!src_has_match_in_dst) {
378 if (is_library) {
379 id_remapper_libraries.add(id_iter_src, id_iter_dst);
380 reports.num_remapped_libraries++;
381 }
382 else {
383 id_remapper.add(id_iter_src, id_iter_dst);
384 reports.num_remapped_ids++;
385 }
386 src_has_match_in_dst = true;
387 }
388#ifdef NDEBUG /* In DEBUG builds, keep looping to ensure there is only one match. */
389 break;
390#endif
391 }
392 }
393 if (!src_has_match_in_dst) {
395 bmain_dst, id_map_dst, id_iter_src, id_remapper, ids_to_move, is_library, reports);
396 }
397 }
399
400 reports.num_merged_ids = int(ids_to_move.size());
401
402 /* Rebase relative filepaths in `bmain_src` using `bmain_dst` path as new reference, or make them
403 * absolute if destination bmain has no filepath. */
404 if (bmain_src->filepath[0] != '\0') {
405 char dir_src[FILE_MAXDIR];
406 BLI_path_split_dir_part(bmain_src->filepath, dir_src, sizeof(dir_src));
408
409 if (bmain_dst->filepath[0] != '\0') {
410 char dir_dst[FILE_MAXDIR];
411 BLI_path_split_dir_part(bmain_dst->filepath, dir_dst, sizeof(dir_dst));
413 BKE_bpath_relative_rebase(bmain_src, dir_src, dir_dst, reports.reports);
414 }
415 else {
416 BKE_bpath_absolute_convert(bmain_src, dir_src, reports.reports);
417 }
418 }
419
420 /* Libraries need to be remapped before moving IDs into `bmain_dst`, to ensure that the sorting
421 * of inserted IDs is correct. Note that no bmain is given here, so this is only a 'raw'
422 * remapping. */
424 ids_to_move,
426 id_remapper_libraries,
428
429 for (ID *id_iter_src : ids_to_move) {
430 BKE_libblock_management_main_remove(bmain_src, id_iter_src);
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,
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{
478}
479
485
486void BKE_main_lock(Main *bmain)
487{
488 BLI_spin_lock((SpinLock *)bmain->lock);
489}
490
492{
493 BLI_spin_unlock((SpinLock *)bmain->lock);
494}
495
497{
498 MainIDRelations *bmain_relations = static_cast<MainIDRelations *>(cb_data->user_data);
499 ID *self_id = cb_data->self_id;
500 ID **id_pointer = cb_data->id_pointer;
501 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
502
503 if (*id_pointer) {
504 MainIDRelationsEntry **entry_p;
505
506 /* Add `id_pointer` as child of `self_id`. */
507 {
509 bmain_relations->relations_from_pointers, self_id, (void ***)&entry_p))
510 {
511 *entry_p = MEM_callocN<MainIDRelationsEntry>(__func__);
512 (*entry_p)->session_uid = self_id->session_uid;
513 }
514 else {
515 BLI_assert((*entry_p)->session_uid == self_id->session_uid);
516 }
517 MainIDRelationsEntryItem *to_id_entry = static_cast<MainIDRelationsEntryItem *>(
518 BLI_mempool_alloc(bmain_relations->entry_items_pool));
519 to_id_entry->next = (*entry_p)->to_ids;
520 to_id_entry->id_pointer.to = id_pointer;
521 to_id_entry->session_uid = (*id_pointer != nullptr) ? (*id_pointer)->session_uid :
523 to_id_entry->usage_flag = cb_flag;
524 (*entry_p)->to_ids = to_id_entry;
525 }
526
527 /* Add `self_id` as parent of `id_pointer`. */
528 if (*id_pointer != nullptr) {
530 bmain_relations->relations_from_pointers, *id_pointer, (void ***)&entry_p))
531 {
532 *entry_p = MEM_callocN<MainIDRelationsEntry>(__func__);
533 (*entry_p)->session_uid = (*id_pointer)->session_uid;
534 }
535 else {
536 BLI_assert((*entry_p)->session_uid == (*id_pointer)->session_uid);
537 }
538 MainIDRelationsEntryItem *from_id_entry = static_cast<MainIDRelationsEntryItem *>(
539 BLI_mempool_alloc(bmain_relations->entry_items_pool));
540 from_id_entry->next = (*entry_p)->from_ids;
541 from_id_entry->id_pointer.from = self_id;
542 from_id_entry->session_uid = self_id->session_uid;
543 from_id_entry->usage_flag = cb_flag;
544 (*entry_p)->from_ids = from_id_entry;
545 }
546 }
547
548 return IDWALK_RET_NOP;
549}
550
551void BKE_main_relations_create(Main *bmain, const short flag)
552{
553 if (bmain->relations != nullptr) {
555 }
556
557 bmain->relations = MEM_mallocN<MainIDRelations>(__func__);
561 sizeof(MainIDRelationsEntryItem), 128, 128, BLI_MEMPOOL_NOP);
562
563 bmain->relations->flag = flag;
564
565 ID *id;
566 FOREACH_MAIN_ID_BEGIN (bmain, id) {
567 const LibraryForeachIDFlag idwalk_flag = IDWALK_READONLY |
570 IDWALK_NOP);
571
572 /* Ensure all IDs do have an entry, even if they are not connected to any other. */
573 MainIDRelationsEntry **entry_p;
574 if (!BLI_ghash_ensure_p(bmain->relations->relations_from_pointers, id, (void ***)&entry_p)) {
575 *entry_p = MEM_callocN<MainIDRelationsEntry>(__func__);
576 (*entry_p)->session_uid = id->session_uid;
577 }
578 else {
579 BLI_assert((*entry_p)->session_uid == id->session_uid);
580 }
581
583 nullptr, id, main_relations_create_idlink_cb, bmain->relations, idwalk_flag);
584 }
586}
587
589{
590 if (bmain->relations != nullptr) {
591 if (bmain->relations->relations_from_pointers != nullptr) {
593 }
595 MEM_freeN(bmain->relations);
596 bmain->relations = nullptr;
597 }
598}
599
600void BKE_main_relations_tag_set(Main *bmain, const eMainIDRelationsEntryTags tag, const bool value)
601{
602 if (bmain->relations == nullptr) {
603 return;
604 }
605
606 GHashIterator *gh_iter;
608 !BLI_ghashIterator_done(gh_iter);
609 BLI_ghashIterator_step(gh_iter))
610 {
611 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
613 if (value) {
614 entry->tags |= tag;
615 }
616 else {
617 entry->tags &= ~tag;
618 }
619 }
620 BLI_ghashIterator_free(gh_iter);
621}
622
624{
625 if (gset == nullptr) {
627 }
628
629 ID *id;
630 FOREACH_MAIN_ID_BEGIN (bmain, id) {
631 BLI_gset_add(gset, id);
632 }
634 return gset;
635}
636
637/* Utils for ID's library weak reference API. */
641
642 LibWeakRefKey(const char *lib_path, const char *id_name)
643 {
644 STRNCPY(this->filepath, lib_path);
645 STRNCPY(this->id_name, id_name);
646 }
647
648 friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
649 {
650 return STREQ(a.filepath, b.filepath) && STREQ(a.id_name, b.id_name);
651 }
652
654 {
655 return blender::get_default_hash(blender::StringRef(this->filepath),
656 blender::StringRef(this->id_name));
657 }
658};
659
663
665{
666 auto *library_weak_reference_mapping = MEM_new<MainLibraryWeakReferenceMap>(__func__);
667
668 ListBase *lb;
669 FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
670 ID *id_iter = static_cast<ID *>(lb->first);
671 if (id_iter == nullptr) {
672 continue;
673 }
675 continue;
676 }
678
679 FOREACH_MAIN_LISTBASE_ID_BEGIN (lb, id_iter) {
680 if (id_iter->library_weak_reference == nullptr) {
681 continue;
682 }
685 library_weak_reference_mapping->map.add(key, id_iter);
686 }
688 }
690
691 return library_weak_reference_mapping;
692}
693
695 MainLibraryWeakReferenceMap *library_weak_reference_mapping)
696{
697 MEM_delete(library_weak_reference_mapping);
698}
699
701 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
702 const char *library_filepath,
703 const char *library_id_name)
704{
705 const LibWeakRefKey key{library_filepath, library_id_name};
706 return library_weak_reference_mapping->map.lookup_default(key, nullptr);
707}
708
710 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
711 const char *library_filepath,
712 const char *library_id_name,
713 ID *new_id)
714{
715 BLI_assert(GS(library_id_name) == GS(new_id->name));
716 BLI_assert(new_id->library_weak_reference == nullptr);
718
719 const LibWeakRefKey key{library_filepath, library_id_name};
720 /* With packed IDs and archive libraries, it is now possible to have several instances of the
721 * (originally) same linked ID made local at the same time in an append opeeration, so it is
722 * possible to get the same key several time here. And `Map::add_new` cannot be used safely
723 * anymore.
724 *
725 * Simply consider the first added one as valid, there is no good way to determine the 'best' one
726 * to keep around for append-or-reuse operations anyway - and the whole append-and-reuse may be
727 * depracted soon too. */
728 library_weak_reference_mapping->map.add(key, new_id);
729
730 BKE_main_library_weak_reference_add(new_id, library_filepath, library_id_name);
731}
732
734 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
735 const char *library_filepath,
736 const char *library_id_name,
737 ID *old_id,
738 ID *new_id)
739{
740 BLI_assert(GS(library_id_name) == GS(old_id->name));
741 BLI_assert(GS(library_id_name) == GS(new_id->name));
742 BLI_assert(old_id->library_weak_reference != nullptr);
743 BLI_assert(new_id->library_weak_reference == nullptr);
744 BLI_assert(STREQ(old_id->library_weak_reference->library_filepath, library_filepath));
745 BLI_assert(STREQ(old_id->library_weak_reference->library_id_name, library_id_name));
746
747 const LibWeakRefKey key{library_filepath, library_id_name};
748 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
749 library_weak_reference_mapping->map.add_overwrite(key, new_id);
750
752 old_id->library_weak_reference = nullptr;
753}
754
756 MainLibraryWeakReferenceMap *library_weak_reference_mapping,
757 const char *library_filepath,
758 const char *library_id_name,
759 ID *old_id)
760{
761 BLI_assert(GS(library_id_name) == GS(old_id->name));
762 BLI_assert(old_id->library_weak_reference != nullptr);
763
764 const LibWeakRefKey key{library_filepath, library_id_name};
765
766 BLI_assert(library_weak_reference_mapping->map.lookup(key) == old_id);
767 library_weak_reference_mapping->map.remove(key);
768
770}
771
773 const char *library_filepath,
774 const char *library_id_name)
775{
776 /* Make filepath absolute so we can compare filepaths that may be either relative or absolute. */
777 char library_filepath_abs[FILE_MAX];
778 STRNCPY(library_filepath_abs, library_filepath);
779 BLI_path_abs(library_filepath_abs, BKE_main_blendfile_path(bmain));
780
781 ListBase *id_list = which_libbase(bmain, GS(library_id_name));
782 LISTBASE_FOREACH (ID *, existing_id, id_list) {
783 if (!(existing_id->library_weak_reference &&
784 STREQ(existing_id->library_weak_reference->library_id_name, library_id_name)))
785 {
786 continue;
787 }
788
789 char existing_filepath_abs[FILE_MAX];
790 STRNCPY(existing_filepath_abs, existing_id->library_weak_reference->library_filepath);
791 BLI_path_abs(existing_filepath_abs, BKE_main_blendfile_path(bmain));
792
793 if (!STREQ(existing_filepath_abs, library_filepath_abs)) {
794 continue;
795 }
796
797 return existing_id;
798 }
799
800 return nullptr;
801}
802
804 const char *library_filepath,
805 const char *library_id_name)
806{
807 if (local_id->library_weak_reference == nullptr) {
809 }
810
811 STRNCPY(local_id->library_weak_reference->library_filepath, library_filepath);
812 STRNCPY(local_id->library_weak_reference->library_id_name, library_id_name);
813}
814
815BlendThumbnail *BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
816{
817 BlendThumbnail *data = nullptr;
818
819 if (bmain) {
821 }
822
823 if (rect) {
824 const size_t data_size = BLEN_THUMB_MEMSIZE(size[0], size[1]);
825 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
826 data->width = size[0];
827 data->height = size[1];
828 memcpy(data->rect, rect, data_size - sizeof(*data));
829 }
830
831 if (bmain) {
832 bmain->blen_thumb = data;
833 }
834 return data;
835}
836
838{
839 BlendThumbnail *data = nullptr;
840
841 if (bmain) {
843 }
844
845 if (img) {
846 const size_t data_size = BLEN_THUMB_MEMSIZE(img->x, img->y);
847 data = static_cast<BlendThumbnail *>(MEM_mallocN(data_size, __func__));
848
849 IMB_byte_from_float(img); /* Just in case... */
850 data->width = img->x;
851 data->height = img->y;
852 memcpy(data->rect, img->byte_buffer.data, data_size - sizeof(*data));
853 }
854
855 if (bmain) {
856 bmain->blen_thumb = data;
857 }
858 return data;
859}
860
862{
863 ImBuf *img = nullptr;
864
865 if (!data && bmain) {
866 data = bmain->blen_thumb;
867 }
868
869 if (data) {
871 (const uint8_t *)data->rect, nullptr, uint(data->width), uint(data->height), 4);
872 }
873
874 return img;
875}
876
878{
880
881 bmain->blen_thumb = static_cast<BlendThumbnail *>(
885}
886
887const char *BKE_main_blendfile_path(const Main *bmain)
888{
889 return bmain->filepath;
890}
891
896
898{
899 return library.runtime->filepath_abs;
900}
901
902ListBase *which_libbase(Main *bmain, short type)
903{
904 switch ((ID_Type)type) {
905 case ID_SCE:
906 return &(bmain->scenes);
907 case ID_LI:
908 return &(bmain->libraries);
909 case ID_OB:
910 return &(bmain->objects);
911 case ID_ME:
912 return &(bmain->meshes);
913 case ID_CU_LEGACY:
914 return &(bmain->curves);
915 case ID_MB:
916 return &(bmain->metaballs);
917 case ID_MA:
918 return &(bmain->materials);
919 case ID_TE:
920 return &(bmain->textures);
921 case ID_IM:
922 return &(bmain->images);
923 case ID_LT:
924 return &(bmain->lattices);
925 case ID_LA:
926 return &(bmain->lights);
927 case ID_CA:
928 return &(bmain->cameras);
929 case ID_KE:
930 return &(bmain->shapekeys);
931 case ID_WO:
932 return &(bmain->worlds);
933 case ID_SCR:
934 return &(bmain->screens);
935 case ID_VF:
936 return &(bmain->fonts);
937 case ID_TXT:
938 return &(bmain->texts);
939 case ID_SPK:
940 return &(bmain->speakers);
941 case ID_LP:
942 return &(bmain->lightprobes);
943 case ID_SO:
944 return &(bmain->sounds);
945 case ID_GR:
946 return &(bmain->collections);
947 case ID_AR:
948 return &(bmain->armatures);
949 case ID_AC:
950 return &(bmain->actions);
951 case ID_NT:
952 return &(bmain->nodetrees);
953 case ID_BR:
954 return &(bmain->brushes);
955 case ID_PA:
956 return &(bmain->particles);
957 case ID_WM:
958 return &(bmain->wm);
959 case ID_GD_LEGACY:
960 return &(bmain->gpencils);
961 case ID_GP:
962 return &(bmain->grease_pencils);
963 case ID_MC:
964 return &(bmain->movieclips);
965 case ID_MSK:
966 return &(bmain->masks);
967 case ID_LS:
968 return &(bmain->linestyles);
969 case ID_PAL:
970 return &(bmain->palettes);
971 case ID_PC:
972 return &(bmain->paintcurves);
973 case ID_CF:
974 return &(bmain->cachefiles);
975 case ID_WS:
976 return &(bmain->workspaces);
977 case ID_CV:
978 return &(bmain->hair_curves);
979 case ID_PT:
980 return &(bmain->pointclouds);
981 case ID_VO:
982 return &(bmain->volumes);
983 }
984 return nullptr;
985}
986
988{
989 MainListsArray lb{};
990 /* Libraries may be accessed from pretty much any other ID. */
991 lb[INDEX_ID_LI] = &bmain.libraries;
992
993 /* Moved here to avoid problems when freeing with animato (aligorith). */
994 lb[INDEX_ID_AC] = &bmain.actions;
995
996 lb[INDEX_ID_KE] = &bmain.shapekeys;
997
998 /* Referenced by gpencil, so needs to be before that to avoid crashes. */
999 lb[INDEX_ID_PAL] = &bmain.palettes;
1000
1001 /* Referenced by nodes, objects, view, scene etc, before to free after. */
1002 lb[INDEX_ID_GD_LEGACY] = &bmain.gpencils;
1003 lb[INDEX_ID_GP] = &bmain.grease_pencils;
1004
1005 lb[INDEX_ID_NT] = &bmain.nodetrees;
1006 lb[INDEX_ID_IM] = &bmain.images;
1007 lb[INDEX_ID_TE] = &bmain.textures;
1008 lb[INDEX_ID_MA] = &bmain.materials;
1009 lb[INDEX_ID_VF] = &bmain.fonts;
1010
1011 /* Important!: When adding a new object type,
1012 * the specific data should be inserted here. */
1013
1014 lb[INDEX_ID_AR] = &bmain.armatures;
1015
1016 lb[INDEX_ID_CF] = &bmain.cachefiles;
1017 lb[INDEX_ID_ME] = &bmain.meshes;
1018 lb[INDEX_ID_CU_LEGACY] = &bmain.curves;
1019 lb[INDEX_ID_MB] = &bmain.metaballs;
1020 lb[INDEX_ID_CV] = &bmain.hair_curves;
1021 lb[INDEX_ID_PT] = &bmain.pointclouds;
1022 lb[INDEX_ID_VO] = &bmain.volumes;
1023
1024 lb[INDEX_ID_LT] = &bmain.lattices;
1025 lb[INDEX_ID_LA] = &bmain.lights;
1026 lb[INDEX_ID_CA] = &bmain.cameras;
1027
1028 lb[INDEX_ID_TXT] = &bmain.texts;
1029 lb[INDEX_ID_SO] = &bmain.sounds;
1030 lb[INDEX_ID_GR] = &bmain.collections;
1031 lb[INDEX_ID_PAL] = &bmain.palettes;
1032 lb[INDEX_ID_PC] = &bmain.paintcurves;
1033 lb[INDEX_ID_BR] = &bmain.brushes;
1034 lb[INDEX_ID_PA] = &bmain.particles;
1035 lb[INDEX_ID_SPK] = &bmain.speakers;
1036 lb[INDEX_ID_LP] = &bmain.lightprobes;
1037
1038 lb[INDEX_ID_WO] = &bmain.worlds;
1039 lb[INDEX_ID_MC] = &bmain.movieclips;
1040 lb[INDEX_ID_SCR] = &bmain.screens;
1041 lb[INDEX_ID_OB] = &bmain.objects;
1042 /* referenced by scenes */
1043 lb[INDEX_ID_LS] = &bmain.linestyles;
1044 lb[INDEX_ID_SCE] = &bmain.scenes;
1045 /* before wm, so it's freed after it! */
1046 lb[INDEX_ID_WS] = &bmain.workspaces;
1047 lb[INDEX_ID_WM] = &bmain.wm;
1048 lb[INDEX_ID_MSK] = &bmain.masks;
1049
1050 return lb;
1051}
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports, BPathSummary *r_summary=nullptr)
Definition bpath.cc:627
void BKE_bpath_relative_rebase(Main *bmain, const char *basedir_src, const char *basedir_dst, ReportList *reports, BPathSummary *r_summary=nullptr)
Definition bpath.cc:478
#define G_MAIN
bool BKE_idtype_idcode_is_linkable(short idcode)
Definition idtype.cc:197
bool BKE_idtype_idcode_append_is_reusable(short idcode)
Definition idtype.cc:216
void BKE_libblock_management_main_remove(Main *bmain, void *idv)
Definition lib_id.cc:1156
#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:1123
@ IDWALK_RET_NOP
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
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:792
@ ID_REMAP_TYPE_REMAP
@ ID_REMAP_DO_LIBRARY_POINTERS
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:583
void BKE_main_clear(Main &bmain)
Definition main.cc:96
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:552
std::array< ListBase *, INDEX_ID_MAX - 1 > MainListsArray
Definition BKE_main.hh:645
@ MAINIDRELATIONS_INCLUDE_UI
Definition BKE_main.hh:141
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:546
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:564
#define BLEN_THUMB_SIZE
Definition BKE_main.hh:684
eMainIDRelationsEntryTags
Definition BKE_main.hh:87
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:557
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
#define BLEN_THUMB_MEMSIZE(_x, _y)
Definition BKE_main.hh:686
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
@ RPT_INFO
Definition BKE_report.hh:35
#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_NOP
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)
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:693
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:189
ID and Library types, which are fundamental for SDNA.
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
#define MAX_ID_NAME
Definition DNA_ID.h:373
eID_Index
Definition DNA_ID.h:1279
@ INDEX_ID_TXT
Definition DNA_ID.h:1301
@ INDEX_ID_WM
Definition DNA_ID.h:1354
@ INDEX_ID_VO
Definition DNA_ID.h:1330
@ INDEX_ID_NULL
Definition DNA_ID.h:1357
@ INDEX_ID_CF
Definition DNA_ID.h:1317
@ INDEX_ID_CV
Definition DNA_ID.h:1328
@ INDEX_ID_PT
Definition DNA_ID.h:1329
@ INDEX_ID_GR
Definition DNA_ID.h:1340
@ INDEX_ID_LA
Definition DNA_ID.h:1332
@ INDEX_ID_LT
Definition DNA_ID.h:1331
@ INDEX_ID_PC
Definition DNA_ID.h:1345
@ INDEX_ID_MA
Definition DNA_ID.h:1312
@ INDEX_ID_IM
Definition DNA_ID.h:1307
@ INDEX_ID_OB
Definition DNA_ID.h:1339
@ INDEX_ID_ME
Definition DNA_ID.h:1325
@ INDEX_ID_SO
Definition DNA_ID.h:1302
@ INDEX_ID_VF
Definition DNA_ID.h:1300
@ INDEX_ID_MC
Definition DNA_ID.h:1308
@ INDEX_ID_MSK
Definition DNA_ID.h:1306
@ INDEX_ID_BR
Definition DNA_ID.h:1346
@ INDEX_ID_WS
Definition DNA_ID.h:1353
@ INDEX_ID_SCR
Definition DNA_ID.h:1352
@ INDEX_ID_SPK
Definition DNA_ID.h:1334
@ INDEX_ID_MB
Definition DNA_ID.h:1327
@ INDEX_ID_CU_LEGACY
Definition DNA_ID.h:1326
@ INDEX_ID_LI
Definition DNA_ID.h:1281
@ INDEX_ID_NT
Definition DNA_ID.h:1296
@ INDEX_ID_WO
Definition DNA_ID.h:1314
@ INDEX_ID_TE
Definition DNA_ID.h:1311
@ INDEX_ID_PAL
Definition DNA_ID.h:1344
@ INDEX_ID_GP
Definition DNA_ID.h:1336
@ INDEX_ID_LS
Definition DNA_ID.h:1313
@ INDEX_ID_SCE
Definition DNA_ID.h:1349
@ INDEX_ID_GD_LEGACY
Definition DNA_ID.h:1290
@ INDEX_ID_LP
Definition DNA_ID.h:1335
@ INDEX_ID_AC
Definition DNA_ID.h:1284
@ INDEX_ID_CA
Definition DNA_ID.h:1333
@ INDEX_ID_AR
Definition DNA_ID.h:1324
@ INDEX_ID_PA
Definition DNA_ID.h:1318
@ INDEX_ID_KE
Definition DNA_ID.h:1321
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_GR
@ ID_SPK
@ ID_MB
@ ID_LT
@ ID_OB
@ ID_GP
@ ID_PA
@ ID_PT
@ ID_PC
void IMB_colormanagement_working_space_init_default(Main *bmain)
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.
#define MEM_SAFE_FREE(v)
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
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
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
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 GS(x)
#define LOG(level)
Definition log.h:97
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:700
MainListsArray BKE_main_lists_get(Main &bmain)
Definition main.cc:987
BlendThumbnail * BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
Definition main.cc:837
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:902
void BKE_main_clear(Main &bmain)
Definition main.cc:96
void BKE_main_merge(Main *bmain_dst, Main **r_bmain_src, MainMergeReport &reports)
Definition main.cc:326
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:755
void BKE_main_library_weak_reference_add(ID *local_id, const char *library_filepath, const char *library_id_name)
Definition main.cc:803
bool BKE_main_needs_overwrite_confirm(const Main *bmain)
Definition main.cc:480
bool BKE_main_has_issues(const Main *bmain)
Definition main.cc:474
Main * BKE_main_new()
Definition main.cc:89
void BKE_main_lock(Main *bmain)
Definition main.cc:486
void BKE_main_relations_tag_set(Main *bmain, const eMainIDRelationsEntryTags tag, const bool value)
Definition main.cc:600
void BKE_main_thumbnail_create(Main *bmain)
Definition main.cc:877
ImBuf * BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
Definition main.cc:861
const char * BKE_main_blendfile_path_from_library(const Library &library)
Definition main.cc:897
void BKE_main_relations_create(Main *bmain, const short flag)
Definition main.cc:551
MainLibraryWeakReferenceMap * BKE_main_library_weak_reference_create(Main *bmain)
Definition main.cc:664
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:709
void BKE_main_free(Main *bmain)
Definition main.cc:192
void BKE_main_library_weak_reference_destroy(MainLibraryWeakReferenceMap *library_weak_reference_mapping)
Definition main.cc:694
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:733
BlendThumbnail * BKE_main_thumbnail_from_buffer(Main *bmain, const uint8_t *rect, const int size[2])
Definition main.cc:815
const char * BKE_main_blendfile_path(const Main *bmain)
Definition main.cc:887
ID * BKE_main_library_weak_reference_find(Main *bmain, const char *library_filepath, const char *library_id_name)
Definition main.cc:772
void BKE_main_unlock(Main *bmain)
Definition main.cc:491
static bool are_ids_from_different_mains_matching(Main *bmain_1, ID *id_1, Main *bmain_2, ID *id_2)
Definition main.cc:197
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:286
bool BKE_main_is_empty(Main *bmain)
Definition main.cc:462
static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
Definition main.cc:496
GSet * BKE_main_gset_create(Main *bmain, GSet *gset)
Definition main.cc:623
void BKE_main_relations_free(Main *bmain)
Definition main.cc:588
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:892
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:414
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
unsigned int session_uid
Definition DNA_ID.h:462
struct LibraryWeakReference * library_weak_reference
Definition DNA_ID.h:526
ImBufByteBuffer byte_buffer
friend bool operator==(const LibWeakRefKey &a, const LibWeakRefKey &b)
Definition main.cc:648
char filepath[FILE_MAX]
Definition main.cc:639
uint64_t hash() const
Definition main.cc:653
LibWeakRefKey(const char *lib_path, const char *id_name)
Definition main.cc:642
char id_name[MAX_ID_NAME]
Definition main.cc:640
LibraryForeachIDCallbackFlag cb_flag
char library_filepath[1024]
Definition DNA_ID.h:608
char library_id_name[258]
Definition DNA_ID.h:611
LibraryRuntimeHandle * runtime
Definition DNA_ID.h:579
void * first
bool is_missing_opencolorio_config
Definition BKE_main.hh:157
MainIDRelationsEntryItem * next
Definition BKE_main.hh:58
union MainIDRelationsEntryItem::@072362065353355346121131265061232353372304016351 id_pointer
LibraryForeachIDCallbackFlag usage_flag
Definition BKE_main.hh:70
GHash * relations_from_pointers
Definition BKE_main.hh:130
BLI_mempool * entry_items_pool
Definition BKE_main.hh:136
blender::Map< LibWeakRefKey, ID * > map
Definition main.cc:661
int num_remapped_libraries
Definition BKE_main.hh:394
ReportList * reports
Definition BKE_main.hh:375
ListBase volumes
Definition BKE_main.hh:322
ListBase lightprobes
Definition BKE_main.hh:296
ListBase brushes
Definition BKE_main.hh:302
ListBase masks
Definition BKE_main.hh:312
ListBase scenes
Definition BKE_main.hh:278
ListBase grease_pencils
Definition BKE_main.hh:310
UniqueName_Map * name_map_global
Definition BKE_main.hh:341
ListBase wm
Definition BKE_main.hh:307
bool is_asset_edit_file
Definition BKE_main.hh:199
bool has_forward_compatibility_issues
Definition BKE_main.hh:192
ListBase textures
Definition BKE_main.hh:285
ListBase actions
Definition BKE_main.hh:300
UniqueName_Map * name_map
Definition BKE_main.hh:335
ListBase texts
Definition BKE_main.hh:294
ListBase meshes
Definition BKE_main.hh:281
char filepath[1024]
Definition BKE_main.hh:179
ListBase movieclips
Definition BKE_main.hh:311
Main()
Definition main.cc:49
~Main()
Definition main.cc:62
ListBase hair_curves
Definition BKE_main.hh:320
ListBase lights
Definition BKE_main.hh:288
ListBase paintcurves
Definition BKE_main.hh:305
ListBase fonts
Definition BKE_main.hh:293
ListBase nodetrees
Definition BKE_main.hh:301
BlendThumbnail * blen_thumb
Definition BKE_main.hh:259
ListBase particles
Definition BKE_main.hh:303
ListBase materials
Definition BKE_main.hh:284
bool is_action_slot_to_id_map_dirty
Definition BKE_main.hh:253
ListBase linestyles
Definition BKE_main.hh:313
ListBase pointclouds
Definition BKE_main.hh:321
ListBase lattices
Definition BKE_main.hh:287
ListBase sounds
Definition BKE_main.hh:297
ListBase shapekeys
Definition BKE_main.hh:290
ListBase libraries
Definition BKE_main.hh:279
ListBase cameras
Definition BKE_main.hh:289
IDNameLib_Map * id_map
Definition BKE_main.hh:332
ListBase armatures
Definition BKE_main.hh:299
ListBase speakers
Definition BKE_main.hh:295
MainLock * lock
Definition BKE_main.hh:343
ListBase curves
Definition BKE_main.hh:282
ListBase worlds
Definition BKE_main.hh:291
ListBase screens
Definition BKE_main.hh:292
ListBase workspaces
Definition BKE_main.hh:315
ListBase palettes
Definition BKE_main.hh:304
ListBase metaballs
Definition BKE_main.hh:283
ListBase collections
Definition BKE_main.hh:298
std::shared_ptr< blender::VectorSet< Main * > > split_mains
Definition BKE_main.hh:166
ListBase images
Definition BKE_main.hh:286
ListBase gpencils
Definition BKE_main.hh:309
MainColorspace colorspace
Definition BKE_main.hh:274
MainIDRelations * relations
Definition BKE_main.hh:329
ListBase objects
Definition BKE_main.hh:280
ListBase cachefiles
Definition BKE_main.hh:314
uint8_t flag
Definition wm_window.cc:145