First step to handle missing libs/datablocks when reading a file.

Idea is, instead of ignoring completely missing linked datablocks, to
create void placeholders for them.

That way, you can work on your file, save it, and find again your missing data once
lib becomes available again. Or you can edit missing lib's path (in Outliner),
save and reload the file, and you are done.

Also, Outliner now shows broken libraries (and placeholders) with a 'broken lib' icon.

Future plans are also to be able to relocate missing libs and reload them at runtime.

Code notes:
    - Placeholder ID is just a regular datablock of same type as expected linked one,
      with 'default' data, and a LIB_MISSING bitflag set.
    - To allow creation of such datablocks, creation of datablocks in BKE was split in two step:
        + Allocation of memory itself.
        + Setting of all internal data to default values.

See also the design task (T43351).

Reviewed by @campbellbarton, thanks a bunch!

Differential Revision: https://developer.blender.org/D1394
This commit is contained in:
Bastien Montagne 2015-10-20 14:44:57 +02:00
parent dcb56d79a8
commit e5916187e8
Notes: blender-bot 2023-02-14 07:49:06 +01:00
Referenced by issue #48688, Crash during file open
38 changed files with 421 additions and 114 deletions

View File

@ -40,6 +40,7 @@ void BKE_brush_system_init(void);
void BKE_brush_system_exit(void);
/* datablock functions */
void BKE_brush_init(struct Brush *brush);
struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode);
struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode);
struct Brush *BKE_brush_copy(struct Brush *brush);

View File

@ -50,6 +50,7 @@ struct GPUFXSettings;
/* Camera Datablock */
void BKE_camera_init(struct Camera *cam);
void *BKE_camera_add(struct Main *bmain, const char *name);
struct Camera *BKE_camera_copy(struct Camera *cam);
void BKE_camera_make_local(struct Camera *cam);

View File

@ -69,6 +69,7 @@ typedef struct CurveCache {
void BKE_curve_unlink(struct Curve *cu);
void BKE_curve_free(struct Curve *cu);
void BKE_curve_editfont_free(struct Curve *cu);
void BKE_curve_init(struct Curve *cu);
struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type);
struct Curve *BKE_curve_copy(struct Curve *cu);
void BKE_curve_make_local(struct Curve *cu);

View File

@ -79,6 +79,7 @@ void BKE_vfont_builtin_register(void *mem, int size);
void BKE_vfont_free_data(struct VFont *vfont);
void BKE_vfont_free(struct VFont *sc);
void BKE_vfont_init(struct VFont *vfont);
struct VFont *BKE_vfont_builtin_get(void);
struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath);
struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists);

View File

@ -42,6 +42,7 @@ struct Lamp;
struct Main;
struct Scene;
void BKE_lamp_init(struct Lamp *la);
struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
struct Lamp *BKE_lamp_copy(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;

View File

@ -45,6 +45,7 @@ struct BPoint;
struct MDeformVert;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
void BKE_lattice_init(struct Lattice *lt);
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
struct Lattice *BKE_lattice_copy(struct Lattice *lt);
void BKE_lattice_free(struct Lattice *lt);

View File

@ -49,7 +49,9 @@ struct bContext;
struct PointerRNA;
struct PropertyRNA;
void *BKE_libblock_alloc_notest(short type);
void *BKE_libblock_alloc(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void BKE_libblock_init_empty(struct ID *id);
void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
void *BKE_libblock_copy_nolib(struct ID *id, const bool do_action) ATTR_NONNULL();
void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();

View File

@ -49,6 +49,7 @@ struct Object;
struct ColorBand;
struct bContext;
void BKE_linestyle_init(struct FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name);
void BKE_linestyle_free(FreestyleLineStyle *linestyle);
FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle);

View File

@ -49,7 +49,7 @@ void BKE_material_free(struct Material *sc);
void BKE_material_free_ex(struct Material *ma, bool do_id_user);
void test_object_materials(struct Main *bmain, struct ID *id);
void BKE_material_resize_object(struct Object *ob, const short totcol, bool do_id_user);
void init_material(struct Material *ma);
void BKE_material_init(struct Material *ma);
void BKE_material_remap_object(struct Object *ob, const unsigned int *remap);
struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Material *ma);

