2018-11-07 16:06:36 +01:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup bke
|
2018-11-07 16:06:36 +01:00
|
|
|
*
|
2019-02-12 01:21:09 +11:00
|
|
|
* Contains management of #Main database itself.
|
2018-11-07 16:06:36 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_ghash.h"
|
|
|
|
#include "BLI_mempool.h"
|
|
|
|
#include "BLI_threads.h"
|
|
|
|
|
|
|
|
#include "DNA_ID.h"
|
|
|
|
|
|
|
|
#include "BKE_global.h"
|
2020-02-10 12:58:59 +01:00
|
|
|
#include "BKE_lib_id.h"
|
|
|
|
#include "BKE_lib_query.h"
|
2018-11-07 16:06:36 +01:00
|
|
|
#include "BKE_main.h"
|
|
|
|
|
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
|
|
|
|
Main *BKE_main_new(void)
|
|
|
|
{
|
|
|
|
Main *bmain = MEM_callocN(sizeof(Main), "new main");
|
|
|
|
bmain->lock = MEM_mallocN(sizeof(SpinLock), "main lock");
|
|
|
|
BLI_spin_init((SpinLock *)bmain->lock);
|
|
|
|
return bmain;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_main_free(Main *mainvar)
|
|
|
|
{
|
|
|
|
/* also call when reading a file, erase all, etc */
|
2021-03-04 18:39:07 +01:00
|
|
|
ListBase *lbarray[INDEX_ID_MAX];
|
2018-11-07 16:06:36 +01:00
|
|
|
int a;
|
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Since we are removing whole main, no need to bother 'properly'
|
|
|
|
* (and slowly) removing each ID from it. */
|
2019-01-16 11:39:30 +01:00
|
|
|
const int free_flag = (LIB_ID_FREE_NO_MAIN | LIB_ID_FREE_NO_UI_USER |
|
|
|
|
LIB_ID_FREE_NO_USER_REFCOUNT | LIB_ID_FREE_NO_DEG_TAG);
|
2019-01-14 16:15:15 +01:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
MEM_SAFE_FREE(mainvar->blen_thumb);
|
|
|
|
|
|
|
|
a = set_listbasepointers(mainvar, lbarray);
|
|
|
|
while (a--) {
|
|
|
|
ListBase *lb = lbarray[a];
|
2019-01-14 16:15:15 +01:00
|
|
|
ID *id, *id_next;
|
2018-11-07 16:06:36 +01:00
|
|
|
|
2019-01-14 16:15:15 +01:00
|
|
|
for (id = lb->first; id != NULL; id = id_next) {
|
|
|
|
id_next = id->next;
|
2018-11-07 16:06:36 +01:00
|
|
|
#if 1
|
2019-01-14 16:15:15 +01:00
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
2018-11-07 16:06:36 +01:00
|
|
|
#else
|
|
|
|
/* errors freeing ID's can be hard to track down,
|
|
|
|
* enable this so valgrind will give the line number in its error log */
|
|
|
|
switch (a) {
|
2019-01-14 16:15:15 +01:00
|
|
|
case 0:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
break;
|
|
|
|
case 1:
|
2019-01-14 16:15:15 +01:00
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
case 2:
|
2019-01-14 16:15:15 +01:00
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 14:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 15:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 17:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 18:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 19:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 20:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 21:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 22:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 23:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 25:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 26:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 27:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 28:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 29:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 30:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 31:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
|
|
|
break;
|
2019-04-17 06:17:24 +02:00
|
|
|
case 33:
|
2019-01-14 16:15:15 +01:00
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
break;
|
2019-01-14 16:15:15 +01:00
|
|
|
case 34:
|
|
|
|
BKE_id_free_ex(mainvar, id, free_flag, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
break;
|
2018-11-07 16:06:36 +01:00
|
|
|
default:
|
2021-03-24 12:38:08 +11:00
|
|
|
BLI_assert_unreachable();
|
2018-11-07 16:06:36 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2019-01-14 16:15:15 +01:00
|
|
|
BLI_listbase_clear(lb);
|
2018-11-07 16:06:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mainvar->relations) {
|
|
|
|
BKE_main_relations_free(mainvar);
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_spin_end((SpinLock *)mainvar->lock);
|
|
|
|
MEM_freeN(mainvar->lock);
|
|
|
|
MEM_freeN(mainvar);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_main_lock(struct Main *bmain)
|
|
|
|
{
|
|
|
|
BLI_spin_lock((SpinLock *)bmain->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_main_unlock(struct Main *bmain)
|
|
|
|
{
|
|
|
|
BLI_spin_unlock((SpinLock *)bmain->lock);
|
|
|
|
}
|
|
|
|
|
2020-02-13 12:56:10 +01:00
|
|
|
static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
|
2018-11-07 16:06:36 +01:00
|
|
|
{
|
2021-01-20 15:50:56 +01:00
|
|
|
MainIDRelations *bmain_relations = cb_data->user_data;
|
2020-02-13 12:56:10 +01:00
|
|
|
ID *id_self = cb_data->id_self;
|
|
|
|
ID **id_pointer = cb_data->id_pointer;
|
|
|
|
const int cb_flag = cb_data->cb_flag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
if (*id_pointer) {
|
2021-01-21 14:52:40 +01:00
|
|
|
MainIDRelationsEntry **entry_p;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-21 14:52:40 +01:00
|
|
|
/* Add `id_pointer` as child of `id_self`. */
|
|
|
|
{
|
|
|
|
if (!BLI_ghash_ensure_p(
|
|
|
|
bmain_relations->relations_from_pointers, id_self, (void ***)&entry_p)) {
|
|
|
|
*entry_p = MEM_callocN(sizeof(**entry_p), __func__);
|
|
|
|
(*entry_p)->session_uuid = id_self->session_uuid;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_assert((*entry_p)->session_uuid == id_self->session_uuid);
|
|
|
|
}
|
|
|
|
MainIDRelationsEntryItem *to_id_entry = BLI_mempool_alloc(bmain_relations->entry_items_pool);
|
|
|
|
to_id_entry->next = (*entry_p)->to_ids;
|
|
|
|
to_id_entry->id_pointer.to = id_pointer;
|
|
|
|
to_id_entry->session_uuid = (*id_pointer != NULL) ? (*id_pointer)->session_uuid :
|
|
|
|
MAIN_ID_SESSION_UUID_UNSET;
|
|
|
|
to_id_entry->usage_flag = cb_flag;
|
|
|
|
(*entry_p)->to_ids = to_id_entry;
|
2018-11-07 16:06:36 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-21 14:52:40 +01:00
|
|
|
/* Add `id_self` as parent of `id_pointer`. */
|
|
|
|
if (*id_pointer != NULL) {
|
|
|
|
if (!BLI_ghash_ensure_p(
|
|
|
|
bmain_relations->relations_from_pointers, *id_pointer, (void ***)&entry_p)) {
|
|
|
|
*entry_p = MEM_callocN(sizeof(**entry_p), __func__);
|
|
|
|
(*entry_p)->session_uuid = (*id_pointer)->session_uuid;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_assert((*entry_p)->session_uuid == (*id_pointer)->session_uuid);
|
|
|
|
}
|
|
|
|
MainIDRelationsEntryItem *from_id_entry = BLI_mempool_alloc(
|
|
|
|
bmain_relations->entry_items_pool);
|
|
|
|
from_id_entry->next = (*entry_p)->from_ids;
|
|
|
|
from_id_entry->id_pointer.from = id_self;
|
|
|
|
from_id_entry->session_uuid = id_self->session_uuid;
|
|
|
|
from_id_entry->usage_flag = cb_flag;
|
|
|
|
(*entry_p)->from_ids = from_id_entry;
|
2018-11-07 16:06:36 +01:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
return IDWALK_RET_NOP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Generate the mappings between used IDs and their users, and vice-versa. */
|
2020-02-18 11:21:34 +01:00
|
|
|
void BKE_main_relations_create(Main *bmain, const short flag)
|
2018-11-07 16:06:36 +01:00
|
|
|
{
|
|
|
|
if (bmain->relations != NULL) {
|
|
|
|
BKE_main_relations_free(bmain);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__);
|
2021-01-21 14:52:40 +01:00
|
|
|
bmain->relations->relations_from_pointers = BLI_ghash_new(
|
2018-11-07 16:06:36 +01:00
|
|
|
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
|
2021-01-21 14:52:40 +01:00
|
|
|
bmain->relations->entry_items_pool = BLI_mempool_create(
|
|
|
|
sizeof(MainIDRelationsEntryItem), 128, 128, BLI_MEMPOOL_NOP);
|
|
|
|
|
|
|
|
bmain->relations->flag = flag;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-14 16:24:49 +01:00
|
|
|
ID *id;
|
2019-04-21 04:40:16 +10:00
|
|
|
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
2020-02-18 11:21:34 +01:00
|
|
|
const int idwalk_flag = IDWALK_READONLY |
|
|
|
|
((flag & MAINIDRELATIONS_INCLUDE_UI) != 0 ? IDWALK_INCLUDE_UI : 0);
|
2021-01-22 17:35:47 +01:00
|
|
|
|
|
|
|
/* Ensure all IDs do have an entry, even if they are not connected to any other. */
|
|
|
|
MainIDRelationsEntry **entry_p;
|
|
|
|
if (!BLI_ghash_ensure_p(bmain->relations->relations_from_pointers, id, (void ***)&entry_p)) {
|
|
|
|
*entry_p = MEM_callocN(sizeof(**entry_p), __func__);
|
|
|
|
(*entry_p)->session_uuid = id->session_uuid;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_assert((*entry_p)->session_uuid == id->session_uuid);
|
|
|
|
}
|
|
|
|
|
2019-02-14 16:24:49 +01:00
|
|
|
BKE_library_foreach_ID_link(
|
2020-02-18 11:21:34 +01:00
|
|
|
NULL, id, main_relations_create_idlink_cb, bmain->relations, idwalk_flag);
|
2019-02-14 16:24:49 +01:00
|
|
|
}
|
|
|
|
FOREACH_MAIN_ID_END;
|
2018-11-07 16:06:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_main_relations_free(Main *bmain)
|
|
|
|
{
|
2021-01-21 14:52:40 +01:00
|
|
|
if (bmain->relations != NULL) {
|
|
|
|
if (bmain->relations->relations_from_pointers != NULL) {
|
|
|
|
BLI_ghash_free(bmain->relations->relations_from_pointers, NULL, MEM_freeN);
|
2018-11-07 16:06:36 +01:00
|
|
|
}
|
2021-01-21 14:52:40 +01:00
|
|
|
BLI_mempool_destroy(bmain->relations->entry_items_pool);
|
2018-11-07 16:06:36 +01:00
|
|
|
MEM_freeN(bmain->relations);
|
|
|
|
bmain->relations = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-02 17:26:30 +01:00
|
|
|
/** Set or clear given `tag` in all relation entries of given `bmain`. */
|
|
|
|
void BKE_main_relations_tag_set(struct Main *bmain,
|
|
|
|
const MainIDRelationsEntryTags tag,
|
|
|
|
const bool value)
|
|
|
|
{
|
|
|
|
if (bmain->relations == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
2021-02-09 21:38:57 +01:00
|
|
|
|
|
|
|
GHashIterator *gh_iter;
|
|
|
|
for (gh_iter = BLI_ghashIterator_new(bmain->relations->relations_from_pointers);
|
2021-02-02 17:26:30 +01:00
|
|
|
!BLI_ghashIterator_done(gh_iter);
|
|
|
|
BLI_ghashIterator_step(gh_iter)) {
|
|
|
|
MainIDRelationsEntry *entry = BLI_ghashIterator_getValue(gh_iter);
|
|
|
|
if (value) {
|
|
|
|
entry->tags |= tag;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
entry->tags &= ~tag;
|
|
|
|
}
|
|
|
|
}
|
2021-02-09 21:38:57 +01:00
|
|
|
BLI_ghashIterator_free(gh_iter);
|
2021-02-02 17:26:30 +01:00
|
|
|
}
|
|
|
|
|
2019-02-08 18:44:37 +01:00
|
|
|
/**
|
|
|
|
* Create a GSet storing all IDs present in given \a bmain, by their pointers.
|
|
|
|
*
|
2019-04-27 12:07:07 +10:00
|
|
|
* \param gset: If not NULL, given GSet will be extended with IDs from given \a bmain,
|
|
|
|
* instead of creating a new one.
|
2019-02-08 18:44:37 +01:00
|
|
|
*/
|
|
|
|
GSet *BKE_main_gset_create(Main *bmain, GSet *gset)
|
|
|
|
{
|
|
|
|
if (gset == NULL) {
|
|
|
|
gset = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-02-14 16:24:49 +01:00
|
|
|
ID *id;
|
2019-04-21 04:40:16 +10:00
|
|
|
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
2019-02-14 16:24:49 +01:00
|
|
|
BLI_gset_add(gset, id);
|
2019-02-07 17:16:15 +01:00
|
|
|
}
|
2019-02-14 16:24:49 +01:00
|
|
|
FOREACH_MAIN_ID_END;
|
|
|
|
return gset;
|
2019-02-07 17:16:15 +01:00
|
|
|
}
|
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
/**
|
|
|
|
* Generates a raw .blend file thumbnail data from given image.
|
|
|
|
*
|
2018-12-12 12:55:20 +11:00
|
|
|
* \param bmain: If not NULL, also store generated data in this Main.
|
|
|
|
* \param img: ImBuf image to generate thumbnail data from.
|
2018-11-07 16:06:36 +01:00
|
|
|
* \return The generated .blend file raw thumbnail data.
|
|
|
|
*/
|
|
|
|
BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img)
|
|
|
|
{
|
|
|
|
BlendThumbnail *data = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
if (bmain) {
|
|
|
|
MEM_SAFE_FREE(bmain->blen_thumb);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
if (img) {
|
|
|
|
const size_t sz = BLEN_THUMB_MEMSIZE(img->x, img->y);
|
|
|
|
data = MEM_mallocN(sz, __func__);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
IMB_rect_from_float(img); /* Just in case... */
|
|
|
|
data->width = img->x;
|
|
|
|
data->height = img->y;
|
|
|
|
memcpy(data->rect, img->rect, sz - sizeof(*data));
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
if (bmain) {
|
|
|
|
bmain->blen_thumb = data;
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates an image from raw .blend file thumbnail \a data.
|
|
|
|
*
|
2018-12-12 12:55:20 +11:00
|
|
|
* \param bmain: Use this bmain->blen_thumb data if given \a data is NULL.
|
|
|
|
* \param data: Raw .blend file thumbnail data.
|
2018-11-07 16:06:36 +01:00
|
|
|
* \return An ImBuf from given data, or NULL if invalid.
|
|
|
|
*/
|
|
|
|
ImBuf *BKE_main_thumbnail_to_imbuf(Main *bmain, BlendThumbnail *data)
|
|
|
|
{
|
|
|
|
ImBuf *img = NULL;
|
|
|
|
|
|
|
|
if (!data && bmain) {
|
|
|
|
data = bmain->blen_thumb;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data) {
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Note: we cannot use IMB_allocFromBuffer(), since it tries to dupalloc passed buffer,
|
|
|
|
* which will fail here (we do not want to pass the first two ints!). */
|
2018-11-07 16:06:36 +01:00
|
|
|
img = IMB_allocImBuf(
|
|
|
|
(unsigned int)data->width, (unsigned int)data->height, 32, IB_rect | IB_metadata);
|
|
|
|
memcpy(img->rect, data->rect, BLEN_THUMB_MEMSIZE(data->width, data->height) - sizeof(*data));
|
|
|
|
}
|
|
|
|
|
|
|
|
return img;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generates an empty (black) thumbnail for given Main.
|
|
|
|
*/
|
|
|
|
void BKE_main_thumbnail_create(struct Main *bmain)
|
|
|
|
{
|
|
|
|
MEM_SAFE_FREE(bmain->blen_thumb);
|
|
|
|
|
|
|
|
bmain->blen_thumb = MEM_callocN(BLEN_THUMB_MEMSIZE(BLEN_THUMB_SIZE, BLEN_THUMB_SIZE), __func__);
|
|
|
|
bmain->blen_thumb->width = BLEN_THUMB_SIZE;
|
|
|
|
bmain->blen_thumb->height = BLEN_THUMB_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return filepath of given \a main.
|
|
|
|
*/
|
|
|
|
const char *BKE_main_blendfile_path(const Main *bmain)
|
|
|
|
{
|
|
|
|
return bmain->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-02-12 01:21:09 +11:00
|
|
|
* Return filepath of global main #G_MAIN.
|
2018-11-07 16:06:36 +01:00
|
|
|
*
|
2019-04-27 12:07:07 +10:00
|
|
|
* \warning Usage is not recommended,
|
|
|
|
* you should always try to get a valid Main pointer from context...
|
2018-11-07 16:06:36 +01:00
|
|
|
*/
|
|
|
|
const char *BKE_main_blendfile_path_from_global(void)
|
|
|
|
{
|
|
|
|
return BKE_main_blendfile_path(G_MAIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \return A pointer to the \a ListBase of given \a bmain for requested \a type ID type.
|
|
|
|
*/
|
|
|
|
ListBase *which_libbase(Main *bmain, short type)
|
|
|
|
{
|
|
|
|
switch ((ID_Type)type) {
|
|
|
|
case ID_SCE:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->scenes);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_LI:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->libraries);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_OB:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->objects);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_ME:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->meshes);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_CU:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->curves);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_MB:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->metaballs);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_MA:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->materials);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_TE:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->textures);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_IM:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->images);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_LT:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->lattices);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_LA:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->lights);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_CA:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->cameras);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_IP:
|
|
|
|
return &(bmain->ipo);
|
|
|
|
case ID_KE:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->shapekeys);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_WO:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->worlds);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_SCR:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->screens);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_VF:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->fonts);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_TXT:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->texts);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_SPK:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->speakers);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_LP:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->lightprobes);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_SO:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->sounds);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_GR:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->collections);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_AR:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->armatures);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_AC:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->actions);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_NT:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->nodetrees);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_BR:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->brushes);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_PA:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->particles);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_WM:
|
|
|
|
return &(bmain->wm);
|
|
|
|
case ID_GD:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->gpencils);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_MC:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->movieclips);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_MSK:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->masks);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_LS:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->linestyles);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_PAL:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->palettes);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_PC:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->paintcurves);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_CF:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->cachefiles);
|
2018-11-07 16:06:36 +01:00
|
|
|
case ID_WS:
|
2019-03-08 09:29:17 +11:00
|
|
|
return &(bmain->workspaces);
|
2020-03-17 14:41:48 +01:00
|
|
|
case ID_HA:
|
|
|
|
return &(bmain->hairs);
|
|
|
|
case ID_PT:
|
|
|
|
return &(bmain->pointclouds);
|
|
|
|
case ID_VO:
|
|
|
|
return &(bmain->volumes);
|
2020-04-20 10:37:38 +02:00
|
|
|
case ID_SIM:
|
|
|
|
return &(bmain->simulations);
|
2018-11-07 16:06:36 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-03-04 18:39:07 +01:00
|
|
|
* Put the pointers to all the #ListBase structs in given `bmain` into the `*lb[INDEX_ID_MAX]`
|
2021-03-05 14:33:38 +11:00
|
|
|
* array, and return the number of those for convenience.
|
2018-11-07 16:06:36 +01:00
|
|
|
*
|
2021-03-04 18:39:07 +01:00
|
|
|
* This is useful for generic traversal of all the blocks in a #Main (by traversing all the lists
|
|
|
|
* in turn), without worrying about block types.
|
|
|
|
*
|
2021-06-10 01:55:41 +10:00
|
|
|
* \param lb: Array of lists #INDEX_ID_MAX in length.
|
|
|
|
*
|
2021-03-04 18:39:07 +01:00
|
|
|
* \note The order of each ID type #ListBase in the array is determined by the `INDEX_ID_<IDTYPE>`
|
|
|
|
* enum definitions in `DNA_ID.h`. See also the #FOREACH_MAIN_ID_BEGIN macro in `BKE_main.h`
|
|
|
|
*/
|
2021-06-10 01:55:41 +10:00
|
|
|
int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
|
2018-11-07 16:06:36 +01:00
|
|
|
{
|
2019-08-14 23:29:46 +10:00
|
|
|
/* Libraries may be accessed from pretty much any other ID. */
|
|
|
|
lb[INDEX_ID_LI] = &(bmain->libraries);
|
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
lb[INDEX_ID_IP] = &(bmain->ipo);
|
2019-08-14 23:29:46 +10:00
|
|
|
|
|
|
|
/* Moved here to avoid problems when freeing with animato (aligorith). */
|
|
|
|
lb[INDEX_ID_AC] = &(bmain->actions);
|
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_KE] = &(bmain->shapekeys);
|
2019-08-14 23:29:46 +10:00
|
|
|
|
|
|
|
/* Referenced by gpencil, so needs to be before that to avoid crashes. */
|
|
|
|
lb[INDEX_ID_PAL] = &(bmain->palettes);
|
|
|
|
|
|
|
|
/* Referenced by nodes, objects, view, scene etc, before to free after. */
|
|
|
|
lb[INDEX_ID_GD] = &(bmain->gpencils);
|
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_NT] = &(bmain->nodetrees);
|
|
|
|
lb[INDEX_ID_IM] = &(bmain->images);
|
|
|
|
lb[INDEX_ID_TE] = &(bmain->textures);
|
|
|
|
lb[INDEX_ID_MA] = &(bmain->materials);
|
|
|
|
lb[INDEX_ID_VF] = &(bmain->fonts);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
/* Important!: When adding a new object type,
|
2019-08-14 23:29:46 +10:00
|
|
|
* the specific data should be inserted here. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_AR] = &(bmain->armatures);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_CF] = &(bmain->cachefiles);
|
|
|
|
lb[INDEX_ID_ME] = &(bmain->meshes);
|
|
|
|
lb[INDEX_ID_CU] = &(bmain->curves);
|
|
|
|
lb[INDEX_ID_MB] = &(bmain->metaballs);
|
2020-03-17 14:41:48 +01:00
|
|
|
lb[INDEX_ID_HA] = &(bmain->hairs);
|
|
|
|
lb[INDEX_ID_PT] = &(bmain->pointclouds);
|
|
|
|
lb[INDEX_ID_VO] = &(bmain->volumes);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_LT] = &(bmain->lattices);
|
|
|
|
lb[INDEX_ID_LA] = &(bmain->lights);
|
|
|
|
lb[INDEX_ID_CA] = &(bmain->cameras);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_TXT] = &(bmain->texts);
|
|
|
|
lb[INDEX_ID_SO] = &(bmain->sounds);
|
|
|
|
lb[INDEX_ID_GR] = &(bmain->collections);
|
|
|
|
lb[INDEX_ID_PAL] = &(bmain->palettes);
|
|
|
|
lb[INDEX_ID_PC] = &(bmain->paintcurves);
|
|
|
|
lb[INDEX_ID_BR] = &(bmain->brushes);
|
|
|
|
lb[INDEX_ID_PA] = &(bmain->particles);
|
|
|
|
lb[INDEX_ID_SPK] = &(bmain->speakers);
|
|
|
|
lb[INDEX_ID_LP] = &(bmain->lightprobes);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_WO] = &(bmain->worlds);
|
|
|
|
lb[INDEX_ID_MC] = &(bmain->movieclips);
|
|
|
|
lb[INDEX_ID_SCR] = &(bmain->screens);
|
|
|
|
lb[INDEX_ID_OB] = &(bmain->objects);
|
|
|
|
lb[INDEX_ID_LS] = &(bmain->linestyles); /* referenced by scenes */
|
|
|
|
lb[INDEX_ID_SCE] = &(bmain->scenes);
|
|
|
|
lb[INDEX_ID_WS] = &(bmain->workspaces); /* before wm, so it's freed after it! */
|
2018-11-07 16:06:36 +01:00
|
|
|
lb[INDEX_ID_WM] = &(bmain->wm);
|
2019-03-08 09:29:17 +11:00
|
|
|
lb[INDEX_ID_MSK] = &(bmain->masks);
|
2020-04-20 10:37:38 +02:00
|
|
|
lb[INDEX_ID_SIM] = &(bmain->simulations);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-07 16:06:36 +01:00
|
|
|
lb[INDEX_ID_NULL] = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-03-04 18:39:07 +01:00
|
|
|
return (INDEX_ID_MAX - 1);
|
2018-11-07 16:06:36 +01:00
|
|
|
}
|