diff options
Diffstat (limited to 'source/blender/blenkernel/intern/library.c')
-rw-r--r-- | source/blender/blenkernel/intern/library.c | 224 |
1 files changed, 220 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 8bb2864a604..f8f92825479 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -59,6 +59,7 @@ #include "DNA_movieclip_types.h" #include "DNA_mask_types.h" #include "DNA_node_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_speaker_types.h" @@ -95,6 +96,7 @@ #include "BKE_lamp.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_library_query.h" #include "BKE_linestyle.h" #include "BKE_mesh.h" #include "BKE_material.h" @@ -119,6 +121,9 @@ #include "RNA_access.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -644,7 +649,7 @@ int set_listbasepointers(Main *main, ListBase **lb) * Allocates and returns memory of the right size for the specified block type, * initialized to zero. */ -static ID *alloc_libblock_notest(short type) +void *BKE_libblock_alloc_notest(short type) { ID *id = NULL; @@ -766,7 +771,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name) ID *id = NULL; ListBase *lb = which_libbase(bmain, type); - id = alloc_libblock_notest(type); + id = BKE_libblock_alloc_notest(type); if (id) { BKE_main_lock(bmain); BLI_addtail(lb, id); @@ -781,6 +786,121 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name) return id; } +/** + * Initialize an ID of given type, such that it has valid 'empty' data. + * ID is assumed to be just calloc'ed. + */ +void BKE_libblock_init_empty(ID *id) +{ + /* Note that only ID types that are not valid when filled of zero should have a callback here. */ + switch (GS(id->name)) { + case ID_SCE: + BKE_scene_init((Scene *)id); + break; + case ID_LI: + /* Nothing to do. */ + break; + case ID_OB: + { + Object *ob = (Object *)id; + ob->type = OB_EMPTY; + BKE_object_init(ob); + break; + } + case ID_ME: + BKE_mesh_init((Mesh *)id); + break; + case ID_CU: + BKE_curve_init((Curve *)id); + break; + case ID_MB: + BKE_mball_init((MetaBall *)id); + break; + case ID_MA: + BKE_material_init((Material *)id); + break; + case ID_TE: + BKE_texture_default((Tex *)id); + break; + case ID_IM: + /* Image is a bit complicated, for now assume NULLified im is OK. */ + break; + case ID_LT: + BKE_lattice_init((Lattice *)id); + break; + case ID_LA: + BKE_lamp_init((Lamp *)id); + break; + case ID_SPK: + BKE_speaker_init((Speaker *)id); + break; + case ID_CA: + BKE_camera_init((Camera *)id); + break; + case ID_IP: + /* Should not be needed - animation from lib pre-2.5 is broken anyway. */ + BLI_assert(0); + break; + case ID_KE: + /* Shapekeys are a complex topic too - they depend on their 'user' data type... + * They are not linkable, though, so it should never reach here anyway. */ + BLI_assert(0); + break; + case ID_WO: + BKE_world_init((World *)id); + break; + case ID_SCR: + /* Nothing to do. */ + break; + case ID_VF: + BKE_vfont_init((VFont *)id); + break; + case ID_TXT: + BKE_text_init((Text *)id); + break; + case ID_SCRIPT: + BLI_assert(0); + break; + case ID_SO: + /* Another fuzzy case, think NULLified content is OK here... */ + break; + case ID_GR: + /* Nothing to do. */ + break; + case ID_AR: + /* Nothing to do. */ + break; + case ID_AC: + /* Nothing to do. */ + break; + case ID_NT: + ntreeInitDefault((bNodeTree *)id); + break; + case ID_BR: + BKE_brush_init((Brush *)id); + break; + case ID_PA: + /* Nothing to do. */ + break; + case ID_PC: + /* Nothing to do. */ + break; + case ID_WM: + /* We should never reach this. */ + BLI_assert(0); + break; + case ID_GD: + /* Nothing to do. */ + break; + case ID_MSK: + /* Nothing to do. */ + break; + case ID_LS: + BKE_linestyle_init((FreestyleLineStyle *)id); + break; + } +} + /* by spec, animdata is first item after ID */ /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */ static void id_copy_animdata(ID *id, const bool do_action) @@ -834,7 +954,7 @@ void *BKE_libblock_copy_nolib(ID *id, const bool do_action) ID *idn; size_t idn_len; - idn = alloc_libblock_notest(GS(id->name)); + idn = BKE_libblock_alloc_notest(GS(id->name)); assert(idn != NULL); BLI_strncpy(idn->name, id->name, sizeof(idn->name)); @@ -861,6 +981,31 @@ void *BKE_libblock_copy(ID *id) return BKE_libblock_copy_ex(G.main, id); } +static bool id_relink_looper(void *UNUSED(user_data), ID **id_pointer, const int cd_flag) +{ + ID *id = *id_pointer; + if (id) { + /* See: NEW_ID macro */ + if (id->newid) { + BKE_library_update_ID_link_user(id->newid, id, cd_flag); + *id_pointer = id->newid; + } + else if (id->flag & LIB_NEW) { + id->flag &= ~LIB_NEW; + BKE_libblock_relink(id); + } + } + return true; +} + +void BKE_libblock_relink(ID *id) +{ + if (id->lib) + return; + + BKE_library_foreach_ID_link(id, id_relink_looper, NULL, 0); +} + static void BKE_library_free(Library *lib) { if (lib->packedfile) @@ -1097,6 +1242,8 @@ void BKE_main_free(Main *mainvar) ListBase *lbarray[MAX_LIBARRAY]; int a; + MEM_SAFE_FREE(mainvar->blen_thumb); + a = set_listbasepointers(mainvar, lbarray); while (a--) { ListBase *lb = lbarray[a]; @@ -1142,6 +1289,7 @@ void BKE_main_free(Main *mainvar) case 30: BKE_libblock_free_ex(mainvar, id, false); break; case 31: BKE_libblock_free_ex(mainvar, id, false); break; case 32: BKE_libblock_free_ex(mainvar, id, false); break; + case 33: BKE_libblock_free_ex(mainvar, id, false); break; default: BLI_assert(0); break; @@ -1166,6 +1314,74 @@ void BKE_main_unlock(struct Main *bmain) BLI_spin_unlock((SpinLock *) bmain->lock); } +/** + * Generates a raw .blend file thumbnail data from given image. + * + * \param bmain If not NULL, also store generated data in this Main. + * \param img ImBuf image to generate thumbnail data from. + * \return The generated .blend file raw thumbnail data. + */ +BlendThumbnail *BKE_main_thumbnail_from_imbuf(Main *bmain, ImBuf *img) +{ + BlendThumbnail *data = NULL; + + if (bmain) { + MEM_SAFE_FREE(bmain->blen_thumb); + } + + if (img) { + const size_t sz = BLEN_THUMB_MEMSIZE(img->x, img->y); + data = MEM_mallocN(sz, __func__); + + IMB_rect_from_float(img); /* Just in case... */ + data->width = img->x; + data->height = img->y; + memcpy(data->rect, img->rect, sz - sizeof(*data)); + } + + if (bmain) { + bmain->blen_thumb = data; + } + return data; +} + +/** + * Generates an image from raw .blend file thumbnail \a data. + * + * \param bmain Use this bmain->blen_thumb data if given \a data is NULL. + * \param data Raw .blend file thumbnail data. + * \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) { + /* 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!). */ + 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; +} + /* ***************** ID ************************ */ ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const char *name) { @@ -1620,7 +1836,7 @@ void rename_id(ID *id, const char *name) */ void name_uiprefix_id(char *name, const ID *id) { - name[0] = id->lib ? 'L' : ' '; + name[0] = id->lib ? (ID_MISSING(id) ? 'M' : 'L') : ' '; name[1] = (id->flag & LIB_FAKEUSER) ? 'F' : ((id->us == 0) ? '0' : ' '); name[2] = ' '; |