View File

@ -40,6 +40,7 @@ struct MetaElem;
void BKE_mball_unlink(struct MetaBall *mb);
void BKE_mball_free(struct MetaBall *mb);
void BKE_mball_init(struct MetaBall *mb);
struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name);
struct MetaBall *BKE_mball_copy(struct MetaBall *mb);

View File

@ -82,6 +82,7 @@ int BKE_mesh_edge_other_vert(const struct MEdge *e, int v);
void BKE_mesh_unlink(struct Mesh *me);
void BKE_mesh_free(struct Mesh *me, int unlink);
void BKE_mesh_init(struct Mesh *me);
struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
struct Mesh *BKE_mesh_copy_ex(struct Main *bmain, struct Mesh *me);
struct Mesh *BKE_mesh_copy(struct Mesh *me);

View File

@ -337,6 +337,7 @@ struct GHashIterator *ntreeTypeGetIterator(void);
void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
void ntreeInitDefault(struct bNodeTree *ntree);
struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
/* copy/free funcs, need to manage ID users */

View File

@ -85,6 +85,7 @@ bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
void BKE_object_init(struct Object *ob);
struct Object *BKE_object_add_only_object(
struct Main *bmain,
int type, const char *name)

View File

@ -67,6 +67,7 @@ void free_avicodecdata(struct AviCodecData *acd);
void free_qtcodecdata(struct QuicktimeCodecData *acd);
void BKE_scene_free(struct Scene *sce);
void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
/* base functions */

View File

@ -29,7 +29,9 @@
*/
struct Main;
struct Speaker;
void BKE_speaker_init(struct Speaker *spk);
void *BKE_speaker_add(struct Main *bmain, const char *name);
struct Speaker *BKE_speaker_copy(struct Speaker *spk);
void BKE_speaker_make_local(struct Speaker *spk);

View File

@ -44,6 +44,7 @@ struct TextLine;
void BKE_text_free (struct Text *text);
void txt_set_undostate (int u);
int txt_get_undostate (void);
void BKE_text_init(struct Text *ta);
struct Text *BKE_text_add (struct Main *bmain, const char *name);
int txt_extended_ascii_as_utf8(char **str);
bool BKE_text_reload(struct Text *text);

View File

@ -38,6 +38,7 @@ struct World;
void BKE_world_free(struct World *sc);
void BKE_world_free_ex(struct World *sc, bool do_id_user);
void BKE_world_init(struct World *wrld);
struct World *add_world(struct Main *bmian, const char *name);
struct World *BKE_world_copy(struct World *wrld);
struct World *localize_world(struct World *wrld);

View File

@ -131,11 +131,9 @@ static void brush_defaults(Brush *brush)
/* Datablock add/copy/free/make_local */
Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
void BKE_brush_init(Brush *brush)
{
Brush *brush;
brush = BKE_libblock_alloc(bmain, ID_BR, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(brush, id));
/* enable fake user by default */
brush->id.flag |= LIB_FAKEUSER;
@ -143,10 +141,20 @@ Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
brush_defaults(brush);
brush->sculpt_tool = SCULPT_TOOL_DRAW; /* sculpting defaults to the draw tool for new brushes */
brush->ob_mode = ob_mode;
/* the default alpha falloff curve */
BKE_brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
}
Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
{
Brush *brush;
brush = BKE_libblock_alloc(bmain, ID_BR, name);
BKE_brush_init(brush);
brush->ob_mode = ob_mode;
return brush;
}

View File

@ -57,11 +57,9 @@
/****************************** Camera Datablock *****************************/
void *BKE_camera_add(Main *bmain, const char *name)
void BKE_camera_init(Camera *cam)
{
Camera *cam;
cam = BKE_libblock_alloc(bmain, ID_CA, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(cam, id));
cam->lens = 35.0f;
cam->sensor_x = DEFAULT_SENSOR_WIDTH;
@ -78,6 +76,15 @@ void *BKE_camera_add(Main *bmain, const char *name)
/* stereoscopy 3d */
cam->stereo.interocular_distance = 0.065f;
cam->stereo.convergence_distance = 30.f * 0.065f;
}
void *BKE_camera_add(Main *bmain, const char *name)
{
Camera *cam;
cam = BKE_libblock_alloc(bmain, ID_CA, name);
BKE_camera_init(cam);
return cam;
}

