Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/library.c')
-rw-r--r--source/blender/blenkernel/intern/library.c224
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] = ' ';