diff options
36 files changed, 944 insertions, 749 deletions
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index e4cd8e39aca..69fb83aac30 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -39,12 +39,18 @@ struct Object; struct PartEff; struct Scene; +typedef struct DupliObject { + struct DupliObject *next, *prev; + struct Object *ob; + float mat[4][4], omat[4][4]; +} DupliObject; + void free_path(struct Path *path); void calc_curvepath(struct Object *ob); int interval_test(int min, int max, int p1, int cycl); int where_on_path(struct Object *ob, float ctime, float *vec, float *dir); -void free_duplilist(void); -void make_duplilist(struct Scene *sce, struct Object *ob); + +ListBase *object_duplilist(struct Scene *sce, struct Object *ob); int count_duplilist(struct Object *ob); #endif diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 5dd820d5a79..294f61e54bd 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -109,5 +109,5 @@ void DAG_scene_flush_update(struct Scene *sce, unsigned int lay); void DAG_object_flush_update(struct Scene *sce, struct Object *ob, short flag); void DAG_pose_sort(struct Object *ob); - + #endif diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 2dcf4bfe1be..05a1cfc5376 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -75,6 +75,7 @@ if( (cyclv) && a==sizev-1) { \ /* prototypes */ +struct Base; struct Object; struct Curve; struct ListBase; @@ -144,7 +145,7 @@ extern void makeDispListMesh(struct Object *ob); extern void makeDispListSurf(struct Object *ob, struct ListBase *dispbase, int forRender); extern void makeDispListCurveTypes(struct Object *ob, int forOrco); extern void makeDispListMBall(struct Object *ob); -extern void shadeDispList(struct Object *ob); +extern void shadeDispList(struct Base *base); void freefastshade(void); void imagestodisplist(void); void reshadeall_displist(void); diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 00a994672be..05621a4d9b2 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -41,6 +41,13 @@ struct Object; struct Curve; struct objfnt; +struct chartrans { + float xof, yof; + float rot; + short linenr,charnr; + char dobreak; +}; + typedef struct SelBox { float x, y, w, h; } SelBox; @@ -55,7 +62,7 @@ struct VFont *load_vfont(char *name); struct chartrans *text_to_curve(struct Object *ob, int mode); int style_to_sel(int style, int toggle); int mat_to_sel(void); -void font_duplilist(struct Object *par); + int getselection(int *start, int *end); void chtoutf8(unsigned long c, char *o); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 2d42a9e284c..db4c83040a8 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -37,15 +37,20 @@ struct Group; struct GroupObject; struct Object; +struct bAction; -void free_group_object(struct GroupObject *go); -void free_group(struct Group *group); +void free_group_object(struct GroupObject *go); +void free_group(struct Group *group); +void unlink_group(struct Group *group); struct Group *add_group(void); -void add_to_group(struct Group *group, struct Object *ob); -void rem_from_group(struct Group *group, struct Object *ob); +void add_to_group(struct Group *group, struct Object *ob); +void rem_from_group(struct Group *group, struct Object *ob); struct Group *find_group(struct Object *ob); -int object_in_group(struct Object *ob, struct Group *group); -void group_tag_recalc(struct Group *group); +int object_in_group(struct Object *ob, struct Group *group); + +void group_tag_recalc(struct Group *group); +void group_handle_recalc_and_update(struct Object *parent, struct Group *group); +struct Object *group_get_member_with_action(struct Group *group, struct bAction *act); #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 04c4d180927..a0713d3a7dd 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1823,8 +1823,6 @@ static void mesh_build_data(Object *ob) Mesh *me = ob->data; float min[3], max[3]; - if(ob->flag&OB_FROMDUPLI) return; - clear_mesh_caches(ob); if(ob!=G.obedit) { diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index d5fa6958dff..211e552f493 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -816,7 +816,7 @@ static void do_nla(Object *ob, int blocktype) actlength = strip->actend-strip->actstart; striptime = (G.scene->r.cfra-(strip->start)) / length; stripframe = (G.scene->r.cfra-(strip->start)) ; - + if (striptime>=0.0){ if(blocktype==ID_AR) @@ -979,6 +979,7 @@ void do_all_pose_actions(Object *ob) void do_all_object_actions(Object *ob) { if(ob==NULL) return; + if(ob->dup_group) return; /* prevent conflicts, might add smarter check later */ /* Do local action */ if(ob->action && ((ob->nlaflag & OB_NLA_OVERRIDE)==0 || ob->nlastrips.first==NULL) ) { diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 5b5f1fabdf2..5700be0fcbc 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -49,17 +49,20 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_view3d_types.h" +#include "DNA_vfont_types.h" +#include "BKE_anim.h" #include "BKE_DerivedMesh.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_font.h" +#include "BKE_group.h" #include "BKE_global.h" -#include "BKE_utildefines.h" -#include "BKE_anim.h" #include "BKE_ipo.h" -#include "BKE_object.h" -#include "BKE_displist.h" #include "BKE_key.h" -#include "BKE_font.h" -#include "BKE_effect.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" #include "BKE_bad_level_calls.h" @@ -272,53 +275,40 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK return 1; } -static Object *new_dupli_object(ListBase *lb, Object *ob, Object *par, int clearpar) -{ - Object *newob; - - newob= MEM_mallocN(sizeof(Object), "newobj dupli"); - - memcpy(newob, ob, sizeof(Object)); - newob->flag |= OB_FROMDUPLI; - newob->id.newid= (ID *)par; /* store duplicator */ - - /* only basis-ball gets displist */ - if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= NULL; +/* ****************** DUPLICATOR ************** */ - if(clearpar) { // dupliverts, particle - newob->parent= NULL; - newob->track= NULL; - } - BLI_addtail(lb, newob); - - return newob; +static void new_dupli_object(ListBase *lb, Object *ob, float mat[][4]) +{ + DupliObject *dob= MEM_mallocN(sizeof(DupliObject), "dupliobject"); + BLI_addtail(lb, dob); + dob->ob= ob; + Mat4CpyMat4(dob->mat, mat); + Mat4CpyMat4(dob->omat, ob->obmat); } -static void group_duplilist(Object *ob) +static void group_duplilist(ListBase *lb, Object *ob) { - Object *newob; GroupObject *go; float mat[4][4]; if(ob->dup_group==NULL) return; + /* handles animated groups, and */ + /* we need to check update for objects that are not in scene... */ + group_handle_recalc_and_update(ob, ob->dup_group); + for(go= ob->dup_group->gobject.first; go; go= go->next) { if(go->ob!=ob) { - /* we need to check update for objects that are not in scene... */ - if(go->ob->recalc) - object_handle_update(go->ob); // bke_object.h - - newob= new_dupli_object(&duplilist, go->ob, ob, 0); - Mat4CpyMat4(mat, newob->obmat); - Mat4MulMat4(newob->obmat, mat, ob->obmat); + Mat4MulMat4(mat, go->ob->obmat, ob->obmat); + new_dupli_object(lb, go->ob, mat); } } } -static void frames_duplilist(Object *ob) +static void frames_duplilist(ListBase *lb, Object *ob) { extern int enable_cu_speed; /* object.c */ - Object *newob, copyob; + Object copyob; int cfrao, ok; cfrao= G.scene->r.cfra; @@ -337,10 +327,9 @@ static void frames_duplilist(Object *ob) else ok= 0; } if(ok) { - newob= new_dupli_object(&duplilist, ob, ob, 0); - - do_ob_ipo(newob); - where_is_object_time(newob, (float)G.scene->r.cfra); + do_ob_ipo(ob); + where_is_object_time(ob, (float)G.scene->r.cfra); + new_dupli_object(lb, ob, ob->obmat); } } @@ -350,6 +339,7 @@ static void frames_duplilist(Object *ob) } struct vertexDupliData { + ListBase *lb; float pmat[4][4]; Object *ob, *par; }; @@ -357,16 +347,15 @@ struct vertexDupliData { static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { struct vertexDupliData *vdd= userData; - Object *newob; - float vec[3], *q2, mat[3][3], tmat[4][4]; + float vec[3], *q2, mat[3][3], tmat[4][4], obmat[4][4]; VECCOPY(vec, co); Mat4MulVecfl(vdd->pmat, vec); VecSubf(vec, vec, vdd->pmat[3]); VecAddf(vec, vec, vdd->ob->obmat[3]); - newob= new_dupli_object(&duplilist, vdd->ob, vdd->par, 1); - VECCOPY(newob->obmat[3], vec); + Mat4CpyMat4(obmat, vdd->ob->obmat); + VECCOPY(obmat[3], vec); if(vdd->par->transflag & OB_DUPLIROT) { @@ -375,13 +364,13 @@ static void vertex_dupli__mapFunc(void *userData, int index, float *co, float *n q2= vectoquat(vec, vdd->ob->trackflag, vdd->ob->upflag); QuatToMat3(q2, mat); - Mat4CpyMat4(tmat, newob->obmat); - Mat4MulMat43(newob->obmat, tmat, mat); + Mat4CpyMat4(tmat, obmat); + Mat4MulMat43(obmat, tmat, mat); } - + new_dupli_object(vdd->lb, vdd->ob, obmat); } -static void vertex_duplilist(Scene *sce, Object *par) +static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par) { Object *ob; Base *base; @@ -411,6 +400,7 @@ static void vertex_duplilist(Scene *sce, Object *par) struct vertexDupliData vdd; ob= base->object; + vdd.lb= lb; vdd.ob= ob; vdd.par= par; Mat4CpyMat4(vdd.pmat, pmat); @@ -442,9 +432,9 @@ static void vertex_duplilist(Scene *sce, Object *par) dm->release(dm); } -static void particle_duplilist(Scene *sce, Object *par, PartEff *paf) +static void particle_duplilist(ListBase *lb, Scene *sce, Object *par, PartEff *paf) { - Object *ob, *newob; + Object *ob, copyob; Base *base; Particle *pa; float ctime, vec1[3]; @@ -460,21 +450,20 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf) } ctime= bsystem_time(par, 0, (float)G.scene->r.cfra, 0.0); - + lay= G.scene->lay; - base= sce->base.first; - while(base) { - + for(base= sce->base.first; base; base= base->next) { if(base->object->type>0 && (base->lay & lay) && G.obedit!=base->object) { ob= base->object->parent; while(ob) { if(ob==par) { ob= base->object; + /* temp copy, to have ipos etc to work OK */ + copyob= *ob; - pa= paf->keys; - for(a=0; a<paf->totpart; a++, pa+=paf->totkey) { + for(a=0, pa= paf->keys; a<paf->totpart; a++, pa+=paf->totkey) { if(paf->flag & PAF_STATIC) { float mtime; @@ -483,13 +472,12 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf) mtime= pa->time+pa->lifetime; for(ctime= pa->time; ctime<mtime; ctime+=paf->staticstep) { - newob= new_dupli_object(&duplilist, ob, par, 1); /* make sure hair grows until the end.. */ if(ctime>pa->time+pa->lifetime) ctime= pa->time+pa->lifetime; /* to give ipos in object correct offset */ - where_is_object_time(newob, ctime-pa->time); + where_is_object_time(ob, ctime-pa->time); where_is_particle(paf, pa, ctime, vec); // makes sure there's always a vec Mat4MulVecfl(par->obmat, vec); @@ -502,11 +490,12 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf) q2= vectoquat(vec1, ob->trackflag, ob->upflag); QuatToMat3(q2, mat); - Mat4CpyMat4(tmat, newob->obmat); - Mat4MulMat43(newob->obmat, tmat, mat); + Mat4CpyMat4(tmat, ob->obmat); + Mat4MulMat43(ob->obmat, tmat, mat); } - VECCOPY(newob->obmat[3], vec); + VECCOPY(ob->obmat[3], vec); + new_dupli_object(lb, ob, ob->obmat); } } else { // non static particles @@ -515,10 +504,9 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf) if((paf->flag & PAF_DIED)==0 && ctime > pa->time+pa->lifetime) continue; //if(ctime < pa->time+pa->lifetime) { - newob= new_dupli_object(&duplilist, ob, par, 1); /* to give ipos in object correct offset */ - where_is_object_time(newob, ctime-pa->time); + where_is_object_time(ob, ctime-pa->time); where_is_particle(paf, pa, ctime, vec); if(paf->stype==PAF_VECT) { @@ -528,56 +516,129 @@ static void particle_duplilist(Scene *sce, Object *par, PartEff *paf) q2= vectoquat(vec1, ob->trackflag, ob->upflag); QuatToMat3(q2, mat); - Mat4CpyMat4(tmat, newob->obmat); - Mat4MulMat43(newob->obmat, tmat, mat); + Mat4CpyMat4(tmat, ob->obmat); + Mat4MulMat43(ob->obmat, tmat, mat); } - VECCOPY(newob->obmat[3], vec); + VECCOPY(ob->obmat[3], vec); + new_dupli_object(lb, ob, ob->obmat); } } + /* temp copy, to have ipos etc to work OK */ + *ob= copyob; + break; } ob= ob->parent; } } - base= base->next; } } -void free_duplilist() +static Object *find_family_object(Object **obar, char *family, char ch) { Object *ob; + int flen; + + if( obar[ch] ) return obar[ch]; - while( (ob= duplilist.first) ) { - BLI_remlink(&duplilist, ob); - MEM_freeN(ob); + flen= strlen(family); + + ob= G.main->object.first; + while(ob) { + if( ob->id.name[flen+2]==ch ) { + if( strncmp(ob->id.name+2, family, flen)==0 ) break; + } + ob= ob->id.next; } + obar[ch]= ob; + + return ob; } -void make_duplilist(Scene *sce, Object *ob) + +static void font_duplilist(ListBase *lb, Object *par) { - PartEff *paf; + Object *ob, *obar[256]; + Curve *cu; + struct chartrans *ct, *chartransdata; + float vec[3], obmat[4][4], pmat[4][4], fsize, xof, yof; + int slen, a; + + Mat4CpyMat4(pmat, par->obmat); + + /* in par the family name is stored, use this to find the other objects */ + + chartransdata= text_to_curve(par, FO_DUPLI); + if(chartransdata==0) return; + + memset(obar, 0, 256*sizeof(void *)); + + cu= par->data; + slen= strlen(cu->str); + fsize= cu->fsize; + xof= cu->xof; + yof= cu->yof; + + ct= chartransdata; + + for(a=0; a<slen; a++, ct++) { + + ob= find_family_object(obar, cu->family, cu->str[a]); + if(ob) { + vec[0]= fsize*(ct->xof - xof); + vec[1]= fsize*(ct->yof - yof); + vec[2]= 0.0; + + Mat4MulVecfl(pmat, vec); + + Mat4CpyMat4(obmat, par->obmat); + VECCOPY(obmat[3], vec); + + new_dupli_object(lb, ob, obmat); + } + + } + + MEM_freeN(chartransdata); +} + +/* ***************************** */ +ListBase *object_duplilist(Scene *sce, Object *ob) +{ + static ListBase duplilist={NULL, NULL}; + + if(duplilist.first) { + printf("wrong call to object_duplilist\n"); + return &duplilist; + } + duplilist.first= duplilist.last= NULL; + if(ob->transflag & OB_DUPLI) { if(ob->transflag & OB_DUPLIVERTS) { if(ob->type==OB_MESH) { if(ob->transflag & OB_DUPLIVERTS) { - if( (paf=give_parteff(ob)) ) particle_duplilist(sce, ob, paf); - else vertex_duplilist(sce, ob); + PartEff *paf; + if( (paf=give_parteff(ob)) ) particle_duplilist(&duplilist, sce, ob, paf); + else vertex_duplilist(&duplilist, sce, ob); } } else if(ob->type==OB_FONT) { - font_duplilist(ob); + font_duplilist(&duplilist, ob); } } else if(ob->transflag & OB_DUPLIFRAMES) - frames_duplilist(ob); + frames_duplilist(&duplilist, ob); else if(ob->transflag & OB_DUPLIGROUP) - group_duplilist(ob); + group_duplilist(&duplilist, ob); } + + return &duplilist; } + int count_duplilist(Object *ob) { if(ob->transflag & OB_DUPLI) { diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 36071d39207..18c8de24feb 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1546,14 +1546,15 @@ static int exists_channel(Object *ob, char *name) return 0; } -static void object_time_update_flags(Object *ob) +static void dag_object_time_update_flags(Object *ob) { if(ob->ipo) ob->recalc |= OB_RECALC_OB; else if(ob->constraints.first) ob->recalc |= OB_RECALC_OB; else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; else if(ob->parent) { - if(ob->parent->type==OB_CURVE) ob->recalc |= OB_RECALC_OB; + /* motion path or bone child */ + if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB; } if(ob->action || ob->nlastrips.first) { @@ -1632,7 +1633,7 @@ void DAG_scene_update_flags(Scene *sce, unsigned int lay) /* now if DagNode were part of base, the node->lay could be checked... */ /* we do all now, since the scene_flush checks layers and clears recalc flags even */ - object_time_update_flags(ob); + dag_object_time_update_flags(ob); /* handled in next loop */ if(ob->dup_group) @@ -1640,16 +1641,28 @@ void DAG_scene_update_flags(Scene *sce, unsigned int lay) } + /* we do groups each once */ for(group= G.main->group.first; group; group= group->id.next) { if(group->id.flag & LIB_DOIT) { for(go= group->gobject.first; go; go= go->next) { - object_time_update_flags(go->ob); + dag_object_time_update_flags(go->ob); } - group->id.flag &= ~LIB_DOIT; } } DAG_scene_flush_update(sce, lay); + + /* and store the info in groubobject */ + for(group= G.main->group.first; group; group= group->id.next) { + if(group->id.flag & LIB_DOIT) { + for(go= group->gobject.first; go; go= go->next) { + go->recalc= go->ob->recalc; +// printf("ob %s recalc %d\n", go->ob->id.name, go->recalc); + } + group->id.flag &= ~LIB_DOIT; + } + } + } /* for depgraph updating, all layers visible in a screen */ diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 219ef69d6d2..c27245fc11e 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -840,8 +840,10 @@ void mesh_create_shadedColors(Object *ob, int onlyForMesh, unsigned int **col1_r } -void shadeDispList(Object *ob) +/* has base pointer, to check for layer */ +void shadeDispList(Base *base) { + Object *ob= base->object; DispList *dl, *dlob; Material *ma = NULL; Curve *cu; @@ -850,8 +852,6 @@ void shadeDispList(Object *ob) unsigned int *col1; int a; - if(ob->flag & OB_FROMDUPLI) return; - dl = find_displist(&ob->disp, DL_VERTCOL); if (dl) { BLI_remlink(&ob->disp, dl); @@ -986,16 +986,13 @@ void reshadeall_displist(void) freefastshade(); - base= G.scene->base.first; - while(base) { + for(base= G.scene->base.first; base; base= base->next) { + ob= base->object; + freedisplist(&ob->disp); if(base->lay & G.scene->lay) { - ob= base->object; - /* Metaballs have standard displist at the Object */ - if(ob->type==OB_MBALL) shadeDispList(ob); - else freedisplist(&ob->disp); + if(ob->type==OB_MBALL) shadeDispList(base); } - base= base->next; } } @@ -1388,7 +1385,7 @@ static float calc_taper(Object *taperobj, int cur, int tot) void makeDispListMBall(Object *ob) { - if(!ob || (ob->flag&OB_FROMDUPLI) || ob->type!=OB_MBALL) return; + if(!ob || ob->type!=OB_MBALL) return; freedisplist(&(ob->disp)); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 2ab13fe328a..b5ed7fb3688 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -73,13 +73,6 @@ struct SelBox *selboxes= NULL; -struct chartrans { - float xof, yof; - float rot; - short linenr,charnr; - char dobreak; -}; - /* UTF-8 <-> wchar transformations */ void chtoutf8(unsigned long c, char *o) @@ -1190,86 +1183,4 @@ struct chartrans *text_to_curve(Object *ob, int mode) return 0; } -/* ***************** DUPLI ***************** */ - -static Object *find_family_object(Object **obar, char *family, char ch) -{ - Object *ob; - int flen; - - if( obar[ch] ) return obar[ch]; - - flen= strlen(family); - - ob= G.main->object.first; - while(ob) { - if( ob->id.name[flen+2]==ch ) { - if( strncmp(ob->id.name+2, family, flen)==0 ) break; - } - ob= ob->id.next; - } - - obar[ch]= ob; - - return ob; -} - - -void font_duplilist(Object *par) -{ - extern ListBase duplilist; - Object *ob, *newob, *obar[256]; - Curve *cu; - struct chartrans *ct, *chartransdata; - float vec[3], pmat[4][4], fsize, xof, yof; - int slen, a; - - Mat4CpyMat4(pmat, par->obmat); - - /* in par the family name is stored, use this to find the other objects */ - - chartransdata= text_to_curve(par, FO_DUPLI); - if(chartransdata==0) return; - - memset(obar, 0, 256*4); - - cu= par->data; - slen= strlen(cu->str); - fsize= cu->fsize; - xof= cu->xof; - yof= cu->yof; - - ct= chartransdata; - - for(a=0; a<slen; a++, ct++) { - - ob= find_family_object(obar, cu->family, cu->str[a]); - if(ob) { - /* not clear if this free line here is still needed */ - freedisplist(&ob->disp); - - vec[0]= fsize*(ct->xof - xof); - vec[1]= fsize*(ct->yof - yof); - vec[2]= 0.0; - - Mat4MulVecfl(pmat, vec); - - newob= MEM_mallocN(sizeof(Object), "newobj dupli"); - memcpy(newob, ob, sizeof(Object)); - newob->flag |= OB_FROMDUPLI; - newob->id.newid= (ID *)par; /* keep duplicator */ - newob->totcol= par->totcol; /* for give_current_material */ - - Mat4CpyMat4(newob->obmat, par->obmat); - VECCOPY(newob->obmat[3], vec); - - newob->parent= 0; - newob->track= 0; - - BLI_addtail(&duplilist, newob); - } - - } - MEM_freeN(chartransdata); -} diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 0ae6208c9de..5e2d0d6fc6d 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -32,19 +32,24 @@ #include "MEM_guardedalloc.h" -#include "DNA_ID.h" +#include "DNA_action_types.h" +#include "DNA_effect_types.h" #include "DNA_group_types.h" -#include "DNA_object_types.h" +#include "DNA_ID.h" #include "DNA_ipo_types.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_nla_types.h" +#include "DNA_scene_types.h" #include "BLI_blenlib.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_library.h" +#include "BKE_global.h" #include "BKE_group.h" -#include "BKE_object.h" #include "BKE_ipo.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_object.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -68,6 +73,34 @@ void free_group(Group *group) } } +void unlink_group(Group *group) +{ + Material *ma; + Object *ob; + + for(ma= G.main->mat.first; ma; ma= ma->id.next) { + if(ma->group==group) + ma->group= NULL; + } + for(ob= G.main->object.first; ob; ob= ob->id.next) { + bActionStrip *strip; + PartEff *paf; + + if(ob->dup_group==group) + ob->dup_group= NULL; + for(strip= ob->nlastrips.first; strip; strip= strip->next) { + if(strip->object==ob) + strip->object= NULL; + } + for(paf= ob->effect.first; paf; paf= paf->next) { + if(paf->type==EFF_PARTICLE) { + if(paf->group) + paf->group= NULL; + } + } + } +} + Group *add_group() { Group *group; @@ -150,3 +183,109 @@ void group_tag_recalc(Group *group) } } +/* only replaces object strips or action when parent nla instructs it */ +/* keep checking nla.c though, in case internal structure of strip changes */ +static void group_replaces_nla(Object *parent, Object *target, char mode) +{ + static ListBase nlastrips={NULL, NULL}; + static bAction *action= NULL; + static int done= 0; + bActionStrip *strip, *nstrip; + + if(mode=='s') { + + for(strip= parent->nlastrips.first; strip; strip= strip->next) { + if(strip->object==target) { + if(done==0) { + /* clear nla & action from object */ + nlastrips= target->nlastrips; + target->nlastrips.first= target->nlastrips.last= NULL; + action= target->action; + target->action= NULL; + target->nlaflag |= OB_NLA_OVERRIDE; + done= 1; + } + nstrip= MEM_dupallocN(strip); + BLI_addtail(&target->nlastrips, nstrip); + } + } + } + else if(mode=='e') { + if(done) { + BLI_freelistN(&target->nlastrips); + target->nlastrips= nlastrips; + target->action= action; + + nlastrips.first= nlastrips.last= NULL; /* not needed, but yah... :) */ + action= NULL; + done= 0; + } + } +} + + +/* puts all group members in local timing system, after this call +you can draw everything, leaves tags in objects to signal it needs further updating */ +void group_handle_recalc_and_update(Object *parent, Group *group) +{ + GroupObject *go; + + /* if animated group... */ + if(parent->sf != 0.0f || parent->nlastrips.first) { + int cfrao; + + /* switch to local time */ + cfrao= G.scene->r.cfra; + G.scene->r.cfra -= (int)parent->sf; + + /* we need a DAG per group... */ + for(go= group->gobject.first; go; go= go->next) { + if(go->ob && go->recalc) { + go->ob->recalc= go->recalc; + + group_replaces_nla(parent, go->ob, 's'); + object_handle_update(go->ob); + group_replaces_nla(parent, go->ob, 'e'); + + /* leave recalc tags in case group members are in normal scene */ + go->ob->recalc= go->recalc; + } + } + + /* restore */ + G.scene->r.cfra= cfrao; + } + else { + /* only do existing tags, as set by regular depsgraph */ + for(go= group->gobject.first; go; go= go->next) { + if(go->ob) { + if(go->ob->recalc) { + object_handle_update(go->ob); + } + } + } + } +} + +Object *group_get_member_with_action(Group *group, bAction *act) +{ + GroupObject *go; + + if(group==NULL || act==NULL) return NULL; + + for(go= group->gobject.first; go; go= go->next) { + if(go->ob) { + if(go->ob->action==act) + return go->ob; + if(go->ob->nlastrips.first) { + bActionStrip *strip; + + for(strip= go->ob->nlastrips.first; strip; strip= strip->next) { + if(strip->act==act) + return go->ob; + } + } + } + } + return NULL; +} diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index ea1608d8a18..09408e4a220 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -1437,11 +1437,12 @@ float init_meta(Object *ob) /* return totsize */ Object *bob; MetaBall *mb; MetaElem *ml; - float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], vec[3]; + float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], obmat[4][4], vec[3]; float temp1[4][4], temp2[4][4], temp3[4][4]; //max=0.0; int a, obnr, zero_size=0; char obname[32]; + Mat4CpyMat4(obmat, ob->obmat); /* to cope with duplicators from next_object */ Mat4Invert(obinv, ob->obmat); a= 0; @@ -1456,7 +1457,7 @@ float init_meta(Object *ob) /* return totsize */ zero_size= 0; ml= NULL; - if(bob==ob) { + if(bob==ob && (base->flag & OB_FROMDUPLI)==0) { mat= imat= 0; mb= ob->data; @@ -1471,7 +1472,6 @@ float init_meta(Object *ob) /* return totsize */ splitIDname(bob->id.name+2, name, &nr); if( strcmp(obname, name)==0 ) { mb= bob->data; - if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) ml= editelems.first; else ml= mb->elems.first; @@ -1535,7 +1535,7 @@ float init_meta(Object *ob) /* return totsize */ imat= new_pgn_element(4*4*sizeof(float)); /* mat is the matrix to transform from mball into the basis-mball */ - Mat4Invert(obinv, ob->obmat); + Mat4Invert(obinv, obmat); Mat4MulMat4(temp2, bob->obmat, obinv); /* MetaBall transformation */ Mat4MulMat4(mat, temp1, temp2); diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 5adde76accc..5fefc41f77c 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -46,6 +46,9 @@ #include <config.h> #endif +/* NOTE: in group.c the strips get copied for group-nla override, this assumes + that strips are one single block, without additional data to be copied */ + void copy_actionstrip (bActionStrip **dst, bActionStrip **src){ bActionStrip *dstrip; bActionStrip *sstrip = *src; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7af6ef21e32..e7cf3577a99 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -208,6 +208,7 @@ void free_object(Object *ob) ob->path= 0; if(ob->ipo) ob->ipo->id.us--; if(ob->action) ob->action->id.us--; + if(ob->dup_group) ob->dup_group->id.us--; if(ob->defbase.first) BLI_freelistN(&ob->defbase); if(ob->pose) { @@ -255,6 +256,7 @@ void unlink_object(Object *ob) Ipo *ipo; Group *group; bConstraint *con; + bActionStrip *strip; int a; char *str; @@ -315,6 +317,7 @@ void unlink_object(Object *ob) obt->recalc |= OB_RECALC_OB; } } + /* object is deflector or field */ if(ob->pd) { if(give_parteff(obt)) @@ -322,6 +325,12 @@ void unlink_object(Object *ob) else if(obt->soft) obt->recalc |= OB_RECALC_DATA; } + + /* strips */ + for(strip= ob->nlastrips.first; strip; strip= strip->next) { + if(strip->object==ob) + strip->object= NULL; + } } obt= obt->id.next; } @@ -999,15 +1008,10 @@ float bsystem_time(Object *ob, Object *par, float cfra, float ofs) if(R.r.mode & R_FIELDSTILL); else cfra+= .5; } + cfra+= bluroffs; - if(ob && (ob->flag & OB_FROMDUPLI)); - else { - /* motion blur */ - cfra+= bluroffs; - - /* global time */ - cfra*= G.scene->r.framelen; - } + /* global time */ + cfra*= G.scene->r.framelen; if(no_speed_curve==0) if(ob && ob->ipo) cfra= calc_ipo_time(ob->ipo, cfra); @@ -1522,9 +1526,6 @@ void solve_tracking (Object *ob, float targetmat[][4]) void where_is_object(Object *ob) { - /* these have been mem copied */ - if(ob->flag & OB_FROMDUPLI) return; - where_is_object_time(ob, (float)G.scene->r.cfra); } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index fd0a6288dbe..df9e626abbf 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -76,7 +76,7 @@ #include "BKE_utildefines.h" #include "BPY_extern.h" - +#include "BLI_arithb.h" #include "BLI_blenlib.h" #include "nla.h" @@ -277,13 +277,10 @@ void set_scene_bg(Scene *sce) ob->flag= base->flag; - ob->recalc= OB_RECALC; - if(ob->dup_group) group_tag_recalc(ob->dup_group); /* for lib-linked stuff */ - ob->ctime= -1234567.0; /* force ipo to be calculated later */ base= base->next; } - // full update + // full animation update scene_update_for_newframe(sce, sce->lay); /* do we need FRAMECHANGED in set_scene? */ @@ -309,23 +306,21 @@ void set_scene_name(char *name) */ int next_object(int val, Base **base, Object **ob) { - extern ListBase duplilist; - static Object *dupob; + static ListBase *duplilist= NULL; + static DupliObject *dupob; static int fase; int run_again=1; /* init */ if(val==0) { fase= F_START; - dupob= 0; + dupob= NULL; } else { /* run_again is set when a duplilist has been ended */ while(run_again) { run_again= 0; - - /* the first base */ if(fase==F_START) { @@ -360,30 +355,40 @@ int next_object(int val, Base **base, Object **ob) } } - if(*base == 0) fase= F_START; + if(*base == NULL) fase= F_START; else { if(fase!=F_DUPLI) { if( (*base)->object->transflag & OB_DUPLI) { - make_duplilist(G.scene, (*base)->object); - dupob= duplilist.first; + duplilist= object_duplilist(G.scene, (*base)->object); + + dupob= duplilist->first; } } /* handle dupli's */ if(dupob) { - *ob= dupob; + Mat4CpyMat4(dupob->ob->obmat, dupob->mat); + + (*base)->flag |= OB_FROMDUPLI; + *ob= dupob->ob; fase= F_DUPLI; - dupob= dupob->id.next; + dupob= dupob->next; } else if(fase==F_DUPLI) { fase= F_SCENE; - free_duplilist(); + (*base)->flag &= ~OB_FROMDUPLI; + + for(dupob= duplilist->first; dupob; dupob= dupob->next) { + Mat4CpyMat4(dupob->ob->obmat, dupob->omat); + } + + BLI_freelistN(duplilist); + duplilist= NULL; run_again= 1; } - } } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index aef5f82f6f6..f8185b229ae 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1254,6 +1254,7 @@ static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist) bActionStrip *strip; for (strip=striplist->first; strip; strip=strip->next){ + strip->object = newlibadr(fd, id->lib, strip->object); strip->act = newlibadr_us(fd, id->lib, strip->act); strip->ipo = newlibadr(fd, id->lib, strip->ipo); } @@ -3155,24 +3156,28 @@ static void lib_link_group(FileData *fd, Main *main) { Group *group= main->group.first; GroupObject *go; - + int add_us; + while(group) { if(group->id.flag & LIB_NEEDLINK) { group->id.flag -= LIB_NEEDLINK; - + + add_us= 0; + go= group->gobject.first; while(go) { go->ob= newlibadr(fd, group->id.lib, go->ob); if(go->ob) { - /* groups have inverse users... */ - if(group->id.us==0) - group->id.us= 1; + /* if group has an object, it increments user... */ + add_us= 1; if(go->ob->id.us==0) go->ob->id.us= 1; } go= go->next; } + if(add_us) group->id.us++; rem_from_group(group, NULL); /* removes NULL entries */ + } group= group->id.next; } @@ -5580,6 +5585,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) expand_constraint_channels(fd, mainvar, &ob->constraintChannels); for (strip=ob->nlastrips.first; strip; strip=strip->next){ + expand_doit(fd, mainvar, strip->object); expand_doit(fd, mainvar, strip->act); expand_doit(fd, mainvar, strip->ipo); } diff --git a/source/blender/include/BIF_outliner.h b/source/blender/include/BIF_outliner.h index 1a33b3d0810..442247864b5 100644 --- a/source/blender/include/BIF_outliner.h +++ b/source/blender/include/BIF_outliner.h @@ -62,7 +62,7 @@ typedef struct TreeElement { #define TSE_CONSTRAINT 8 #define TSE_MODIFIER_BASE 9 #define TSE_MODIFIER 10 -#define TSE_MODIFIER_OB 11 +#define TSE_LINKED_OB 11 #define TSE_SCRIPT_BASE 12 #define TSE_POSE_BASE 13 #define TSE_POSE_CHANNEL 14 diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index b0e40699f42..4a9876705e6 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -46,6 +46,9 @@ void circ(float x, float y, float rad); void do_viewbuts(unsigned short event); +/* View3DAfter->type */ +#define V3D_XRAY 1 +#define V3D_TRANSP 2 void add_view3d_after(struct View3D *v3d, struct Base *base, int type); void backdrawview3d(int test); diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h index 2ee699839ed..09ecc3a68c1 100644 --- a/source/blender/makesdna/DNA_group_types.h +++ b/source/blender/makesdna/DNA_group_types.h @@ -43,6 +43,8 @@ typedef struct GroupObject { struct GroupObject *next, *prev; struct Object *ob; void *lampren; /* used while render */ + int recalc; /* copy of ob->recalc, used to set animated groups OK */ + int pad; } GroupObject; diff --git a/source/blender/makesdna/DNA_nla_types.h b/source/blender/makesdna/DNA_nla_types.h index bf3d7820dae..fa1a4fbe456 100644 --- a/source/blender/makesdna/DNA_nla_types.h +++ b/source/blender/makesdna/DNA_nla_types.h @@ -35,6 +35,7 @@ struct bAction; struct Ipo; +struct Object; typedef struct bActionStrip { struct bActionStrip *next, *prev; @@ -43,7 +44,7 @@ typedef struct bActionStrip { struct Ipo *ipo; /* Blending ipo */ struct bAction *act; /* The action referenced by this strip */ - + struct Object *object; /* For groups, the actual object being nla'ed */ float start, end; /* The range of frames covered by this strip */ float actstart, actend; /* The range of frames taken from the action */ float stridelen; /* The stridelength (considered when flag & ACT_USESTRIDE) */ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index bf4f44a421d..3e1628a658c 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -63,18 +63,6 @@ typedef struct BGpic { unsigned int *rect; } BGpic; -# -# -typedef struct View3DAfter { - struct View3DAfter *next, *prev; - struct Base *base; - int type; -} View3DAfter; - -/* View3DAfter->type */ -#define V3D_XRAY 1 -#define V3D_TRANSP 2 - typedef struct View3D { struct SpaceLink *next, *prev; int spacetype; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 0d6e141df5f..f5b14fccaed 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2518,6 +2518,7 @@ void *shadepixel(float x, float y, int z, int facenr, int mask, float *col, floa VECADD(col, shr.diff, shr.spec); + /* NOTE: this is not correct here, sky from raytrace gets corrected... */ /* exposure correction */ if(R.wrld.exp!=0.0 || R.wrld.range!=1.0) { if((shi.mat->mode & MA_SHLESS)==0) { diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c index 3b694813e91..f50a95bcbc9 100644 --- a/source/blender/renderconverter/intern/convertBlenderScene.c +++ b/source/blender/renderconverter/intern/convertBlenderScene.c @@ -2683,7 +2683,7 @@ extern ListBase duplilist; void RE_rotateBlenderScene(void) { Base *base; - Object *ob, *obd; + Object *ob; Scene *sce; unsigned int lay; float mat[4][4]; @@ -2776,6 +2776,7 @@ void RE_rotateBlenderScene(void) if( (base->lay & lay) || (ob->type==OB_LAMP && (base->lay & G.scene->lay)) ) { if(ob->transflag & OB_DUPLI) { + /* exception: mballs! */ /* yafray: Include at least one copy of a dupliframe object for yafray in the renderlist. mballs comment above true as well for yafray, they are not included, only all other object types */ @@ -2793,28 +2794,17 @@ void RE_rotateBlenderScene(void) } } - make_duplilist(sce, ob); if(ob->type==OB_MBALL) { init_render_object(ob); } else { - obd= duplilist.first; - if(obd) { - /* exception, in background render it doesnt make the displist */ - if ELEM(obd->type, OB_CURVE, OB_SURF) { - Curve *cu; - - cu= obd->data; - if(cu->disp.first==NULL) { - obd->flag &= ~OB_FROMDUPLI; - makeDispListCurveTypes(obd, 0); - obd->flag |= OB_FROMDUPLI; - } - } - } - - obd= duplilist.first; - while(obd) { + DupliObject *dob; + ListBase *lb= object_duplilist(sce, ob); + + for(dob= lb->first; dob; dob= dob->next) { + Object *obd= dob->ob; + Mat4CpyMat4(obd->obmat, dob->mat); + if(obd->type!=OB_MBALL) { /* yafray: special handling of duplivert objects for yafray: only the matrix is stored, together with the source object name. @@ -2829,10 +2819,10 @@ void RE_rotateBlenderScene(void) } else init_render_object(obd); } - obd= obd->id.next; + Mat4CpyMat4(obd->obmat, dob->omat); } + BLI_freelistN(lb); } - free_duplilist(); } else { /* yafray: if there are linked data objects (except lamps, empties or armatures), diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c index 752e831c2b4..43813f7f907 100644 --- a/source/blender/src/butspace.c +++ b/source/blender/src/butspace.c @@ -117,6 +117,7 @@ void test_actionpoin_but(char *name, ID **idpp) id= G.main->action.first; while(id) { if( strcmp(name, id->name+2)==0 ) { + id_lib_extern(id); /* checks lib data, sets correct flag for saving then */ *idpp= id; return; } @@ -140,6 +141,7 @@ void test_obpoin_but(char *name, ID **idpp) while(id) { if( strcmp(name, id->name+2)==0 ) { *idpp= id; + id_lib_extern(id); /* checks lib data, sets correct flag for saving then */ return; } id= id->next; diff --git a/source/blender/src/drawnla.c b/source/blender/src/drawnla.c index 2b0ba1a7ad3..bb6e77bc507 100644 --- a/source/blender/src/drawnla.c +++ b/source/blender/src/drawnla.c @@ -79,6 +79,7 @@ #include "BDR_editcurve.h" #include "blendef.h" +#include "butspace.h" #include "mydevice.h" #define TESTBASE_SAFE(base) ((base)->flag & SELECT) @@ -460,8 +461,8 @@ static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES /* first labels, for simpler align code :) */ uiDefBut(block, LABEL, 0, "Timeline Range:", 10,180,300,19, 0, 0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Blending:", 10,120,300,19, 0, 0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Options:", 10,80,300,19, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Blending:", 10,120,150,19, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Options:", 160,120,150,19, 0, 0, 0, 0, 0, ""); uiDefBut(block, LABEL, 0, "Stride Support:", 10,40,300,19, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); @@ -482,13 +483,18 @@ static void nla_panel_properties(short cntrl) // NLA_HANDLER_PROPERTIES } uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NLA_PANEL, "Blendin:", 10,100,150,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in"); - uiDefButF(block, NUM, B_NLA_PANEL, "Blendout:", 160,100,150,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out"); + uiDefButF(block, NUM, B_NLA_PANEL, "Blendin:", 10,100,156,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in"); + uiDefButF(block, NUM, B_NLA_PANEL, "Blendout:", 10,80,145,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out"); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_NLA_PANEL, "Repeat:", 10,60,150,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat"); - uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold", 160,60,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip"); - uiDefButS(block, TOG, B_NLA_PANEL, "Add", 230,60,75,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode"); + uiDefButF(block, NUM, B_NLA_PANEL, "Repeat:", 160,100,150,19, &strip->repeat, 0.001, 1000.0f, 100, 0, "Number of times the action should repeat"); + uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold", 160,80,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip"); + uiDefButS(block, TOG, B_NLA_PANEL, "Add", 235,80,75,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode"); + uiBlockEndAlign(block); + + if(ob->dup_group) { + uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_NLA_PANEL, "Target:", 160, 50, 150, 19, &strip->object, "Target Object in this group"); + } uiBlockBeginAlign(block); uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_NLA_PANEL, "Stride Path", 10,20,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride"); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 10fdbee4dba..b4bdd066ed4 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -158,7 +158,7 @@ static int set_gl_material(int nr) } /* returns 1: when there's alpha needed to be drawn in a 2nd pass */ -static int init_gl_materials(Object *ob) +static int init_gl_materials(Object *ob, int check_alpha) { extern Material defmaterial; // render module abuse... Material *ma; @@ -189,7 +189,7 @@ static int init_gl_materials(Object *ob) matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; /* draw transparent, not in pick-select, nor editmode */ - if(!(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) { + if(check_alpha && !(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) { if(G.vd->transp) { // drawing the transparent pass if(ma->alpha==1.0) matbuf[a][0][3]= 0.0; // means skip solid else matbuf[a][0][3]= ma->alpha; @@ -1754,8 +1754,9 @@ static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmoot return 1; } -static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, int dt) +static void draw_mesh_fancy(Base *base, DerivedMesh *baseDM, DerivedMesh *dm, int dt) { + Object *ob= base->object; Mesh *me = ob->data; Material *ma= give_current_material(ob, 1); int hasHaloMat = (ma && (ma->mode&MA_HALO)); @@ -1780,7 +1781,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in } else if( (ob==OBACT && (G.f & G_FACESELECT)) || (G.vd->drawtype==OB_TEXTURE && dt>OB_SOLID)) { - if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !(G.f&(G_FACESELECT|G_PICKSEL)) && !draw_wire) { + if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !(G.f&(G_FACESELECT|G_PICKSEL)) && !draw_wire) { draw_mesh_object_outline(ob, dm); } @@ -1788,7 +1789,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in } else if(dt==OB_SOLID ) { - if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) { + if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { draw_mesh_object_outline(ob, dm); } @@ -1802,7 +1803,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in glFrontFace(GL_CCW); glDisable(GL_LIGHTING); - if(ob->flag & SELECT) { + if(base->flag & SELECT) { BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT); } else { BIF_ThemeColor(TH_WIRE); @@ -1836,11 +1837,11 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in else { dl = ob->disp.first; if (!dl || !dl->col1) { - shadeDispList(ob); + shadeDispList(base); dl = find_displist(&ob->disp, DL_VERTCOL); } - if ((G.vd->flag&V3D_SELECT_OUTLINE) && (ob->flag&SELECT) && !draw_wire) { + if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { draw_mesh_object_outline(ob, dm); } @@ -1852,7 +1853,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in dm->drawFacesColored(dm, me->flag&ME_TWOSIDED, (unsigned char*) obCol1, (unsigned char*) obCol2); } - if(ob->flag & SELECT) { + if(base->flag & SELECT) { BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT); } else { BIF_ThemeColor(TH_WIRE); @@ -1866,7 +1867,7 @@ static void draw_mesh_fancy(Object *ob, DerivedMesh *baseDM, DerivedMesh *dm, in * overlaying the wires. */ if (dt!=OB_WIRE) { - if(ob->flag & SELECT) { + if(base->flag & SELECT) { BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT); } else { BIF_ThemeColor(TH_WIRE); @@ -1914,7 +1915,7 @@ static int draw_mesh_object(Base *base, int dt) cageDM = editmesh_get_derived_cage_and_final(&finalDM, &cageNeedsFree, &finalNeedsFree); } - if(dt>OB_WIRE) init_gl_materials(ob); // no transp in editmode, the fancy draw over goes bad then + if(dt>OB_WIRE) init_gl_materials(ob, 0); // no transp in editmode, the fancy draw over goes bad then draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt); if (cageNeedsFree) cageDM->release(cageDM); @@ -1928,8 +1929,8 @@ static int draw_mesh_object(Base *base, int dt) DerivedMesh *baseDM = mesh_get_derived_deform(ob, &baseDMneedsFree); DerivedMesh *realDM = mesh_get_derived_final(ob, &realDMneedsFree); - if(dt==OB_SOLID) has_alpha= init_gl_materials(ob); - if(baseDM && realDM) draw_mesh_fancy(ob, baseDM, realDM, dt); + if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0); + if(baseDM && realDM) draw_mesh_fancy(base, baseDM, realDM, dt); if(me->totvert==0) retval= 1; @@ -2352,8 +2353,9 @@ static void drawDispListshaded(ListBase *lb, Object *ob) } /* returns 1 when nothing was drawn */ -static int drawDispList(Object *ob, int dt) +static int drawDispList(Base *base, int dt) { + Object *ob= base->object; ListBase *lb=0; DispList *dl; Curve *cu; @@ -2382,11 +2384,11 @@ static int drawDispList(Object *ob, int dt) } else { if(dt==OB_SHADED) { - if(ob->disp.first==0) shadeDispList(ob); + if(ob->disp.first==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob); + init_gl_materials(ob, 0); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); drawDispListsolid(lb, ob); } @@ -2416,11 +2418,11 @@ static int drawDispList(Object *ob, int dt) if(dl->nors==NULL) addnormalsDispList(ob, lb); if(dt==OB_SHADED) { - if(ob->disp.first==NULL) shadeDispList(ob); + if(ob->disp.first==NULL) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob); + init_gl_materials(ob, 0); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); drawDispListsolid(lb, ob); @@ -2441,11 +2443,11 @@ static int drawDispList(Object *ob, int dt) if(dt==OB_SHADED) { dl= lb->first; - if(dl && dl->col1==0) shadeDispList(ob); + if(dl && dl->col1==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob); + init_gl_materials(ob, 0); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); drawDispListsolid(lb, ob); @@ -2789,15 +2791,16 @@ static void draw_editnurb(Object *ob, Nurb *nurb, int sel) } } -static void drawnurb(Object *ob, Nurb *nurb, int dt) +static void drawnurb(Base *base, Nurb *nurb, int dt) { + Object *ob= base->object; Curve *cu = ob->data; Nurb *nu; BevList *bl; /* DispList */ BIF_ThemeColor(TH_WIRE); - drawDispList(ob, dt); + drawDispList(base, dt); if(G.vd->zbuf) glDisable(GL_DEPTH_TEST); @@ -3066,8 +3069,9 @@ void drawcircball(int mode, float *cent, float rad, float tmat[][4]) } /* return 1 if nothing was drawn */ -static int drawmball(Object *ob, int dt) +static int drawmball(Base *base, int dt) { + Object *ob= base->object; MetaBall *mb; MetaElem *ml; float imat[4][4], tmat[4][4]; @@ -3077,11 +3081,12 @@ static int drawmball(Object *ob, int dt) if(ob==G.obedit) { BIF_ThemeColor(TH_WIRE); - if((G.f & G_PICKSEL)==0 ) drawDispList(ob, dt); + if((G.f & G_PICKSEL)==0 ) drawDispList(base, dt); ml= editelems.first; } else { - drawDispList(ob, dt); + if((base->flag & OB_FROMDUPLI)==0) + drawDispList(base, dt); ml= mb->elems.first; } @@ -3406,7 +3411,8 @@ static void drawSolidSelect(Base *base) drawDispListwire(&cu->disp); } } else if (ob->type==OB_MBALL) { - drawDispListwire(&ob->disp); + if((base->flag & OB_FROMDUPLI)==0) + drawDispListwire(&ob->disp); } else if(ob->type==OB_ARMATURE) { if(!(ob->flag & OB_POSEMODE)) { @@ -3495,7 +3501,7 @@ void draw_object(Base *base, int flag) ob= base->object; /* xray delay? */ - if((flag & DRAW_PICKING)==0 && (ob->flag & OB_FROMDUPLI)==0) { + if((flag & DRAW_PICKING)==0 && (base->flag & OB_FROMDUPLI)==0) { /* xray and transp are set when it is drawing the 2nd/3rd pass */ if(!G.vd->xray && !G.vd->transp && (ob->dtx & OB_DRAWXRAY)) { add_view3d_after(G.vd, base, V3D_XRAY); @@ -3703,10 +3709,10 @@ void draw_object(Base *base, int flag) if (cu->flag & CU_FAST) { cpack(0xFFFFFF); set_inverted_drawing(1); - drawDispList(ob, OB_WIRE); + drawDispList(base, OB_WIRE); set_inverted_drawing(0); } else { - drawDispList(ob, dt); + drawDispList(base, dt); } if (cu->linewidth != 0.0) { @@ -3781,7 +3787,7 @@ void draw_object(Base *base, int flag) else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob); else if(boundbox_clip(ob->obmat, cu->bb)) - empty_object= drawDispList(ob, dt); + empty_object= drawDispList(base, dt); break; case OB_CURVE: @@ -3791,21 +3797,21 @@ void draw_object(Base *base, int flag) if (cu->disp.first==NULL) makeDispListCurveTypes(ob, 0); if(ob==G.obedit) { - drawnurb(ob, editNurb.first, dt); + drawnurb(base, editNurb.first, dt); } else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob); else if(boundbox_clip(ob->obmat, cu->bb)) - empty_object= drawDispList(ob, dt); + empty_object= drawDispList(base, dt); break; case OB_MBALL: if(ob==G.obedit) - drawmball(ob, dt); + drawmball(base, dt); else if(dt==OB_BOUNDBOX) draw_bounding_volume(ob); else - empty_object= drawmball(ob, dt); + empty_object= drawmball(base, dt); break; case OB_EMPTY: drawaxes(1.0, flag); @@ -4155,7 +4161,7 @@ void draw_object_instance(Object *ob, int dt, int outline) draw_mesh_object_outline(ob, dm?dm:edm); if(dm) - init_gl_materials(ob); + init_gl_materials(ob, 0); else { glEnable(GL_COLOR_MATERIAL); BIF_ThemeColor(TH_BONE_SOLID); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index dcb5e391046..87bdb5f8e1f 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -122,7 +122,6 @@ #include "BSE_view.h" #include "RE_renderconverter.h" - #include "BPY_extern.h" #include "blendef.h" @@ -2046,6 +2045,14 @@ static void view3d_blockhandlers(ScrArea *sa) } +/* ****************** View3d afterdraw *************** */ + +typedef struct View3DAfter { + struct View3DAfter *next, *prev; + struct Base *base; + int type; +} View3DAfter; + /* temp storage of Objects that need to be drawn as last */ void add_view3d_after(View3D *v3d, Base *base, int type) { @@ -2103,6 +2110,41 @@ static void view3d_draw_transp(View3D *v3d, int flag) } +/* *********************** */ + +static void draw_dupli_objects(View3D *v3d, Base *base) +{ + ListBase *lb; + DupliObject *dob; + Base tbase; + int color= (base->flag & SELECT)?TH_SELECT:TH_WIRE; + char dt, dtx; + + tbase.flag= OB_FROMDUPLI|base->flag; + lb= object_duplilist(G.scene, base->object); + + for(dob= lb->first; dob; dob= dob->next) { + tbase.object= dob->ob; + + Mat4CpyMat4(dob->ob->obmat, dob->mat); + /* extra service: draw the duplicator in drawtype of parent */ + dt= tbase.object->dt; tbase.object->dt= base->object->dt; + dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx; + + BIF_ThemeColorBlend(color, TH_BACK, 0.5); + draw_object(&tbase, DRAW_CONSTCOLOR); + + /* restore */ + Mat4CpyMat4(dob->ob->obmat, dob->omat); + tbase.object->dt= dt; + tbase.object->dtx= dtx; + } + /* Transp afterdraw disabled, afterdraw only stores base pointers, and duplis can be same obj */ + + BLI_freelistN(lb); + +} + void drawview3dspace(ScrArea *sa, void *spacedata) { View3D *v3d= spacedata; @@ -2203,26 +2245,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata) draw_object(base, DRAW_CONSTCOLOR); if(base->object->transflag & OB_DUPLI) { - extern ListBase duplilist; - Base tbase; - - tbase= *base; - - tbase.flag= OB_FROMDUPLI; - make_duplilist(G.scene->set, base->object); - ob= duplilist.first; - while(ob) { - tbase.object= ob; - BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.4f); - draw_object(&tbase, DRAW_CONSTCOLOR); - ob= ob->id.next; - } - - /* Transp afterdraw */ - view3d_draw_transp(v3d, DRAW_CONSTCOLOR); - - free_duplilist(); - + draw_dupli_objects(v3d, base); } } base= base->next; @@ -2244,23 +2267,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata) /* dupli drawing */ if(base->object->transflag & OB_DUPLI) { - extern ListBase duplilist; - Base tbase; - - tbase.flag= OB_FROMDUPLI; - make_duplilist(G.scene, base->object); - - ob= duplilist.first; - while(ob) { - tbase.object= ob; - BIF_ThemeColorBlend(TH_BACK, TH_WIRE, 0.5); - draw_object(&tbase, DRAW_CONSTCOLOR); - ob= ob->id.next; - } - /* Transp afterdraw stuff */ - view3d_draw_transp(v3d, DRAW_CONSTCOLOR); - - free_duplilist(); + draw_dupli_objects(v3d, base); } if((base->flag & SELECT)==0) { if(base->object!=G.obedit) draw_object(base, 0); @@ -2348,7 +2355,6 @@ void drawview3d_render(struct View3D *v3d) { extern short v3d_windowmode; Base *base; - Object *ob; update_for_newframe_muted(); /* first, since camera can be animated */ @@ -2405,21 +2411,7 @@ void drawview3d_render(struct View3D *v3d) draw_object(base, DRAW_CONSTCOLOR); if(base->object->transflag & OB_DUPLI) { - extern ListBase duplilist; - Base tbase; - - tbase.flag= OB_FROMDUPLI; - make_duplilist(G.scene->set, base->object); - ob= duplilist.first; - while(ob) { - tbase.object= ob; - draw_object(&tbase, DRAW_CONSTCOLOR); - ob= ob->id.next; - } - /* Transp afterdraw stuff */ - view3d_draw_transp(v3d, DRAW_CONSTCOLOR); - - free_duplilist(); + draw_dupli_objects(v3d, base); } } } @@ -2440,26 +2432,7 @@ void drawview3d_render(struct View3D *v3d) else { if(base->object->transflag & OB_DUPLI) { - extern ListBase duplilist; - Base tbase; - - draw_object(base, 0); - - BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5f); - - tbase.flag= OB_FROMDUPLI; - make_duplilist(G.scene, base->object); - ob= duplilist.first; - while(ob) { - tbase.object= ob; - draw_object(&tbase, DRAW_CONSTCOLOR); - ob= ob->id.next; - } - - /* Transp afterdraw stuff */ - view3d_draw_transp(v3d, DRAW_CONSTCOLOR); - - free_duplilist(); + draw_dupli_objects(v3d, base); } else if((base->flag & SELECT)==0) { draw_object(base, 0); diff --git a/source/blender/src/editgroup.c b/source/blender/src/editgroup.c index f946a952b5b..67d6701b13e 100644 --- a/source/blender/src/editgroup.c +++ b/source/blender/src/editgroup.c @@ -112,6 +112,11 @@ void group_operation_with_menu(void) } } + if(group && group->id.lib) { + error("Cannot edit library data"); + return; + } + if(base) mode= pupmenu("Groups %t|Add to current Group %x3|Add to New Group %x1|Remove from all Groups %x2"); else diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index ea7821bc977..e05d3b149ff 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -1,15 +1,12 @@ /** -* $Id$ -* - * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * $Id$ + * + * ***** BEGIN GPL BLOCK ***** * * 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. The Blender - * Foundation also sells licenses for use in proprietary software under - * the Blender License. See http://www.blender.org/BL/ for information - * about this. + * 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 @@ -27,11 +24,12 @@ * * Contributor(s): none yet. * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** -* This file is a horrible mess: An attmept to cram some -* final functionality into blender before it is too late. -* -* Hopefully it can be tidied up at a later date... + * ***** END GPL ***** + * + * This file is a horrible mess: An attmept to cram some + * final functionality into blender before it is too late. + * + * Hopefully it can be tidied up at a later date... */ #include <stdlib.h> @@ -57,6 +55,7 @@ #include "BKE_action.h" #include "BKE_depsgraph.h" +#include "BKE_group.h" #include "BKE_global.h" #include "BKE_ipo.h" #include "BKE_library.h" @@ -97,7 +96,6 @@ static Base *get_nearest_nlachannel_ob_key (float *index, short *sel); static bAction *get_nearest_nlachannel_ac_key (float *index, short *sel); static Base *get_nearest_nlastrip (bActionStrip **rstrip, short *sel); static void mouse_nlachannels(short mval[2]); -static void add_nlablock(short mval[2]); static void convert_nla(short mval[2]); /* ******************** SPACE: NLA ********************** */ @@ -249,189 +247,6 @@ void snap_action_strips(void) allqueue (REDRAWNLA, 0); } -void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) -{ - unsigned short event= evt->event; - short val= evt->val; - SpaceNla *snla = curarea->spacedata.first; - int doredraw= 0; - short mval[2]; - float dx,dy; - int cfra; - short mousebut = L_MOUSE; - - if (curarea->win==0) return; - if (!snla) return; - - if(val) { - if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; - - /* swap mouse buttons based on user preference */ - if (U.flag & USER_LMOUSESELECT) { - if (event == LEFTMOUSE) { - event = RIGHTMOUSE; - mousebut = L_MOUSE; - } else if (event == RIGHTMOUSE) { - event = LEFTMOUSE; - mousebut = R_MOUSE; - } - } - - getmouseco_areawin(mval); - - switch(event) { - case UI_BUT_EVENT: - do_nlabuts(val); // in drawnla.c - break; - - case HOMEKEY: - do_nla_buttons(B_NLAHOME); - break; - - case EQUALKEY: - case PAGEUPKEY: - shift_nlastrips_up(); - break; - - case MINUSKEY: - case PAGEDOWNKEY: - shift_nlastrips_down(); - break; - - case AKEY: - if (G.qual & LR_SHIFTKEY){ - add_nlablock(mval); - allqueue (REDRAWNLA, 0); - allqueue (REDRAWVIEW3D, 0); - } - else{ - if (mval[0]>=NLAWIDTH) - deselect_nlachannel_keys(1); - else{ - deselect_nlachannels(1); - allqueue (REDRAWVIEW3D, 0); - } - allqueue (REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - BIF_undo_push("(De)select all NLA"); - } - break; - - case BKEY: - borderselect_nla(); - break; - - case CKEY: - convert_nla(mval); - break; - - case DKEY: - if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){ - duplicate_nlachannel_keys(); - update_for_newframe_muted(); - } - break; - - case GKEY: - if (mval[0]>=NLAWIDTH) - transform_nlachannel_keys ('g', 0); - update_for_newframe_muted(); - break; - - case NKEY: - if(G.qual==0) { - toggle_blockhandler(curarea, NLA_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE); - scrarea_queue_winredraw(curarea); - } - break; - - case SKEY: - if(G.qual==LR_ALTKEY) { - val= pupmenu("Action Strip Scale%t|Clear Strip Size%x1|Remap Start/End%x2"); - if(val==1) - reset_action_strips(1); - else if(val==2) - reset_action_strips(2); - } - else if(G.qual & LR_SHIFTKEY) { - if(okee("Snap Strips to Frame")) - snap_action_strips(); - } - else { - if (mval[0]>=NLAWIDTH) - transform_nlachannel_keys ('s', 0); - update_for_newframe_muted(); - } - break; - - case DELKEY: - case XKEY: - if (mval[0]>=NLAWIDTH) - delete_nlachannel_keys (); - - update_for_newframe_muted(); - break; - - /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above, - * based on user preference USER_LMOUSESELECT - */ - case LEFTMOUSE: - if(view2dmove(LEFTMOUSE)) - break; // only checks for sliders - else if (mval[0]>=snla->v2d.mask.xmin) { - do { - getmouseco_areawin(mval); - - areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); - - cfra= (int)dx; - if(cfra< 1) cfra= 1; - - if( cfra!=CFRA ) { - CFRA= cfra; - update_for_newframe(); - force_draw_all(0); - } - else PIL_sleep_ms(30); - - } while(get_mbut() & mousebut); - break; - } - /* else pass on! */ - case RIGHTMOUSE: - if (mval[0]>=snla->v2d.mask.xmin) { - if(G.qual & LR_SHIFTKEY) - mouse_nla(SELECT_INVERT); - else - mouse_nla(SELECT_REPLACE); - } - else - mouse_nlachannels(mval); - break; - - case PADPLUSKEY: - view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); - doredraw= 1; - break; - case PADMINUS: - view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); - doredraw= 1; - break; - case MIDDLEMOUSE: - case WHEELUPMOUSE: - case WHEELDOWNMOUSE: - view2dmove(event); /* in drawipo.c */ - break; - } - } - - if(doredraw) scrarea_queue_winredraw(curarea); -} - static void set_active_strip(Object *ob, bActionStrip *act) { bActionStrip *strip; @@ -444,9 +259,13 @@ static void set_active_strip(Object *ob, bActionStrip *act) if(ob->action!=act->act) { if(ob->action) ob->action->id.us--; - ob->action= act->act; - ob->action->id.us++; - + if(act->act->id.lib) { + ob->action= NULL; + } + else { + ob->action= act->act; + id_us_plus(&ob->action->id); + } allqueue(REDRAWIPO, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWACTION, 0); @@ -556,11 +375,9 @@ static void convert_nla(short mval[2]) } } - -static Base *nla_base=NULL; /* global, bad, bad! put it in nla space later, or recode the 2 functions below (ton) */ - static void add_nla_block(short event) { + Object *ob= OBACT; bAction *act=NULL; bActionStrip *strip; int cur; @@ -585,23 +402,24 @@ static void add_nla_block(short event) /* Link the action to the strip */ strip->act = act; + id_us_plus(&act->id); calc_action_range(strip->act, &strip->actstart, &strip->actend); strip->start = G.scene->r.cfra; /* could be mval[0] another time... */ strip->end = strip->start + (strip->actend-strip->actstart); /* simple prevention of zero strips */ if(strip->start>strip->end-2) strip->end= strip->start+100; - - strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; - - find_stridechannel(nla_base->object, strip); - set_active_strip(nla_base->object, strip); - strip->repeat = 1.0; - act->id.us++; + strip->flag = ACTSTRIP_SELECT|ACTSTRIP_LOCK_ACTION; - BLI_addtail(&nla_base->object->nlastrips, strip); + find_stridechannel(ob, strip); + set_active_strip(ob, strip); + strip->object= group_get_member_with_action(ob->dup_group, act); + if(strip->object) + id_lib_extern(&strip->object->id); /* checks lib data, sets correct flag for saving then */ + + BLI_addtail(&ob->nlastrips, strip); BIF_undo_push("Add NLA strip"); } @@ -611,70 +429,29 @@ static void add_nla_databrowse_callback(unsigned short val) /* val is not used, databrowse needs it to optional pass an event */ short event; - if(nla_base==NULL) return; + if(OBACT==NULL) return; event= G.snla->menunr; /* set by databrowse or pupmenu */ add_nla_block(event); } -static void add_nlablock(short mval[2]) +/* Adds strip to to active Object */ +static void add_nlablock(void) { - /* Make sure we are over an object with action */ - Base *base; - rctf rectf; - float ymin, ymax; - float x, y; + Object *ob= OBACT; short event; short nr; - char *str; - - areamouseco_to_ipoco(G.v2d, mval, &x, &y); - - mval[0]-=7; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + char *str, title[64]; - mval[0]+=14; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); - - ymax = count_nla_levels(); - ymax*= (NLACHANNELHEIGHT + NLACHANNELSKIP); - ymax+= NLACHANNELHEIGHT/2; - - for (base=G.scene->base.first; base; base=base->next){ - /* Handle object ipo selection */ - if (nla_filter(base)) { - - /* Area that encloses object name (or ipo) */ - ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); - - /* Area that encloses action */ - if (base->object->action) - ymin-=(NLACHANNELHEIGHT+NLACHANNELSKIP); - - /* Area that encloses nla strips */ - ymin-=(NLACHANNELHEIGHT+NLACHANNELSKIP)* - (BLI_countlist(&base->object->nlastrips)); - - /* Test to see the mouse is in an action area */ - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) - break; - - ymax=ymin; - } - } - - /* global... for the call above, because the NLA system seems not to have an 'active strip' stored */ - nla_base= base; - - /* Make sure we have an action */ - if (!base){ - error ("Object has not an Action"); + if(ob==NULL) { + error("Need active Object to add NLA strips"); return; } /* Popup action menu */ - IDnames_to_pupstring(&str, "Add Action", NULL, &G.main->action, (ID *)G.scene, &nr); + sprintf(title, "Add Action strip to %s", ob->id.name+2); + IDnames_to_pupstring(&str, title, NULL, &G.main->action, (ID *)G.scene, &nr); if(strncmp(str+13, "DataBrow", 8)==0) { MEM_freeN(str); @@ -689,11 +466,6 @@ static void add_nlablock(short mval[2]) MEM_freeN(str); add_nla_block(event); } - - /* Ton: this is a callback for databrowse too - Hos: no, I don't think it is - add_nla_block(0); - */ } /* Left hand side of channels display, selects objects */ @@ -1761,3 +1533,187 @@ void deselect_nlachannels(int test) base->object->flag= base->flag; } } + +void winqreadnlaspace(ScrArea *sa, void *spacedata, BWinEvent *evt) +{ + unsigned short event= evt->event; + short val= evt->val; + SpaceNla *snla = curarea->spacedata.first; + int doredraw= 0; + short mval[2]; + float dx,dy; + int cfra; + short mousebut = L_MOUSE; + + if (curarea->win==0) return; + if (!snla) return; + + if(val) { + if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + + /* swap mouse buttons based on user preference */ + if (U.flag & USER_LMOUSESELECT) { + if (event == LEFTMOUSE) { + event = RIGHTMOUSE; + mousebut = L_MOUSE; + } else if (event == RIGHTMOUSE) { + event = LEFTMOUSE; + mousebut = R_MOUSE; + } + } + + getmouseco_areawin(mval); + + switch(event) { + case UI_BUT_EVENT: + do_nlabuts(val); // in drawnla.c + break; + + case HOMEKEY: + do_nla_buttons(B_NLAHOME); + break; + + case EQUALKEY: + case PAGEUPKEY: + shift_nlastrips_up(); + break; + + case MINUSKEY: + case PAGEDOWNKEY: + shift_nlastrips_down(); + break; + + case AKEY: + if (G.qual & LR_SHIFTKEY){ + add_nlablock(); + allqueue (REDRAWNLA, 0); + allqueue (REDRAWVIEW3D, 0); + } + else{ + if (mval[0]>=NLAWIDTH) + deselect_nlachannel_keys(1); + else{ + deselect_nlachannels(1); + allqueue (REDRAWVIEW3D, 0); + } + allqueue (REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); + BIF_undo_push("(De)select all NLA"); + } + break; + + case BKEY: + borderselect_nla(); + break; + + case CKEY: + convert_nla(mval); + break; + + case DKEY: + if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){ + duplicate_nlachannel_keys(); + update_for_newframe_muted(); + } + break; + + case GKEY: + if (mval[0]>=NLAWIDTH) + transform_nlachannel_keys ('g', 0); + update_for_newframe_muted(); + break; + + case NKEY: + if(G.qual==0) { + toggle_blockhandler(curarea, NLA_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE); + scrarea_queue_winredraw(curarea); + } + break; + + case SKEY: + if(G.qual==LR_ALTKEY) { + val= pupmenu("Action Strip Scale%t|Clear Strip Size%x1|Remap Start/End%x2"); + if(val==1) + reset_action_strips(1); + else if(val==2) + reset_action_strips(2); + } + else if(G.qual & LR_SHIFTKEY) { + if(okee("Snap Strips to Frame")) + snap_action_strips(); + } + else { + if (mval[0]>=NLAWIDTH) + transform_nlachannel_keys ('s', 0); + update_for_newframe_muted(); + } + break; + + case DELKEY: + case XKEY: + if (mval[0]>=NLAWIDTH) + delete_nlachannel_keys (); + + update_for_newframe_muted(); + break; + + /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above, + * based on user preference USER_LMOUSESELECT + */ + case LEFTMOUSE: + if(view2dmove(LEFTMOUSE)) + break; // only checks for sliders + else if (mval[0]>=snla->v2d.mask.xmin) { + do { + getmouseco_areawin(mval); + + areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); + + cfra= (int)dx; + if(cfra< 1) cfra= 1; + + if( cfra!=CFRA ) { + CFRA= cfra; + update_for_newframe(); + force_draw_all(0); + } + else PIL_sleep_ms(30); + + } while(get_mbut() & mousebut); + break; + } + /* else pass on! */ + case RIGHTMOUSE: + if (mval[0]>=snla->v2d.mask.xmin) { + if(G.qual & LR_SHIFTKEY) + mouse_nla(SELECT_INVERT); + else + mouse_nla(SELECT_REPLACE); + } + else + mouse_nlachannels(mval); + break; + + case PADPLUSKEY: + view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy); + test_view2d(G.v2d, sa->winx, sa->winy); + view2d_do_locks(curarea, V2D_LOCK_COPY); + doredraw= 1; + break; + case PADMINUS: + view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy); + test_view2d(G.v2d, sa->winx, sa->winy); + view2d_do_locks(curarea, V2D_LOCK_COPY); + doredraw= 1; + break; + case MIDDLEMOUSE: + case WHEELUPMOUSE: + case WHEELDOWNMOUSE: + view2dmove(event); /* in drawipo.c */ + break; + } + } + + if(doredraw) scrarea_queue_winredraw(curarea); +} + diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 894f787a2d2..32f42644625 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3133,7 +3133,7 @@ void make_duplilist_real() { Base *base, *basen; Object *ob; - extern ListBase duplilist; +// extern ListBase duplilist; if(okee("Make dupli objects real")==0) return; @@ -3142,11 +3142,11 @@ void make_duplilist_real() if TESTBASELIB(base) { if(base->object->transflag & OB_DUPLI) { - - make_duplilist(G.scene, base->object); - ob= duplilist.first; - while(ob) { - + ListBase *lb= object_duplilist(G.scene, base->object); + DupliObject *dob; + + for(dob= lb->first; dob; dob= dob->next) { + ob= copy_object(dob->ob); /* font duplis can have a totcol without material, we get them from parent * should be implemented better... */ @@ -3155,19 +3155,17 @@ void make_duplilist_real() basen= MEM_dupallocN(base); basen->flag &= ~OB_FROMDUPLI; BLI_addhead(&G.scene->base, basen); /* addhead: othwise eternal loop */ + basen->object= ob; ob->ipo= NULL; /* make sure apply works */ ob->parent= ob->track= NULL; ob->disp.first= ob->disp.last= NULL; - ob->transflag &= ~OB_DUPLI; - basen->object= copy_object(ob); - basen->object->flag &= ~OB_FROMDUPLI; - - apply_obmat(basen->object); + ob->transflag &= ~OB_DUPLI; - ob= ob->id.next; + Mat4CpyMat4(ob->obmat, dob->mat); + apply_obmat(ob); } - free_duplilist(); + BLI_freelistN(lb); base->object->transflag &= ~OB_DUPLI; } diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index db4c981eba2..269e4bc04d7 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -2617,7 +2617,12 @@ void main_to_filelist(SpaceFile *sfile) if (hide==0 || id->name[2] != '.') { memset( files, 0 , sizeof(struct direntry)); - files->relname= BLI_strdup(id->name+2); + if(id->lib==NULL) + files->relname= BLI_strdup(id->name+2); + else { + files->relname= MEM_mallocN(FILE_MAXDIR+FILE_MAXFILE+32, "filename for lib"); + sprintf(files->relname, "%s | %s", id->lib->name, id->name+2); + } if(sfile->returnfunc==0) { /* F4 DATA BROWSE */ if(idcode==ID_OB) { diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 01c1ddc194d..dbb32bf9358 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -1216,6 +1216,9 @@ void do_info_addmenu(void *arg, int event) /* Lattice */ add_object_draw(OB_LATTICE); break; + case 10: + /* group instance not yet */ + break; default: break; } diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 7fe1ac4cbf7..077d43d7a5a 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -61,6 +61,7 @@ #include "BKE_constraint.h" #include "BKE_depsgraph.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_material.h" @@ -110,7 +111,7 @@ #define TS_CHUNK 128 -#define TREESTORE(a) soops->treestore->data+(a)->store_index +#define TREESTORE(a) ((a)?soops->treestore->data+(a)->store_index:NULL) /* ******************** PERSISTANT DATA ***************** */ @@ -511,13 +512,13 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i te->name= md->name; if (md->type==eModifierType_Lattice) { - outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_MODIFIER_OB, 0); + outliner_add_element(soops, &te->subtree, ((LatticeModifierData*) md)->object, te, TSE_LINKED_OB, 0); } else if (md->type==eModifierType_Curve) { - outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_MODIFIER_OB, 0); + outliner_add_element(soops, &te->subtree, ((CurveModifierData*) md)->object, te, TSE_LINKED_OB, 0); } else if (md->type==eModifierType_Armature) { - outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_MODIFIER_OB, 0); + outliner_add_element(soops, &te->subtree, ((ArmatureModifierData*) md)->object, te, TSE_LINKED_OB, 0); } else if (md->type==eModifierType_Hook) { - outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_MODIFIER_OB, 0); + outliner_add_element(soops, &te->subtree, ((HookModifierData*) md)->object, te, TSE_LINKED_OB, 0); } } } @@ -543,6 +544,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i outliner_add_element(soops, &tenla->subtree, ob->scriptlink.scripts[a], te, 0, 0); } } + + if(ob->dup_group) + outliner_add_element(soops, &te->subtree, ob->dup_group, te, 0, 0); + if(ob->nlastrips.first) { bActionStrip *strip; TreeElement *ten; @@ -775,16 +780,18 @@ static void outliner_build_tree(SpaceOops *soops) GroupObject *go; for(group= G.main->group.first; group; group= group->id.next) { - te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0); - tselem= TREESTORE(te); - - for(go= group->gobject.first; go; go= go->next) { - ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); - ten->directdata= NULL; + if(group->id.us) { + te= outliner_add_element(soops, &soops->tree, group, NULL, 0, 0); + tselem= TREESTORE(te); + + for(go= group->gobject.first; go; go= go->next) { + ten= outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0); + ten->directdata= NULL; + } + outliner_make_hierarchy(soops, &te->subtree); + /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ + for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL; } - outliner_make_hierarchy(soops, &te->subtree); - /* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */ - for(go= group->gobject.first; go; go= go->next) go->ob->id.newid= NULL; } } else if(soops->outlinevis == SO_SAME_TYPE) { @@ -1425,7 +1432,7 @@ static int tree_element_type_active(SpaceOops *soops, TreeElement *te, TreeStore return tree_element_active_ebone(te, tselem, set); case TSE_MODIFIER: return tree_element_active_modifier(te, tselem, set); - case TSE_MODIFIER_OB: + case TSE_LINKED_OB: if(set) tree_element_active_object(soops, te); else if(tselem->id==(ID *)OBACT) return 1; break; @@ -1710,12 +1717,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb) case ID_ME: case ID_CU: case ID_MB: case ID_LT: case ID_LA: case ID_AR: case ID_CA: - idlevel= -2; - break; - case ID_MA: case ID_TE: case ID_IP: case ID_IM: case ID_SO: case ID_KE: case ID_WO: case ID_AC: - case ID_NLA: case ID_TXT: + case ID_NLA: case ID_TXT: case ID_GR: if(idlevel==0) idlevel= idcode; else if(idlevel!=idcode) idlevel= -1; break; @@ -1726,7 +1730,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb) } } -static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep) +static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { Material **matar=NULL; int a, totcol=0; @@ -1760,7 +1764,7 @@ static void unlink_material_cb(TreeElement *te, TreeStoreElem *tsep) } } -static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep) +static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { MTex **mtex= NULL; int a; @@ -1789,8 +1793,25 @@ static void unlink_texture_cb(TreeElement *te, TreeStoreElem *tsep) } } +static void unlink_group_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +{ + Group *group= (Group *)tselem->id; + + if(tsep) { + if( GS(tsep->id->name)==ID_OB) { + Object *ob= (Object *)tsep->id; + ob->dup_group= NULL; + group->id.us--; + } + } + else { + unlink_group(group); + group->id.us= 0; + } +} + static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb, - void (*operation_cb)(TreeElement *, TreeStoreElem *)) + void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *)) { TreeElement *te; TreeStoreElem *tselem; @@ -1800,7 +1821,7 @@ static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb, if(tselem->flag & TSE_SELECTED) { if(tselem->type==0) { TreeStoreElem *tsep= TREESTORE(te->parent); - operation_cb(te, tsep); + operation_cb(te, tsep, tselem); } } if((tselem->flag & TSE_CLOSED)==0) { @@ -1811,7 +1832,7 @@ static void outliner_do_libdata_operation(SpaceOops *soops, ListBase *lb, /* */ -static void object_select_cb(TreeElement *te, TreeStoreElem *tselem) +static void object_select_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { Base *base= (Base *)te->directdata; @@ -1822,7 +1843,7 @@ static void object_select_cb(TreeElement *te, TreeStoreElem *tselem) } } -static void object_deselect_cb(TreeElement *te, TreeStoreElem *tselem) +static void object_deselect_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { Base *base= (Base *)te->directdata; @@ -1833,7 +1854,7 @@ static void object_deselect_cb(TreeElement *te, TreeStoreElem *tselem) } } -static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem) +static void object_delete_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) { Base *base= (Base *)te->directdata; @@ -1853,9 +1874,17 @@ static void object_delete_cb(TreeElement *te, TreeStoreElem *tselem) } } +static void id_local_cb(TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem) +{ + if(tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) { + tselem->id->lib= NULL; + tselem->id->flag= LIB_LOCAL; + new_id(0, tselem->id, 0); + } +} static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb, - void (*operation_cb)(TreeElement *, TreeStoreElem *)) + void (*operation_cb)(TreeElement *, TreeStoreElem *, TreeStoreElem *)) { TreeElement *te; TreeStoreElem *tselem; @@ -1868,7 +1897,7 @@ static void outliner_do_object_operation(SpaceOops *soops, ListBase *lb, Scene *sce= (Scene *)outliner_search_back(soops, te, ID_SCE); if(sce && G.scene != sce) set_scene(sce); - operation_cb(te, tselem); + operation_cb(te, NULL, tselem); } } if((tselem->flag & TSE_CLOSED)==0) { @@ -1959,7 +1988,7 @@ void outliner_operation_menu(ScrArea *sa) //else pupmenu("Scene Operations%t|Delete"); } else if(objectlevel) { - short event= pupmenu("Object Operations%t|Select%x1|Deselect%x2|Delete%x4"); + short event= pupmenu("Object Operations%t|Select%x1|Deselect%x2|Delete%x4|Make Local%x5"); if(event>0) { char *str=""; @@ -1979,18 +2008,21 @@ void outliner_operation_menu(ScrArea *sa) DAG_scene_sort(G.scene); str= "Delete Objects"; } + else if(event==5) { + outliner_do_object_operation(soops, &soops->tree, id_local_cb); + str= "Localized Objects"; + } countall(); BIF_undo_push(str); - allqueue(REDRAWALL, 0); // yah... to be sure :) + allqueue(REDRAWALL, 0); } } else if(idlevel) { if(idlevel==-1 || datalevel) error("Mixed selection"); - else if(idlevel==-2) error("No operations available"); else { - short event= pupmenu("Data Operations%t|Unlink"); + short event= pupmenu("Data Operations%t|Unlink %x1|Make Local %x2"); if(event==1) { switch(idlevel) { @@ -2004,12 +2036,19 @@ void outliner_operation_menu(ScrArea *sa) allqueue(REDRAWBUTSSHADING, 1); BIF_undo_push("Unlink texture"); break; + case ID_GR: + outliner_do_libdata_operation(soops, &soops->tree, unlink_group_cb); + BIF_undo_push("Unlink group"); + break; default: error("Not yet..."); } - allqueue(REDRAWOOPS, 0); - allqueue(REDRAWBUTSALL, 0); - allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWALL, 0); + } + else if(event==2) { + outliner_do_libdata_operation(soops, &soops->tree, id_local_cb); + BIF_undo_push("Localized Data"); + allqueue(REDRAWALL, 0); } } } @@ -2065,7 +2104,7 @@ static void tselem_draw_icon(float x, float y, TreeStoreElem *tselem, TreeElemen BIF_draw_icon(x, y, ICON_CONSTRAINT); break; case TSE_MODIFIER_BASE: BIF_draw_icon(x, y, ICON_MODIFIER); break; - case TSE_MODIFIER_OB: + case TSE_LINKED_OB: BIF_draw_icon(x, y, ICON_OBJECT); break; case TSE_MODIFIER: { @@ -2279,17 +2318,21 @@ static void outliner_draw_tree_element(SpaceOops *soops, TreeElement *te, int st // icons a bit higher tselem_draw_icon(startx+offsx, *starty+2, tselem, te); offsx+= OL_X; + + if(tselem->id->lib && tselem->type==0) { + glPixelTransferf(GL_ALPHA_SCALE, 0.5); + if(tselem->id->flag & LIB_INDIRECT) + BIF_draw_icon(startx+offsx, *starty+2, ICON_DATALIB); + else + BIF_draw_icon(startx+offsx, *starty+2, ICON_PARLIB); + glPixelTransferf(GL_ALPHA_SCALE, 1.0); + offsx+= OL_X; + } glDisable(GL_BLEND); /* name */ - if(tselem->id->lib) { - if(active==1) glColor3ub(0xBB, 0xFF, 0xFF); - else glColor3ub(0, 0x30, 0x30); - } - else { - if(active==1) BIF_ThemeColor(TH_TEXT_HI); - else BIF_ThemeColor(TH_TEXT); - } + if(active==1) BIF_ThemeColor(TH_TEXT_HI); + else BIF_ThemeColor(TH_TEXT); glRasterPos2i(startx+offsx, *starty+5); BIF_RasterPos(startx+offsx, *starty+5); BIF_DrawString(G.font, te->name, 0); diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 6238d253d35..82839fcdeb9 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -55,10 +55,11 @@ #include "BIF_language.h" #include "BIF_resources.h" +#include "DNA_group_types.h" #include "DNA_image_types.h" -#include "DNA_object_types.h" -#include "DNA_mesh_types.h" #include "DNA_lamp_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_userdef_types.h" @@ -67,13 +68,14 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" -#include "BKE_depsgraph.h" -#include "BKE_plugin_types.h" -#include "BKE_utildefines.h" -#include "BKE_mesh.h" #include "BKE_displist.h" +#include "BKE_depsgraph.h" #include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_mesh.h" #include "BKE_main.h" +#include "BKE_plugin_types.h" +#include "BKE_utildefines.h" #include "BIF_editnla.h" #include "BIF_editarmature.h" @@ -2241,6 +2243,10 @@ static TBitem addmenu_armature[]= { { 0, "Bone", 8, NULL}, { -1, "", 0, do_info_addmenu}}; +/* dynamic items */ +#define TB_ADD_GROUP 6 +#define TB_ADD_LAMP 9 + static TBitem tb_add[]= { { 0, "Mesh", 0, addmenu_mesh}, { 0, "Curve", 1, addmenu_curve}, @@ -2248,6 +2254,7 @@ static TBitem tb_add[]= { { 0, "Meta", 3, addmenu_meta}, { 0, "Text", 4, NULL}, { 0, "Empty", 5, NULL}, +{ 0, "Group", 10, NULL}, { 0, "SEPR", 0, NULL}, { 0, "Camera", 6, NULL}, { 0, "Lamp", 7, addmenu_lamp}, @@ -2256,21 +2263,6 @@ static TBitem tb_add[]= { { 0, "Lattice", 9, NULL}, { -1, "", 0, do_info_addmenu}}; -static TBitem tb_add_YF[]= { -{ 0, "Mesh", 0, addmenu_mesh}, -{ 0, "Curve", 1, addmenu_curve}, -{ 0, "Surface", 2, addmenu_surf}, -{ 0, "Meta", 3, addmenu_meta}, -{ 0, "Text", 4, NULL}, -{ 0, "Empty", 5, NULL}, -{ 0, "SEPR", 0, NULL}, -{ 0, "Camera", 6, NULL}, -{ 0, "Lamp", 7, addmenu_YF_lamp}, -{ 0, "SEPR", 0, NULL}, -{ 0, "Armature", 8, NULL}, -{ 0, "Lattice", 9, NULL}, -{ -1, "", 0, do_info_addmenu}}; - static TBitem tb_empty[]= { { 0, "Nothing...", 0, NULL}, { -1, "", 0, NULL}}; @@ -2361,13 +2353,57 @@ static void store_main(void *arg1, void *arg2) tb_mainy= (int)arg2; } +static void do_group_addmenu(void *arg, int event) +{ + Object *ob; + + add_object_draw(OB_EMPTY); + ob= OBACT; + + ob->dup_group= BLI_findlink(&G.main->group, event); + if(ob->dup_group) { + id_us_plus((ID *)ob->dup_group); + ob->transflag |= OB_DUPLIGROUP; + } +} + +/* example of dynamic toolbox sublevel */ +static TBitem *create_group_sublevel(void) +{ + static TBitem addmenu[]= { { 0, "No Groups", 0, NULL}, { -1, "", 0, NULL}}; + TBitem *groupmenu; + Group *group; + int a; + + int tot= BLI_countlist(&G.main->group); + + if(tot==0) { + tb_add[TB_ADD_GROUP].poin= addmenu; + return NULL; + } + + groupmenu= MEM_callocN(sizeof(TBitem)*(tot+1), "group menu"); + for(a=0, group= G.main->group.first; group; group= group->id.next, a++) { + groupmenu[a].name= group->id.name+2; + groupmenu[a].retval= a; + } + groupmenu[a].icon= -1; /* end signal */ + groupmenu[a].name= ""; + groupmenu[a].retval= a; + groupmenu[a].poin= do_group_addmenu; + + tb_add[TB_ADD_GROUP].poin= groupmenu; + + return groupmenu; +} + void toolbox_n(void) { uiBlock *block; uiBut *but; TBitem *menu1=NULL, *menu2=NULL, *menu3=NULL; TBitem *menu4=NULL, *menu5=NULL, *menu6=NULL; - TBitem *menu7=NULL; + TBitem *menu7=NULL, *groupmenu; int dx=0; short event, mval[2], tot=0; char *str1=NULL, *str2=NULL, *str3=NULL, *str4=NULL, *str5=NULL, *str6=NULL, *str7=NULL; @@ -2389,16 +2425,19 @@ void toolbox_n(void) uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1); uiBlockSetCol(block, TH_MENU_ITEM); + /* dynamic menu entries */ + groupmenu= create_group_sublevel(); + + if (G.scene->r.renderer==R_YAFRAY) + tb_add[TB_ADD_LAMP].poin= addmenu_YF_lamp; + else + tb_add[TB_ADD_LAMP].poin= addmenu_lamp; + /* select context for main items */ if(curarea->spacetype==SPACE_VIEW3D) { if(U.uiflag & USER_PLAINMENUS) { - /* column layout menu */ - if (G.scene->r.renderer==R_YAFRAY) { - menu1= tb_add_YF; str1= "Add"; - } else { - menu1= tb_add; str1= "Add"; - } + menu1= tb_add; str1= "Add"; menu2= tb_object_edit; str2= "Edit"; menu3= tb_object_select; str3= "Select"; menu4= tb_transform; str4= "Transform"; @@ -2411,11 +2450,7 @@ void toolbox_n(void) } else { /* 3x2 layout menu */ menu1= tb_object; str1= "Object"; - if (G.scene->r.renderer==R_YAFRAY) { - menu2= tb_add_YF; str2= "Add"; - } else { - menu2= tb_add; str2= "Add"; - } + menu2= tb_add; str2= "Add"; menu3= tb_object_select; str3= "Select"; menu4= tb_object_edit; str4= "Edit"; menu5= tb_transform; str5= "Transform"; @@ -2599,6 +2634,8 @@ void toolbox_n(void) uiBoundsBlock(block, 2); event= uiDoBlocks(&tb_listb, 0); + if(groupmenu) MEM_freeN(groupmenu); + mywinset(curarea->win); } diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 6f6a01de09b..5de5e134c4b 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -61,10 +61,11 @@ #include "DNA_userdef_types.h" #include "DNA_view3d_types.h" -#include "BKE_utildefines.h" -#include "BKE_object.h" +#include "BKE_anim.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" #include "BIF_gl.h" #include "BIF_space.h" @@ -1012,6 +1013,27 @@ short view3d_opengl_select(unsigned int *buffer, unsigned int bufsize, short x1 base->selcol= code; glLoadName(code); draw_object(base, DRAW_PICKING|DRAW_CONSTCOLOR); + + /* we draw group-duplicators for selection too */ + if((base->object->transflag & OB_DUPLI) && base->object->dup_group) { + ListBase *lb; + DupliObject *dob; + Base tbase; + + tbase.flag= OB_FROMDUPLI; + lb= object_duplilist(G.scene, base->object); + + for(dob= lb->first; dob; dob= dob->next) { + tbase.object= dob->ob; + Mat4CpyMat4(dob->ob->obmat, dob->mat); + + draw_object(&tbase, DRAW_PICKING|DRAW_CONSTCOLOR); + + Mat4CpyMat4(dob->ob->obmat, dob->omat); + } + BLI_freelistN(lb); + } + code++; } } |