View File

@ -161,15 +161,14 @@ void BKE_curve_free(Curve *cu)
MEM_freeN(cu->tb);
}
Curve *BKE_curve_add(Main *bmain, const char *name, int type)
void BKE_curve_init(Curve *cu)
{
Curve *cu;
/* BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(cu, id)); */ /* cu->type is already initialized... */
cu = BKE_libblock_alloc(bmain, ID_CU, name);
copy_v3_fl(cu->size, 1.0f);
cu->flag = CU_FRONT | CU_BACK | CU_DEFORM_BOUNDS_OFF | CU_PATH_RADIUS;
cu->pathlen = 100;
cu->resolu = cu->resolv = (type == OB_SURF) ? 4 : 12;
cu->resolu = cu->resolv = (cu->type == OB_SURF) ? 4 : 12;
cu->width = 1.0;
cu->wordspace = 1.0;
cu->spacing = cu->linedist = 1.0;
@ -179,7 +178,6 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
cu->smallcaps_scale = 0.75f;
/* XXX: this one seems to be the best one in most cases, at least for curve deform... */
cu->twist_mode = CU_TWIST_MINIMUM;
cu->type = type;
cu->bevfac1 = 0.0f;
cu->bevfac2 = 1.0f;
cu->bevfac1_mapping = CU_BEVFAC_MAP_RESOLU;
@ -187,7 +185,7 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
cu->bb = BKE_boundbox_alloc_unit();
if (type == OB_FONT) {
if (cu->type == OB_FONT) {
cu->vfont = cu->vfontb = cu->vfonti = cu->vfontbi = BKE_vfont_builtin_get();
cu->vfont->id.us += 4;
cu->str = MEM_mallocN(12, "str");
@ -198,6 +196,16 @@ Curve *BKE_curve_add(Main *bmain, const char *name, int type)
cu->tb = MEM_callocN(MAXTEXTBOX * sizeof(TextBox), "textbox");
cu->tb[0].w = cu->tb[0].h = 0.0;
}
}
Curve *BKE_curve_add(Main *bmain, const char *name, int type)
{
Curve *cu;
cu = BKE_libblock_alloc(bmain, ID_CU, name);
cu->type = type;
BKE_curve_init(cu);
return cu;
}

View File

@ -203,6 +203,26 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont)
return vfont->data;
}
/* Bad naming actually in this case... */
void BKE_vfont_init(VFont *vfont)
{
PackedFile *pf = get_builtin_packedfile();
if (pf) {
VFontData *vfd;
vfd = BLI_vfontdata_from_freetypefont(pf);
if (vfd) {
vfont->data = vfd;
BLI_strncpy(vfont->name, FO_BUILTIN_NAME, sizeof(vfont->name));
}
/* Free the packed file */
freePackedFile(pf);
}
}
VFont *BKE_vfont_load(Main *bmain, const char *filepath)
{
char filename[FILE_MAXFILE];

View File

@ -53,12 +53,10 @@
#include "BKE_main.h"
#include "BKE_node.h"
Lamp *BKE_lamp_add(Main *bmain, const char *name)
void BKE_lamp_init(Lamp *la)
{
Lamp *la;
la = BKE_libblock_alloc(bmain, ID_LA, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(la, id));
la->r = la->g = la->b = la->k = 1.0f;
la->haint = la->energy = 1.0f;
la->dist = 25.0f;
@ -100,6 +98,16 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name)
la->shadow_frustum_size = 10.0f;
curvemapping_initialize(la->curfalloff);
}
Lamp *BKE_lamp_add(Main *bmain, const char *name)
{
Lamp *la;
la = BKE_libblock_alloc(bmain, ID_LA, name);
BKE_lamp_init(la);
return la;
}

View File

@ -251,12 +251,10 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
MEM_freeN(vertexCos);
}
Lattice *BKE_lattice_add(Main *bmain, const char *name)
void BKE_lattice_init(Lattice *lt)
{
Lattice *lt;
lt = BKE_libblock_alloc(bmain, ID_LT, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(lt, id));
lt->flag = LT_GRID;
lt->typeu = lt->typev = lt->typew = KEY_BSPLINE;
@ -264,7 +262,16 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name)
lt->def = MEM_callocN(sizeof(BPoint), "lattvert"); /* temporary */
BKE_lattice_resize(lt, 2, 2, 2, NULL); /* creates a uniform lattice */
lt->actbp = LT_ACTBP_NONE;
}
Lattice *BKE_lattice_add(Main *bmain, const char *name)
{
Lattice *lt;
lt = BKE_libblock_alloc(bmain, ID_LT, name);
BKE_lattice_init(lt);
return lt;
}

View File

@ -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"
@ -648,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;
@ -770,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);
@ -785,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)
@ -838,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));
@ -1720,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] = ' ';

View File

@ -80,8 +80,10 @@ static const char *modifier_name[LS_MODIFIER_NUM] = {
"3D Curvature",
};
static void default_linestyle_settings(FreestyleLineStyle *linestyle)
void BKE_linestyle_init(FreestyleLineStyle *linestyle)
{
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(linestyle, id));
linestyle->panel = LS_PANEL_STROKES;
linestyle->r = linestyle->g = linestyle->b = 0.0f;
linestyle->alpha = 1.0f;
@ -118,7 +120,7 @@ FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name)
linestyle = (FreestyleLineStyle *)BKE_libblock_alloc(bmain, ID_LS, name);
default_linestyle_settings(linestyle);
BKE_linestyle_init(linestyle);
return linestyle;
}

View File

@ -78,7 +78,7 @@ Material defmaterial;
/* called on startup, creator.c */
void init_def_material(void)
{
init_material(&defmaterial);
BKE_material_init(&defmaterial);
}
/* not material itself */
@ -122,8 +122,10 @@ void BKE_material_free_ex(Material *ma, bool do_id_user)
GPU_material_free(&ma->gpumaterial);
}
void init_material(Material *ma)
void BKE_material_init(Material *ma)
{
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ma, id));
ma->r = ma->g = ma->b = ma->ref = 0.8;
ma->specr = ma->specg = ma->specb = 1.0;
ma->mirr = ma->mirg = ma->mirb = 1.0;
@ -221,7 +223,7 @@ Material *BKE_material_add(Main *bmain, const char *name)
ma = BKE_libblock_alloc(bmain, ID_MA, name);
init_material(ma);
BKE_material_init(ma);
return ma;
}

View File

@ -91,19 +91,26 @@ void BKE_mball_free(MetaBall *mb)
if (mb->disp.first) BKE_displist_free(&mb->disp);
}
MetaBall *BKE_mball_add(Main *bmain, const char *name)
void BKE_mball_init(MetaBall *mb)
{
MetaBall *mb;
mb = BKE_libblock_alloc(bmain, ID_MB, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(mb, id));
mb->size[0] = mb->size[1] = mb->size[2] = 1.0;
mb->texflag = MB_AUTOSPACE;
mb->wiresize = 0.4f;
mb->rendersize = 0.2f;
mb->thresh = 0.6f;
}
MetaBall *BKE_mball_add(Main *bmain, const char *name)
{
MetaBall *mb;
mb = BKE_libblock_alloc(bmain, ID_MB, name);
BKE_mball_init(mb);
return mb;
}

View File

@ -490,12 +490,10 @@ static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
mesh->totface = 0;
}
Mesh *BKE_mesh_add(Main *bmain, const char *name)
void BKE_mesh_init(Mesh *me)
{
Mesh *me;
me = BKE_libblock_alloc(bmain, ID_ME, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(me, id));
me->size[0] = me->size[1] = me->size[2] = 1.0;
me->smoothresh = 30;
me->texflag = ME_AUTOSPACE;
@ -511,6 +509,15 @@ Mesh *BKE_mesh_add(Main *bmain, const char *name)
CustomData_reset(&me->fdata);
CustomData_reset(&me->pdata);
CustomData_reset(&me->ldata);
}
Mesh *BKE_mesh_add(Main *bmain, const char *name)
{
Mesh *me;
me = BKE_libblock_alloc(bmain, ID_ME, name);
BKE_mesh_init(me);
return me;
}

View File

@ -1151,6 +1151,11 @@ void nodeDetachNode(struct bNode *node)
}
}
void ntreeInitDefault(bNodeTree *ntree)
{
ntree_set_typeinfo(ntree, NULL);
}
bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
{
bNodeTree *ntree;

View File

@ -972,19 +972,10 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
}
}
/* more general add: creates minimum required data, but without vertices etc. */
Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
void BKE_object_init(Object *ob)
{
Object *ob;
/* BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ob, id)); */ /* ob->type is already initialized... */
if (!name)
name = get_obdata_defname(type);
ob = BKE_libblock_alloc(bmain, ID_OB, name);
/* default object vars */
ob->type = type;
ob->col[0] = ob->col[1] = ob->col[2] = 1.0;
ob->col[3] = 1.0;
@ -1012,7 +1003,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob->empty_drawtype = OB_PLAINAXES;
ob->empty_drawsize = 1.0;
if (ELEM(type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
ob->trackflag = OB_NEGZ;
ob->upflag = OB_POSY;
}
@ -1053,6 +1044,22 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
/* Animation Visualization defaults */
animviz_settings_init(&ob->avs);
}
/* more general add: creates minimum required data, but without vertices etc. */
Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
{
Object *ob;
if (!name)
name = get_obdata_defname(type);
ob = BKE_libblock_alloc(bmain, ID_OB, name);
/* default object vars */
ob->type = type;
BKE_object_init(ob);
return ob;
}

View File

@ -464,15 +464,15 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
}
Scene *BKE_scene_add(Main *bmain, const char *name)
void BKE_scene_init(Scene *sce)
{
Scene *sce;
ParticleEditSettings *pset;
int a;
const char *colorspace_name;
SceneRenderView *srv;
sce = BKE_libblock_alloc(bmain, ID_SCE, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(sce, id));
sce->lay = sce->layact = 1;
sce->r.mode = R_GAMMA | R_OSA | R_SHADOW | R_SSS | R_ENVMAP | R_RAYTRACE;
@ -743,6 +743,15 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
copy_v2_fl2(sce->safe_areas.action_center, 15.0f / 100.0f, 5.0f / 100.0f);
sce->preview = NULL;
}
Scene *BKE_scene_add(Main *bmain, const char *name)
{
Scene *sce;
sce = BKE_libblock_alloc(bmain, ID_SCE, name);
BKE_scene_init(sce);
return sce;
}

View File

@ -37,11 +37,9 @@
#include "BKE_main.h"
#include "BKE_speaker.h"
void *BKE_speaker_add(Main *bmain, const char *name)
void BKE_speaker_init(Speaker *spk)
{
Speaker *spk;
spk = BKE_libblock_alloc(bmain, ID_SPK, name);
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(spk, id));
spk->attenuation = 1.0f;
spk->cone_angle_inner = 360.0f;
@ -55,6 +53,15 @@ void *BKE_speaker_add(Main *bmain, const char *name)
spk->volume = 1.0f;
spk->volume_max = 1.0f;
spk->volume_min = 0.0f;
}
void *BKE_speaker_add(Main *bmain, const char *name)
{
Speaker *spk;
spk = BKE_libblock_alloc(bmain, ID_SPK, name);
BKE_speaker_init(spk);
return spk;
}

View File

@ -171,14 +171,12 @@ void BKE_text_free(Text *text)
#endif
}
Text *BKE_text_add(Main *bmain, const char *name)
void BKE_text_init(Text *ta)
{
Text *ta;
TextLine *tmp;
ta = BKE_libblock_alloc(bmain, ID_TXT, name);
ta->id.us = 1;
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ta, id));
ta->name = NULL;
init_undo_text(ta);
@ -206,6 +204,15 @@ Text *BKE_text_add(Main *bmain, const char *name)
ta->curc = 0;
ta->sell = ta->lines.first;
ta->selc = 0;
}
Text *BKE_text_add(Main *bmain, const char *name)
{
Text *ta;
ta = BKE_libblock_alloc(bmain, ID_TXT, name);
BKE_text_init(ta);
return ta;
}

View File

@ -580,6 +580,8 @@ void BKE_texture_free(Tex *tex)
void BKE_texture_default(Tex *tex)
{
/* BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(tex, id)); */ /* Not here, can be called with some pointers set. :/ */
tex->type = TEX_IMAGE;
tex->ima = NULL;
tex->stype = 0;

View File

@ -31,6 +31,7 @@
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "MEM_guardedalloc.h"
@ -83,12 +84,10 @@ void BKE_world_free(World *wrld)
BKE_world_free_ex(wrld, true);
}
World *add_world(Main *bmain, const char *name)
void BKE_world_init(World *wrld)
{
World *wrld;
BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(wrld, id));
wrld = BKE_libblock_alloc(bmain, ID_WO, name);
wrld->horr = 0.05f;
wrld->horg = 0.05f;
wrld->horb = 0.05f;
@ -113,6 +112,15 @@ World *add_world(Main *bmain, const char *name)
wrld->preview = NULL;
wrld->miststa = 5.0f;
wrld->mistdist = 25.0f;
}
World *add_world(Main *bmain, const char *name)
{
World *wrld;
wrld = BKE_libblock_alloc(bmain, ID_WO, name);
BKE_world_init(wrld);
return wrld;
}

View File

@ -7937,7 +7937,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
if (id->flag & LIB_FAKEUSER) id->us= 1;
else id->us = 0;
id->icon_id = 0;
id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA|LIB_DOIT);
id->flag &= ~(LIB_ID_RECALC | LIB_ID_RECALC_DATA | LIB_DOIT | LIB_MISSING);
/* this case cannot be direct_linked: it's just the ID part */
if (bhead->code == ID_ID) {
@ -9615,6 +9615,25 @@ static void give_base_to_groups(
}
}
static ID *create_placeholder(Main *mainvar, const char *idname, const short flag)
{
const short idcode = GS(idname);
ListBase *lb = which_libbase(mainvar, idcode);
ID *ph_id = BKE_libblock_alloc_notest(idcode);
memcpy(ph_id->name, idname, sizeof(ph_id->name));
BKE_libblock_init_empty(ph_id);
ph_id->lib = mainvar->curlib;
ph_id->flag = flag | LIB_MISSING;
ph_id->us = (flag & LIB_FAKEUSER) ? 1 : 0;
ph_id->icon_id = 0;
BLI_addtail(lb, ph_id);
id_sort_by_name(lb, ph_id);
return ph_id;
}
/* returns true if the item was found
* but it may already have already been appended/linked */
static ID *link_named_part(Main *mainl, FileData *fd, const short idcode, const char *name)
@ -9758,16 +9777,35 @@ ID *BLO_library_link_named_part_ex(
return link_named_part_ex(mainl, fd, idcode, name, flag, scene, v3d);
}
static void link_id_part(FileData *fd, Main *mainvar, ID *id, ID **r_id)
static void link_id_part(ReportList *reports, FileData *fd, Main *mainvar, ID *id, ID **r_id)
{
BHead *bhead = find_bhead_from_idname(fd, id->name);
BHead *bhead = NULL;
if (fd) {
bhead = find_bhead_from_idname(fd, id->name);
}
id->flag &= ~LIB_READ;
if (bhead) {
id->flag &= ~LIB_READ;
id->flag |= LIB_NEED_EXPAND;
// printf("read lib block %s\n", id->name);
read_libblock(fd, mainvar, bhead, id->flag, r_id);
}
else {
blo_reportf_wrap(
reports, RPT_WARNING,
TIP_("LIB ERROR: %s: '%s' missing from '%s', parent '%s'"),
BKE_idcode_to_name(GS(id->name)),
id->name + 2,
mainvar->curlib->filepath,
library_parent_filepath(mainvar->curlib));
/* Generate a placeholder for this ID (simplified version of read_libblock actually...). */
if (r_id) {
*r_id = create_placeholder(mainvar, id->name, id->flag);
}
}
}
/* common routine to append/link something from a library */
@ -10012,6 +10050,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
else {
mainptr->curlib->filedata = NULL;
mainptr->curlib->id.flag |= LIB_MISSING;
}
if (fd == NULL) {
@ -10021,37 +10060,29 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
if (fd) {
do_it = true;
a = set_listbasepointers(mainptr, lbarray);
while (a--) {
ID *id = lbarray[a]->first;
while (id) {
ID *idn = id->next;
if (id->flag & LIB_READ) {
ID *realid = NULL;
BLI_remlink(lbarray[a], id);
link_id_part(fd, mainptr, id, &realid);
if (!realid) {
blo_reportf_wrap(
fd->reports, RPT_WARNING,
TIP_("LIB ERROR: %s: '%s' missing from '%s', parent '%s'"),
BKE_idcode_to_name(GS(id->name)),
id->name + 2,
mainptr->curlib->filepath,
library_parent_filepath(mainptr->curlib));
}
change_idid_adr(mainlist, basefd, id, realid);
MEM_freeN(id);
}
id = idn;
}
}
BLO_expand_main(fd, mainptr);
}
a = set_listbasepointers(mainptr, lbarray);
while (a--) {
ID *id = lbarray[a]->first;
while (id) {
ID *idn = id->next;
if (id->flag & LIB_READ) {
ID *realid = NULL;
BLI_remlink(lbarray[a], id);
link_id_part(basefd->reports, fd, mainptr, id, &realid);
BLI_assert(realid != NULL);
change_idid_adr(mainlist, basefd, id, realid);
MEM_freeN(id);
}
id = idn;
}
}
BLO_expand_main(fd, mainptr);
}
mainptr = mainptr->next;
@ -10059,6 +10090,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
}
/* test if there are unread libblocks */
/* XXX This code block is kept for 2.77, until we are sure it never gets reached anymore. Can be removed later. */
for (mainptr = mainl->next; mainptr; mainptr = mainptr->next) {
a = set_listbasepointers(mainptr, lbarray);
while (a--) {
@ -10067,10 +10099,12 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
for (id = lbarray[a]->first; id; id = idn) {
idn = id->next;
if (id->flag & LIB_READ) {
BLI_assert(0);
BLI_remlink(lbarray[a], id);
blo_reportf_wrap(
basefd->reports, RPT_WARNING,
TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s', parent '%s'"),
TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s', parent '%s' - "
"Please file a bug report if you see this message"),
BKE_idcode_to_name(GS(id->name)),
id->name + 2,
mainptr->curlib->filepath,

View File

@ -1318,7 +1318,16 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
case ID_GR:
tselem_draw_icon_uibut(&arg, ICON_GROUP); break;
case ID_LI:
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break;
if (tselem->id->flag & LIB_MISSING) {
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_BROKEN);
}
else if (((Library *)tselem->id)->parent) {
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_INDIRECT);
}
else {
tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT);
}
break;
case ID_LS:
tselem_draw_icon_uibut(&arg, ICON_LINE_DATA); break;
case ID_GD:
@ -1553,10 +1562,15 @@ static void outliner_draw_tree_element(
if (tselem->type == 0 && tselem->id->lib) {
glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
if (tselem->id->flag & LIB_INDIRECT)
if (tselem->id->flag & LIB_MISSING) {
UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN);
}
else if (tselem->id->flag & LIB_INDIRECT) {
UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT);
else
}
else {
UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT);
}
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
offsx += UI_UNIT_X;
}

View File

@ -261,6 +261,8 @@ typedef struct PreviewImage {
#define ID_BLEND_PATH(_bmain, _id) ((_id)->lib ? (_id)->lib->filepath : (_bmain)->name)
#define ID_MISSING(_id) (((_id)->flag & LIB_MISSING) != 0)
#ifdef GS
# undef GS
#endif
@ -280,6 +282,8 @@ enum {
LIB_TESTIND = (LIB_NEED_EXPAND | LIB_INDIRECT),
LIB_READ = 1 << 4,
LIB_NEED_LINK = 1 << 5,
/* tag datablock as a place-holder (because the real one could not be linked from its library e.g.). */
LIB_MISSING = 1 << 6,
LIB_NEW = 1 << 8,
LIB_FAKEUSER = 1 << 9,