diff options
22 files changed, 1315 insertions, 305 deletions
diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index e7494f28fc4..411225b0635 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -1,8 +1,8 @@ /* BKE_deform.h June 2001 * - * support for deformation groups + * support for deformation groups and hooks * - * Reevan McKay + * Reevan McKay et al * * $Id$ * @@ -46,5 +46,12 @@ void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2); struct bDeformGroup* copy_defgroup (struct bDeformGroup *ingroup); void color_temperature (float input, unsigned char *r, unsigned char *g, unsigned char *b); +void hook_object_deform(struct Object *ob, int index, float *vec); + +int curve_modifier(struct Object *ob, char mode); +int mesh_modifier(struct Object *ob, char mode); +int lattice_modifier(struct Object *ob, char mode); + + #endif diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 3bd2ff432b9..a5384ee2ae2 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -93,7 +93,6 @@ void minmax_object(struct Object *ob, float *min, float *max); void solve_tracking (struct Object *ob, float targetmat[][4]); void solve_constraints (struct Object *ob, short obtype, void *obdata, float ctime); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index fc7953c051d..1cd442a5391 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -97,8 +97,6 @@ void calc_curvepath(Object *ob) if(cu->path) free_path(cu->path); cu->path= 0; - if((cu->flag & CU_PATH)==0) return; - bl= cu->bev.first; if(bl==0) { makeDispList(ob); @@ -213,10 +211,13 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK float *fp, *p0, *p1, *p2, *p3, fac; float data[4]; int cycl=0, s0, s1, s2, s3; - + if(ob==0 || ob->type != OB_CURVE) return 0; cu= ob->data; - if(cu->path==0 || cu->path->data==0) calc_curvepath(ob); + if(cu->path==0 || cu->path->data==0) { + calc_curvepath(ob); + if(cu->path==0 || cu->path->data==0) return 0; + } path= cu->path; fp= path->data; @@ -224,7 +225,6 @@ int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK bl= cu->bev.first; if(bl && bl->poly> -1) cycl= 1; - /* ctime is between 0.0-1.0 */ ctime *= (path->len-1); s1= (int)floor(ctime); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index ae73d7f5059..0c30e53ec16 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1197,9 +1197,13 @@ void make_displists_by_armature (Object *ob) for (base= G.scene->base.first; base; base= base->next){ if ((ob==base->object->parent) && (base->lay & G.scene->lay)) if ((base->object->partype==PARSKEL) || (base->object->type==OB_MBALL)) - makeDispList(base->object); + freedisplist(&base->object->disp); } } +/* +(ton) changed this; now a free displist is sufficient, drawobject.c will make disp +*/ + } void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index f1ba0324fc8..f3eab76a465 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -36,10 +36,23 @@ */ #include <string.h> + #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" + +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "DNA_object_types.h" + +#include "BKE_curve.h" #include "BKE_deform.h" +#include "BKE_displist.h" +#include "BKE_lattice.h" +#include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -117,3 +130,243 @@ bDeformGroup* copy_defgroup (bDeformGroup *ingroup) return outgroup; } +/* *************** HOOK ****************** */ + +/* vec==NULL: init + vec is supposed to be local coord +*/ + +void hook_object_deform(Object *ob, int index, float *vec) +{ + float totforce; + ObHook *hook; + float vect[3], vectot[3]; + + if(ob->hooks.first==NULL) return; + + /* reinitialize if... */ + if(vec==NULL) { + totforce= 0.0; + for(hook= ob->hooks.first; hook; hook= hook->next) { + if(hook->parent) { + hook->curindex= 0; + Mat4Invert(ob->imat, ob->obmat); + /* apparently this call goes from right to left... */ + Mat4MulSerie(hook->mat, ob->imat, hook->parent->obmat, hook->parentinv, NULL, + NULL, NULL, NULL, NULL); + } + } + return; + } + + totforce= 0.0; + vectot[0]= vectot[1]= vectot[2]= 0.0; + + for(hook= ob->hooks.first; hook; hook= hook->next) { + if(hook->parent) { + + /* is 'index' in hook array? */ + while(hook->curindex < hook->totindex-1) { + if( hook->indexar[hook->curindex] < index ) hook->curindex++; + else break; + } + + if( hook->indexar[hook->curindex]==index ) { + float fac= hook->force; + + totforce+= fac; + + VecMat4MulVecfl(vect, hook->mat, vec); + vectot[0]+= fac*vect[0]; + vectot[1]+= fac*vect[1]; + vectot[2]+= fac*vect[2]; + } + } + } + + /* if totforce < 1.0, we take old position also into account */ + if(totforce<1.0) { + vectot[0]+= (1.0-totforce)*vec[0]; + vectot[1]+= (1.0-totforce)*vec[1]; + vectot[2]+= (1.0-totforce)*vec[2]; + } + else VecMulf(vectot, 1.0/totforce); + + VECCOPY(vec, vectot); +} + + +/* modifiers: hooks, deform, softbody + mode=='s' is start, 'e' end +*/ + +int mesh_modifier(Object *ob, char mode) +{ + static MVert *mvert=NULL; + Mesh *me= ob->data; + MVert *mv; + int a, done=0; + + /* conditions if it's needed */ + if(ob->hooks.first); + else if(ob->parent && ob->parent->type==OB_LATTICE); + else if(ob->parent && ob->partype==PARSKEL); + else return 0; + + if(me->totvert==0) return 0; + + if(mode=='s') { // "start" + /* copy */ + mvert= MEM_dupallocN(me->mvert); + + /* hooks */ + if(ob->hooks.first) { + done= 1; + + /* NULL signals initialize */ + hook_object_deform(ob, 0, NULL); + + for(a=0, mv= me->mvert; a<me->totvert; a++, mv++) { + hook_object_deform(ob, a, mv->co); + } + } + + /* deform: input mesh, output ob dl_verts. is used by subsurf */ + done |= object_deform(ob); + + /* put deformed vertices in dl->verts, optional subsurf will replace that */ + if(done) { + DispList *dl= find_displist_create(&ob->disp, DL_VERTS); + float *fp; + + if(dl->verts) MEM_freeN(dl->verts); + dl->nr= me->totvert; + if(dl->nr) { + + /* make disp array */ + dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); + mv= me->mvert; + for(a=0; a<me->totvert; a++, mv++, fp+=3) { + VECCOPY(fp, mv->co); + } + } + } + } + else { // end + if(mvert) { + MEM_freeN(me->mvert); + me->mvert= mvert; + mvert= NULL; + } + } + + return done; +} + +int curve_modifier(Object *ob, char mode) +{ + static ListBase nurb={NULL, NULL}; + Curve *cu= ob->data; + Nurb *nu, *newnu; + BezTriple *bezt; + BPoint *bp; + int a, index, done= 0; + + /* conditions if it's needed */ + if(ob->hooks.first); + else if(ob->parent && ob->partype==PARSKEL); + else if(ob->parent && ob->parent->type==OB_LATTICE); + else return 0; + + if(mode=='s') { // "start" + /* copy */ + nurb.first= nurb.last= NULL; + nu= cu->nurb.first; + while(nu) { + newnu= duplicateNurb(nu); + BLI_addtail(&nurb, newnu); + nu= nu->next; + } + + /* hooks */ + if(ob->hooks.first) { + done= 1; + + /* NULL signals initialize */ + hook_object_deform(ob, 0, NULL); + index= 0; + + nu= cu->nurb.first; + while(nu) { + if((nu->type & 7)==CU_BEZIER) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + hook_object_deform(ob, index++, bezt->vec[0]); + hook_object_deform(ob, index++, bezt->vec[1]); + hook_object_deform(ob, index++, bezt->vec[2]); + bezt++; + } + } + else { + bp= nu->bp; + a= nu->pntsu*nu->pntsv; + while(a--) { + hook_object_deform(ob, index++, bp->vec); + bp++; + } + } + + nu= nu->next; + } + } + } + else { + /* paste */ + freeNurblist(&cu->nurb); + cu->nurb= nurb; + } + + return done; +} + +int lattice_modifier(Object *ob, char mode) +{ + static BPoint *bpoint; + Lattice *lt= ob->data; + BPoint *bp; + int a, index, done= 0; + + /* conditions if it's needed */ + if(ob->hooks.first); + else if(ob->parent && ob->partype==PARSKEL); + else return 0; + + if(mode=='s') { // "start" + /* copy */ + bpoint= MEM_dupallocN(lt->def); + + /* hooks */ + if(ob->hooks.first) { + done= 1; + + /* NULL signals initialize */ + hook_object_deform(ob, 0, NULL); + index= 0; + bp= lt->def; + a= lt->pntsu*lt->pntsv*lt->pntsw; + while(a--) { + hook_object_deform(ob, index++, bp->vec); + bp++; + } + } + } + else { // end + MEM_freeN(lt->def); + lt->def= bpoint; + bpoint= NULL; + } + + return done; +} + diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 821a1a5bd7c..932eccb2357 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -70,6 +70,7 @@ #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_displist.h" +#include "BKE_deform.h" #include "BKE_object.h" #include "BKE_world.h" #include "BKE_mesh.h" @@ -331,6 +332,20 @@ void freedisplist(ListBase *lb) } } +static void freedisplist_object(Object *ob) +{ + freedisplist(&ob->disp); + + if(ob->type==OB_MESH) { + Mesh *me= ob->data; + freedisplist(&me->disp); + } + else if(ob->type==OB_CURVE || ob->type==OB_SURF || ob->type==OB_FONT) { + Curve *cu= ob->data; + freedisplist(&cu->disp); + } +} + void free_displist_by_type(ListBase *lb, int type) { DispList *dl; @@ -1740,8 +1755,9 @@ void makeDispList(Object *ob) tex_space_mesh(ob->data); - /* deform: input mesh, output ob dl_verts. is used by subsurf */ - object_deform(ob); + if(ob!=G.obedit) { + mesh_modifier(ob, 's'); + } if(ob->effect.first) object_wave(ob); @@ -1752,7 +1768,7 @@ void makeDispList(Object *ob) dlm= subsurf_make_dispListMesh_from_editmesh(em, me->subdiv, me->flag, me->subsurftype); } else { DispList *dlVerts= find_displist(&ob->disp, DL_VERTS); - + // not needed anymore, recode it (ton) dlm= subsurf_make_dispListMesh_from_mesh(me, dlVerts?dlVerts->verts:NULL, me->subdiv, me->flag); } @@ -1764,6 +1780,8 @@ void makeDispList(Object *ob) free_displist_by_type(&me->disp, DL_MESH); BLI_addtail(&me->disp, dl); } + + if(ob!=G.obedit) mesh_modifier(ob, 'e'); } else if(ob->type==OB_MBALL) { @@ -1783,8 +1801,11 @@ void makeDispList(Object *ob) freedisplist(dispbase); if(ob==G.obedit) nu= editNurb.first; - else nu= cu->nurb.first; - + else { + curve_modifier(ob, 's'); + nu= cu->nurb.first; + } + while(nu) { if(nu->hide==0) { if(nu->pntsv==1) { @@ -1856,7 +1877,8 @@ void makeDispList(Object *ob) } tex_space_curve(cu); - + + if(ob!=G.obedit) curve_modifier(ob, 'e'); if(ob!=G.obedit) object_deform(ob); } else if ELEM(ob->type, OB_CURVE, OB_FONT) { @@ -1872,6 +1894,8 @@ void makeDispList(Object *ob) BLI_freelistN(&(cu->bev)); + if(ob!=G.obedit) curve_modifier(ob, 's'); + if(ob==G.obedit) { if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase); else curve_to_displist(&cu->nurb, dispbase); @@ -1986,12 +2010,14 @@ void makeDispList(Object *ob) } } + if(ob!=G.obedit) curve_modifier(ob, 'e'); if(ob!=G.obedit) object_deform(ob); tex_space_curve(cu); } + boundbox_displist(ob); } @@ -2294,12 +2320,13 @@ void imagestodisplist(void) } /* on frame change */ - +/* new method: only frees displists, and relies on + drawobject.c & convertscene.c to build it when needed +*/ void test_all_displists(void) { Base *base; Object *ob; - int done; /* prevent displist to be made too often */ unsigned int lay; /* background */ @@ -2310,8 +2337,6 @@ void test_all_displists(void) if(base->lay & lay) { ob= base->object; - done= 0; - if(ob->type==OB_MBALL && (ob->ipo || ob->parent)) { // find metaball object holding the displist // WARNING: if more metaballs have IPO's the displist @@ -2321,44 +2346,62 @@ void test_all_displists(void) if(ob->disp.first == NULL) { ob= find_basis_mball(ob); } - // makeDispList(ob); freedisplist(&ob->disp); } else if(ob->parent) { - done= 1; if (ob->parent->type == OB_LATTICE) - makeDispList(ob); + freedisplist_object(ob); else if ((ob->parent->type == OB_IKA) && (ob->partype == PARSKEL)) - makeDispList(ob); + freedisplist_object(ob); else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL)) - makeDispList(ob); - else done= 0; + freedisplist_object(ob); + else if ((ob->parent->type==OB_CURVE) && (ob->partype == PARSKEL)) + freedisplist_object(ob); } - /* warn, ob pointer changed in case of OB_MALL */ - if(done==0) { - if ELEM(ob->type, OB_CURVE, OB_SURF) { - if(ob!=G.obedit) { - if( ((Curve *)(ob->data))->key ) makeDispList(ob); - } + if(ob->hooks.first) { + ObHook *hook; + for(hook= ob->hooks.first; hook; hook= hook->next) { + if(hook->parent) freedisplist_object(ob); + break; } - else if(ob->type==OB_FONT) { + } + + /* warn, ob pointer changed in case of OB_MALL */ + + if ELEM(ob->type, OB_CURVE, OB_SURF) { + if(ob!=G.obedit) { Curve *cu= ob->data; - if(cu->textoncurve) { - if( ((Curve *)cu->textoncurve->data)->key ) { - text_to_curve(ob, 0); - makeDispList(ob); - } + + if(cu->key ) freedisplist_object(ob); //makeDispList(ob); + if(cu->bevobj) { + Curve *cu1= cu->bevobj->data; + if(cu1->key ) freedisplist_object(ob); + } + if(cu->taperobj) { + Curve *cu1= cu->taperobj->data; + if(cu1->key ) freedisplist_object(ob); } } - else if(ob->type==OB_MESH) { - if(ob->effect.first) object_wave(ob); - if(ob!=G.obedit) { - if(( ((Mesh *)(ob->data))->key )||(ob->effect.first)) makeDispList(ob); + } + else if(ob->type==OB_FONT) { + Curve *cu= ob->data; + if(cu->textoncurve) { + if( ((Curve *)cu->textoncurve->data)->key ) { + text_to_curve(ob, 0); + freedisplist_object(ob); //makeDispList(ob); } } } + else if(ob->type==OB_MESH) { + if(ob->effect.first) object_wave(ob); + if(ob!=G.obedit) { + if(( ((Mesh *)(ob->data))->key )||(ob->effect.first)) + freedisplist_object(ob); //makeDispList(ob); + } + } + } if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; else base= base->next; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 3cb2f20925f..959cb7001fb 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -53,23 +53,27 @@ #include "DNA_key_types.h" #include "DNA_ika_types.h" -#include "BKE_utildefines.h" +#include "BKE_anim.h" #include "BKE_armature.h" -#include "BKE_library.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_screen.h" +#include "BKE_curve.h" +#include "BKE_deform.h" #include "BKE_displist.h" -#include "BKE_lattice.h" +#include "BKE_global.h" +#include "BKE_ika.h" #include "BKE_key.h" +#include "BKE_lattice.h" +#include "BKE_library.h" +#include "BKE_main.h" #include "BKE_object.h" -#include "BKE_ika.h" -#include "BKE_curve.h" +#include "BKE_screen.h" +#include "BKE_utildefines.h" #ifdef HAVE_CONFIG_H #include <config.h> #endif +#include "blendef.h" + Lattice *editLatt=0, *deformLatt=0; float *latticedata=0, latmat[4][4]; @@ -236,6 +240,7 @@ void init_latt_deform(Object *oblatt, Object *ob) fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata"); + lattice_modifier(oblatt, 's'); bp= deformLatt->def; if(ob) where_is_object(ob); @@ -279,6 +284,9 @@ void init_latt_deform(Object *oblatt, Object *ob) } vec[2]+= dw; } + + lattice_modifier(oblatt, 'e'); + } void calc_latt_deform(float *co) @@ -383,6 +391,119 @@ void end_latt_deform() latticedata= 0; } + /* calculations is in local space of deformed object + so we store in latmat transform from path coord inside object + */ +typedef struct { + float dmin[3], dmax[3], dsize, dloc[3]; + float curvespace[4][4], objectspace[4][4]; +} CurveDeform; + +static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd) +{ + Mat4Invert(ob->imat, ob->obmat); + Mat4MulMat4(cd->objectspace, par->obmat, ob->imat); + Mat4Invert(cd->curvespace, cd->objectspace); + + // offset vector for 'no smear' + Mat4Invert(par->imat, par->obmat); + VecMat4MulVecfl(cd->dloc, par->imat, ob->obmat[3]); + +} + +/* this makes sure we can extend for non-cyclic */ +static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir) /* returns OK */ +{ + Curve *cu= ob->data; + BevList *bl; + float ctime1; + int cycl=0; + + /* test for cyclic */ + bl= cu->bev.first; + if(bl && bl->poly> -1) cycl= 1; + + if(cycl==0) { + ctime1= CLAMPIS(ctime, 0.0, 1.0); + } + else ctime1= ctime; + + if(where_on_path(ob, ctime1, vec, dir)) { + + if(cycl==0) { + Path *path= cu->path; + float dvec[3]; + + if(ctime < 0.0) { + VecSubf(dvec, path->data+4, path->data); + VecMulf(dvec, ctime*(float)path->len); + VECADD(vec, vec, dvec); + } + else if(ctime > 1.0) { + VecSubf(dvec, path->data+4*path->len-4, path->data+4*path->len-8); + VecMulf(dvec, (ctime-1.0)*(float)path->len); + VECADD(vec, vec, dvec); + } + } + return 1; + } + return 0; +} + + /* for each point, rotate & translate to curve */ + /* use path, since it has constant distances */ + /* co: local coord, result local too */ +static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd) +{ + Curve *cu= par->data; + float fac, loc[3], dir[3], *quat, mat[3][3], cent[3]; + short upflag, index; + + if(axis==OB_POSX || axis==OB_NEGX) { + upflag= OB_POSZ; + cent[0]= 0.0; + cent[1]= co[1]; + cent[2]= co[2]; + index= 0; + } + else if(axis==OB_POSY || axis==OB_NEGY) { + upflag= OB_POSZ; + cent[0]= co[0]; + cent[1]= 0.0; + cent[2]= co[2]; + index= 1; + } + else { + upflag= OB_POSY; + cent[0]= co[0]; + cent[1]= co[1]; + cent[2]= 0.0; + index= 2; + } + /* to be sure */ + if(cu->path==NULL) calc_curvepath(par); + + /* options */ + if(cu->flag & CU_STRETCH) + fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]); + else + fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist); + + if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */ + + quat= vectoquat(dir, axis, upflag); + QuatToMat3(quat, mat); + + /* local rotation */ + Mat3MulVecfl(mat, cent); + + /* translation */ + VECADD(co, cent, loc); + + } + +} + static int _object_deform(Object *ob, int applyflag) { @@ -391,32 +512,59 @@ static int _object_deform(Object *ob, int applyflag) DispList *dl; MVert *mvert; float *fp; - int a, tot; + int a, tot, flag; - if(ob->parent==0) return 0; + if(ob->parent==NULL) return 0; /* always try to do the entire deform in this function: apply! */ - - if(ob->parent->type==OB_LATTICE) { + + if(ob->parent->type==OB_CURVE) { + CurveDeform cd; - init_latt_deform(ob->parent, ob); + if (ob->partype != PARSKEL){ + return 0; + } + cu= ob->parent->data; + flag= cu->flag; + cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist if(ob->type==OB_MESH) { + me= ob->data; + if(me->totvert==0) return 0; - dl= find_displist_create(&ob->disp, DL_VERTS); + /* init deform */ + init_curve_deform(ob->parent, ob, &cd); - mvert= me->mvert; - if(dl->verts) MEM_freeN(dl->verts); - dl->nr= me->totvert; - dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); + /* transformation to curve space, and min max*/ + INIT_MINMAX(cd.dmin, cd.dmax); + + for(a=0, mvert=me->mvert; a<me->totvert; a++, mvert++) { + Mat4MulVecfl(cd.curvespace, mvert->co); + DO_MINMAX(mvert->co, cd.dmin, cd.dmax); + } - for(a=0; a<me->totvert; a++, mvert++, fp+=3) { - if(applyflag) calc_latt_deform(mvert->co); - else { - VECCOPY(fp, mvert->co); - calc_latt_deform(fp); - } + mvert= me->mvert; + for(a=0; a<me->totvert; a++, mvert++) { + calc_curve_deform(ob->parent, mvert->co, ob->trackflag, &cd); + /* move coord back to objectspace */ + Mat4MulVecfl(cd.objectspace, mvert->co); + } + } + /* restore */ + cu->flag = flag; + return 1; + } + else if(ob->parent->type==OB_LATTICE) { + + init_latt_deform(ob->parent, ob); + + if(ob->type==OB_MESH) { + me= ob->data; + + mvert= me->mvert; + for(a=0; a<me->totvert; a++, mvert++) { + calc_latt_deform(mvert->co); } } else if(ob->type==OB_MBALL) { @@ -479,9 +627,6 @@ static int _object_deform(Object *ob, int applyflag) } } end_latt_deform(); - - boundbox_displist(ob); - return 1; } else if(ob->parent->type==OB_ARMATURE) { @@ -495,97 +640,16 @@ static int _object_deform(Object *ob, int applyflag) case OB_MESH: me= ob->data; - dl= find_displist_create(&ob->disp, DL_VERTS); - mvert= me->mvert; - if(dl->verts) MEM_freeN(dl->verts); - dl->nr= me->totvert; - dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); - - for(a=0; a<me->totvert; a++, mvert++, fp+=3) { - if(applyflag){ - calc_armature_deform(ob->parent, mvert->co, a); - } - else { - VECCOPY(fp, mvert->co); - calc_armature_deform(ob->parent, fp, a); - } + for(a=0; a<me->totvert; a++, mvert++) { + calc_armature_deform(ob->parent, mvert->co, a); } - break; - default: + case OB_CURVE: + case OB_SURF: break; } - boundbox_displist(ob); - return 1; - } - else if(ob->parent->type==OB_IKA) { - - Ika *ika; - - if(ob->partype!=PARSKEL) return 0; - - ika= ob->parent->data; - if(ika->def==0) return 0; - - init_skel_deform(ob->parent, ob); - - if(ob->type==OB_MESH) { - me= ob->data; - - dl= find_displist_create(&ob->disp, DL_VERTS); - - mvert= me->mvert; - if(dl->verts) MEM_freeN(dl->verts); - dl->nr= me->totvert; - dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); - - for(a=0; a<me->totvert; a++, mvert++, fp+=3) { - if(applyflag) calc_skel_deform(ika, mvert->co); - else { - VECCOPY(fp, mvert->co); - calc_skel_deform(ika, fp); - } - } - } - else if ELEM(ob->type, OB_CURVE, OB_SURF) { - - cu= ob->data; - if(applyflag) { - Nurb *nu; - BPoint *bp; - - nu= cu->nurb.first; - while(nu) { - if(nu->bp) { - a= nu->pntsu*nu->pntsv; - bp= nu->bp; - while(a--) { - calc_skel_deform(ika, bp->vec); - bp++; - } - } - nu= nu->next; - } - } - - /* when apply, do this too, looks more interactive */ - dl= cu->disp.first; - while(dl) { - - fp= dl->verts; - tot= dl->nr*dl->parts; - for(a=0; a<tot; a++, fp+=3) { - calc_skel_deform(ika, fp); - } - - dl= dl->next; - } - } - - boundbox_displist(ob); - return 1; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index bd7cb626182..b4b8203355b 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -148,6 +148,16 @@ void update_base_layer(Object *ob) } } +static void free_hooks(ListBase *lb) +{ + while(lb->first) { + ObHook *hook= lb->first; + if(hook->indexar) MEM_freeN(hook->indexar); + BLI_remlink(lb, hook); + MEM_freeN(hook); + } +} + /* do not free object itself */ void free_object(Object *ob) { @@ -193,7 +203,9 @@ void free_object(Object *ob) free_constraints(&ob->constraints); free_constraint_channels(&ob->constraintChannels); free_nlastrips(&ob->nlastrips); - + + free_hooks(&ob->hooks); + freedisplist(&ob->disp); BPY_free_scriptlink(&ob->scriptlink); @@ -210,6 +222,7 @@ void unlink_object(Object *ob) Scene *sce; Curve *cu; Tex *tex; + ObHook *hook; Group *group; int a; @@ -225,6 +238,9 @@ void unlink_object(Object *ob) if(ob->type==OB_LATTICE) freedisplist(&obt->disp); } if(obt->track==ob) obt->track= NULL; + for(hook=obt->hooks.first; hook; hook= hook->next) { + if(hook->parent==ob) hook->parent= NULL; + } if ELEM(obt->type, OB_CURVE, OB_FONT) { cu= obt->data; if(cu->bevobj==ob) cu->bevobj= NULL; @@ -752,7 +768,8 @@ Object *copy_object(Object *ob) id_us_plus((ID *)obn->action); for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); - obn->disp.first= obn->disp.last= 0; + obn->disp.first= obn->disp.last= NULL; + obn->hooks.first= obn->hooks.last= NULL; return obn; } @@ -969,7 +986,8 @@ void ob_parcurve(Object *ob, Object *par, float mat[][4]) if(cu->flag & CU_FOLLOW) { quat= vectoquat(dir, ob->trackflag, ob->upflag); - + + /* the tilt */ Normalise(dir); q[0]= (float)cos(0.5*vec[3]); x1= (float)sin(0.5*vec[3]); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8da7ff687c8..a9a5b16b462 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2122,7 +2122,7 @@ static void lib_link_object(FileData *fd, Main *main) bSensor *sens; bController *cont; bActuator *act; - + ObHook *hook; void *poin; int warn=0, a; @@ -2240,6 +2240,10 @@ static void lib_link_object(FileData *fd, Main *main) } lib_link_scriptlink(fd, &ob->id, &ob->scriptlink); + + for(hook= ob->hooks.first; hook; hook= hook->next) { + hook->parent= newlibadr(fd, ob->id.lib, hook->parent); + } } ob= ob->id.next; } @@ -2270,7 +2274,8 @@ static void direct_link_object(FileData *fd, Object *ob) bSensor *sens; bController *cont; bActuator *act; - + ObHook *hook; + ob->disp.first=ob->disp.last= 0; ob->pose= newdataadr(fd, ob->pose); @@ -2335,7 +2340,18 @@ static void direct_link_object(FileData *fd, Object *ob) act= act->next; } - ob->bb= 0; + link_list(fd, &ob->hooks); + for(hook= ob->hooks.first; hook; hook= hook->next) { + hook->indexar= newdataadr(fd, hook->indexar); + if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) { + int a; + for(a=0; a<hook->totindex; a++) { + SWITCH_INT(hook->indexar[a]); + } + } + } + + ob->bb= NULL; } /* ************ READ SCENE ***************** */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 94e2e804073..0bb8d378978 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -655,7 +655,8 @@ static void write_constraint_channels(WriteData *wd, ListBase *chanbase) static void write_objects(WriteData *wd, ListBase *idbase) { Object *ob; - + ObHook *hook; + ob= idbase->first; while(ob) { if(ob->id.us>0) { @@ -677,6 +678,11 @@ static void write_objects(WriteData *wd, ListBase *idbase) write_nlastrips(wd, &ob->nlastrips); writestruct(wd, DATA, "PartDeflect", 1, ob->pd); + + for(hook= ob->hooks.first; hook; hook= hook->next) { + writestruct(wd, DATA, "ObHook", 1, hook); + writedata(wd, DATA, sizeof(int)*hook->totindex, hook->indexar); + } } ob= ob->id.next; } diff --git a/source/blender/include/BDR_editcurve.h b/source/blender/include/BDR_editcurve.h index e99ce2c625f..839bf4c6802 100644 --- a/source/blender/include/BDR_editcurve.h +++ b/source/blender/include/BDR_editcurve.h @@ -33,6 +33,7 @@ #ifndef BDR_EDITCURVE_H #define BDR_EDITCURVE_H +struct Object; struct Curve; struct Nurb; struct BezTriple; @@ -89,6 +90,7 @@ void add_primitiveNurb(int type); void clear_tilt(void); void clever_numbuts_curve(void); int bezt_compare (const void *e1, const void *e2); +void curve_changes_other_objects(struct Object *ob); extern void undo_push_curve(char *name); extern void undo_clear_curve(void); diff --git a/source/blender/include/BDR_editobject.h b/source/blender/include/BDR_editobject.h index 5b1fe2552aa..a00878448fa 100644 --- a/source/blender/include/BDR_editobject.h +++ b/source/blender/include/BDR_editobject.h @@ -119,6 +119,7 @@ void mirrormenu(void); void mirror_edit(short mode); void mirror_object(short mode); void flag_edge_crease(void); +void add_hook(void); #endif /* BDR_EDITOBJECT_H */ diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 54af18adfb3..2c83b50e6e3 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -209,11 +209,14 @@ void butspace_context_switch(SpaceButs *buts, struct Base *new); #define B_ANIMBUTS 1500 #define B_RECALCPATH 1401 - +#define B_TRACKBUTS 1402 +#define B_DEL_HOOK 1403 +#define B_CLR_HOOK 1404 #define B_PRINTSPEED 1413 #define B_PRINTLEN 1414 #define B_RELKEY 1415 +#define B_CURVECHECK 1416 /* this has MAX_EFFECT settings! Next free define is 1450... */ #define B_SELEFFECT 1430 diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 59e91fa861b..bdf91f35a2f 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -174,6 +174,7 @@ typedef struct IpoCurve { #define CU_FOLLOW 16 #define CU_UV_ORCO 32 #define CU_NOPUNOFLIP 64 +#define CU_STRETCH 128 /* spacemode */ #define CU_LEFT 0 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index ac6e75f03e5..2905b2eeb09 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -89,7 +89,6 @@ typedef struct PartDeflect { float f_power; /* The power law - real gravitation is 2 (square) */ } PartDeflect; - typedef struct Object { ID id; @@ -191,7 +190,8 @@ typedef struct Object { ListBase constraints; ListBase nlastrips; - + ListBase hooks; + PartDeflect *pd; /* particle deflector/attractor/collision data */ struct Life *life; @@ -201,6 +201,24 @@ typedef struct Object { float toonedge, smoothresh; /* smoothresh is phong interpolation ray_shadow correction in render */ } Object; +typedef struct ObHook { + struct ObHook *next, *prev; + + struct Object *parent; + float parentinv[4][4]; /* matrix making current transform unmodified */ + float mat[4][4]; /* temp matrix while hooking */ + float cent[3]; /* visualization of hook */ + int pad; + + char name[32]; + + int *indexar; + int totindex, curindex; /* curindex is cache for fast lookup */ + short type, active; /* active is only first hook, for button menu */ + float force; +} ObHook; + + /* this work object is defined in object.c */ extern Object workob; diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c index 3f5765c3fb5..25698bfe5ca 100644 --- a/source/blender/renderconverter/intern/convertBlenderScene.c +++ b/source/blender/renderconverter/intern/convertBlenderScene.c @@ -68,27 +68,27 @@ #include "DNA_meta_types.h" #include "DNA_space_types.h" -#include "BKE_mesh.h" -#include "BKE_key.h" +#include "BKE_anim.h" +#include "BKE_armature.h" #include "BKE_action.h" #include "BKE_curve.h" -#include "BKE_armature.h" -#include "BKE_object.h" -#include "BKE_texture.h" -#include "BKE_material.h" -#include "BKE_main.h" -#include "BKE_mball.h" -#include "BKE_anim.h" -#include "BKE_global.h" +#include "BKE_constraint.h" +#include "BKE_displist.h" +#include "BKE_deform.h" #include "BKE_effect.h" -#include "BKE_world.h" +#include "BKE_global.h" +#include "BKE_key.h" #include "BKE_ipo.h" #include "BKE_ika.h" -#include "BKE_displist.h" #include "BKE_lattice.h" -#include "BKE_constraint.h" -#include "BKE_utildefines.h" +#include "BKE_material.h" +#include "BKE_main.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" +#include "BKE_object.h" #include "BKE_subsurf.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" #include "BKE_world.h" #include "render.h" @@ -1247,8 +1247,8 @@ static void init_render_mesh(Object *ob) me= ob->data; - /* object_deform changes imat */ - do_puno= object_deform(ob); + /* object_deform changes imat! */ + do_puno= mesh_modifier(ob, 's'); paf = give_parteff(ob); if(paf) { @@ -1299,8 +1299,6 @@ static void init_render_mesh(Object *ob) if((me->subdivdone-1)!=me->subdivr) { DispList *dlVerts; - object_deform(ob); - dlVerts= find_displist(&ob->disp, DL_VERTS); dlm= subsurf_make_dispListMesh_from_mesh(me, dlVerts?dlVerts->verts:NULL, me->subdivr, me->flag); dl= MEM_callocN(sizeof(*dl), "dl"); @@ -1317,16 +1315,19 @@ static void init_render_mesh(Object *ob) } } - if(dl==0 || dl->type!=DL_MESH) return; - dlm= dl->mesh; - - mvert= dlm->mvert; - totvert= dlm->totvert; - - if(need_orco) { - make_orco_displist_mesh(ob, me->subdivr); + if(dl==NULL || dl->type!=DL_MESH); // here used to be a return, but why? + else { + dlm= dl->mesh; + + mvert= dlm->mvert; + totvert= dlm->totvert; + + if(need_orco) { + make_orco_displist_mesh(ob, me->subdivr); + } + ms= NULL; // no stick in displistmesh } - ms= NULL; // no stick in displistmesh + } else { dlm= NULL; mvert= me->mvert; @@ -1527,7 +1528,8 @@ static void init_render_mesh(Object *ob) } if(do_puno) normalenrender(totverto, totvlako); - + + mesh_modifier(ob, 'e'); // end } /* ------------------------------------------------------------------------- */ @@ -1797,6 +1799,8 @@ static void init_render_surf(Object *ob) if(cu->orco==0 && need_orco) make_orco_surf(cu); orco= cu->orco; + curve_modifier(ob, 's'); + /* make a complete new displist, the base-displist can be different */ displist.first= displist.last= 0; nu= cu->nurb.first; @@ -1840,6 +1844,9 @@ static void init_render_surf(Object *ob) end_latt_deform(); } + /* note; deform will be included in modifier() later */ + curve_modifier(ob, 'e'); + if(ob->partype==PARSKEL && ob->parent && ob->parent->type==OB_ARMATURE) { /* bArmature *arm= ob->parent->data; */ init_armature_deform(ob->parent, ob); @@ -2162,6 +2169,8 @@ static void init_render_curve(Object *ob) nu= cu->nurb.first; if(nu==0) return; + curve_modifier(ob, 's'); + /* test displist */ if(cu->disp.first==0) makeDispList(ob); dl= cu->disp.first; @@ -2234,6 +2243,9 @@ static void init_render_curve(Object *ob) } } + /* modifier() will get deform included later */ + curve_modifier(ob, 'e'); + if(ob->parent && ob->parent->type==OB_LATTICE) { lt= ob->parent->data; init_latt_deform(ob->parent, ob); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index fb1bb652be3..8d40bb2307f 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1248,17 +1248,20 @@ static void editing_panel_curve_type(Object *ob, Curve *cu) } if(ob->type!=OB_SURF) { - + if(ob->type==OB_CURVE) { extern float prlen; // buttons_object.c, should be moved.... char str[32]; uiBlockBeginAlign(block); - uiDefButS(block, NUM, B_RECALCPATH, "PathLen:", 600,50,150,19, &cu->pathlen, 1.0, 9000.0, 0, 0, ""); - uiDefButS(block, TOG|BIT|3, B_RECALCPATH, "CurvePath", 600,30,75,19 , &cu->flag, 0, 0, 0, 0, ""); - uiDefButS(block, TOG|BIT|4, REDRAWVIEW3D, "CurveFollow",675,30,75,19, &cu->flag, 0, 0, 0, 0, ""); + uiDefButS(block, NUM, B_RECALCPATH, "PathLen:", 600,50,150,19, &cu->pathlen, 1.0, 9000.0, 0, 0, "If no speed Ipo was set, the amount of frames of the path"); + uiDefButS(block, TOG|BIT|3, B_RECALCPATH, "CurvePath", 600,30,75,19 , &cu->flag, 0, 0, 0, 0, "Enables curve to become translation path"); + uiDefButS(block, TOG|BIT|4, REDRAWVIEW3D, "CurveFollow",675,30,75,19, &cu->flag, 0, 0, 0, 0, "Makes curve path children to rotate along path"); + uiDefButS(block, TOG|BIT|7, B_CURVECHECK, "CurveStretch", 600,10,150,19, &cu->flag, 0, 0, 0, 0, "Option for curve-deform: makes deformed child to stretch along entire path"); + + uiBlockEndAlign(block); sprintf(str, "%.4f", prlen); - uiDefBut(block, BUT, B_PRINTLEN, "PrintLen", 600,10,75,19, 0, 0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, str, 675,10,75,19, 0, 1.0, 0, 0, 0, ""); + uiDefBut(block, BUT, B_PRINTLEN, "PrintLen", 600,-10,75,19, 0, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, str, 675,-10,75,19, 0, 1.0, 0, 0, 0, ""); } uiBlockBeginAlign(block); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 4314b3fa408..29fa70a1644 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -72,6 +72,7 @@ #include "BDR_editcurve.h" #include "BDR_editface.h" #include "BDR_drawobject.h" + #include "BIF_butspace.h" #include "mydevice.h" @@ -1033,18 +1034,102 @@ void object_panel_draw(Object *ob) } +void object_panel_hooks(Object *ob) +{ + uiBlock *block; + ObHook *hook; + int tothook=0, nr, active; + char *cp; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_hooks", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Draw", "Object"); + if(uiNewPanel(curarea, block, "Hooks", "Object", 320, 0, 318, 204)==0) return; + + if(ob->hooks.first==NULL) { + uiDefBut(block, LABEL, 0, "Add hooks in Editmode", 10,180,300,19, NULL, 0, 0, 0, 0, ""); + return; + } + + /* build menu */ + for(hook= ob->hooks.first; hook; hook= hook->next) tothook++; + + cp= MEM_callocN(32*tothook+32, "temp string"); + strcpy(cp, "Active Hook %t|"); + + for(hook= ob->hooks.first; hook; hook= hook->next) { + strcat(cp, hook->name); + strcat(cp, " |"); + } + /* active is stored in first hook */ + hook= ob->hooks.first; + if(hook->active<1 || hook->active > tothook) hook->active= 1; + active= hook->active; + + uiDefButS(block, MENU, B_REDR, cp, 10,180,150,19, &hook->active, 0, 0, 0, 0, "Set active hook"); + MEM_freeN(cp); + for(nr=1, hook= ob->hooks.first; hook; hook= hook->next, nr++) { + if(nr==active) break; + } + if(hook==NULL) printf("error in object_panel_hooks\n"); + + uiBlockBeginAlign(block); + uiDefButC(block, TEX, B_REDR, "Name: ", 160,180,150,19, hook->name, 0, 32, 0, 0, "Set name of hook"); + uiDefIDPoinBut(block, test_obpoin_but, B_CLR_HOOK, "Parent:", 160, 160, 150, 19, &hook->parent, "Parent Object for hook, also recalculates and clears offset"); + uiDefButF(block, NUMSLI, B_MAKEDISP, "Force: ", 160,140,150,19, &hook->force, 0.0, 1.0, 100, 0, "Set force of hook"); + + uiBlockBeginAlign(block); + uiDefBut(block, BUT, B_DEL_HOOK, "Delete", 10,100,150,19, NULL, 0.0, 0.0, 0, 0, "Delete hook"); + uiDefBut(block, BUT, B_CLR_HOOK, "Clear offset", 160,100,150,19, NULL, 0.0, 0.0, 0, 0, "Recalculate and clear offset (transform) of hook"); +} void do_object_panels(unsigned short event) { Object *ob; + ObHook *hook; Effect *eff; ob= OBACT; switch(event) { - + case B_TRACKBUTS: + ob= OBACT; + if(ob && ob->parent && ob->parent->type==OB_CURVE) freedisplist(&ob->disp); + allqueue(REDRAWVIEW3D, 0); + break; + case B_DEL_HOOK: + hook= ob->hooks.first; + if(hook) { + int active= hook->active, nr; + for(nr=1, hook=ob->hooks.first; hook; hook=hook->next, nr++) { + if(active==nr) break; + } + if(hook) { + BLI_remlink(&ob->hooks, hook); + if(hook->indexar) MEM_freeN(hook->indexar); + MEM_freeN(hook); + } + freedisplist(&ob->disp); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); + } + break; + case B_CLR_HOOK: + hook= ob->hooks.first; + if(hook) { + int active= hook->active, nr; + for(nr=1, hook=ob->hooks.first; hook; hook=hook->next, nr++) { + if(active==nr) break; + } + if(hook && hook->parent) { + Mat4Invert(hook->parent->imat, hook->parent->obmat); + /* apparently this call goes from right to left... */ + Mat4MulSerie(hook->parentinv, hook->parent->imat, ob->obmat, NULL, + NULL, NULL, NULL, NULL, NULL); + } + } + break; case B_RECALCPATH: calc_curvepath(OBACT); allqueue(REDRAWVIEW3D, 0); @@ -1079,7 +1164,11 @@ void do_object_panels(unsigned short event) allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWIPO, 0); break; - + case B_CURVECHECK: + curve_changes_other_objects(OBACT); + allqueue(REDRAWVIEW3D, 0); + break; + default: if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) { ob= OBACT; @@ -1101,7 +1190,6 @@ void do_object_panels(unsigned short event) } - static void object_panel_anim(Object *ob) { uiBlock *block; @@ -1111,12 +1199,12 @@ static void object_panel_anim(Object *ob) if(uiNewPanel(curarea, block, "Anim settings", "Object", 0, 0, 318, 204)==0) return; uiBlockBeginAlign(block); - uiDefButC(block, ROW,REDRAWVIEW3D,"TrackX", 24,190,59,19, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object"); - uiDefButC(block, ROW,REDRAWVIEW3D,"Y", 85,190,19,19, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object"); - uiDefButC(block, ROW,REDRAWVIEW3D,"Z", 104,190,19,19, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object"); - uiDefButC(block, ROW,REDRAWVIEW3D,"-X", 124,190,24,19, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object"); - uiDefButC(block, ROW,REDRAWVIEW3D,"-Y", 150,190,24,19, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object"); - uiDefButC(block, ROW,REDRAWVIEW3D,"-Z", 178,190,24,19, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object"); + uiDefButC(block, ROW,B_TRACKBUTS,"TrackX", 24,190,59,19, &ob->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object"); + uiDefButC(block, ROW,B_TRACKBUTS,"Y", 85,190,19,19, &ob->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object"); + uiDefButC(block, ROW,B_TRACKBUTS,"Z", 104,190,19,19, &ob->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object"); + uiDefButC(block, ROW,B_TRACKBUTS,"-X", 124,190,24,19, &ob->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object"); + uiDefButC(block, ROW,B_TRACKBUTS,"-Y", 150,190,24,19, &ob->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object"); + uiDefButC(block, ROW,B_TRACKBUTS,"-Z", 178,190,24,19, &ob->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object"); uiBlockBeginAlign(block); uiDefButC(block, ROW,REDRAWVIEW3D,"UpX", 226,190,45,19, &ob->upflag, 13.0, 0.0, 0, 0, "Specify the axis that points up"); uiDefButC(block, ROW,REDRAWVIEW3D,"Y", 274,190,20,19, &ob->upflag, 13.0, 1.0, 0, 0, "Specify the axis that points up"); @@ -1485,6 +1573,7 @@ void object_panels() object_panel_anim(ob); object_panel_draw(ob); + object_panel_hooks(ob); object_panel_constraint(); if(ob->type==OB_MESH) { object_panel_effects(ob); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 127ba5d5582..935901548d4 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -74,15 +74,16 @@ #include "BKE_utildefines.h" #include "BKE_curve.h" #include "BKE_constraint.h" // for the get_constraint_target function -#include "BKE_object.h" -#include "BKE_global.h" +#include "BKE_deform.h" // lattice_modifier() #include "BKE_displist.h" -#include "BKE_material.h" -#include "BKE_mball.h" -#include "BKE_ipo.h" -#include "BKE_mesh.h" #include "BKE_effect.h" +#include "BKE_global.h" +#include "BKE_ipo.h" #include "BKE_lattice.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_mball.h" +#include "BKE_object.h" #include "BIF_gl.h" #include "BIF_mywindow.h" @@ -861,6 +862,7 @@ static void drawlattice(Object *ob) cpack(0x004000); } else { + lattice_modifier(ob, 's'); bp= lt->def; } @@ -950,6 +952,8 @@ static void drawlattice(Object *ob) if(G.zbuf) glEnable(GL_DEPTH_TEST); } + else lattice_modifier(ob, 'e'); + } /* ***************** ******************** */ @@ -3701,6 +3705,33 @@ static void draw_extra_wire(Object *ob) } } +/* should be called in view space */ +static void draw_hooks(Object *ob) +{ + ObHook *hook; + float vec[3]; + + for(hook= ob->hooks.first; hook; hook= hook->next) { + + VecMat4MulVecfl(vec, ob->obmat, hook->cent); + if(hook->parent) { + setlinestyle(3); + glBegin(GL_LINES); + glVertex3fv(hook->parent->obmat[3]); + glVertex3fv(vec); + glEnd(); + setlinestyle(0); + } + + glPointSize(3.0); + bglBegin(GL_POINTS); + bglVertex3fv(vec); + bglEnd(); + glPointSize(1.0); + + } +} + void draw_object(Base *base) { PartEff *paf; @@ -3873,6 +3904,17 @@ void draw_object(Base *base) } } + /* exception for mesh..., needs to be here for outline draw */ + if(ob->type==OB_MESH) { + me= ob->data; + /* check for need for displist (it's zero when parent, key, or hook changed) */ + if(ob->disp.first==NULL) { + if(ob->parent && ob->partype==PARSKEL) makeDispList(ob); + else if(ob->hooks.first) makeDispList(ob); + else if(mesh_uses_displist(me)) makeDispList(ob); + } + } + /* draw outline for selected solid objects */ if(G.vd->flag & V3D_SELECT_OUTLINE) { if(dt>OB_WIRE && ob!=G.obedit && (G.f & G_BACKBUFSEL)==0) { @@ -3886,17 +3928,6 @@ void draw_object(Base *base) case OB_MESH: me= ob->data; -#if 0 - /* this is a source of great slowness */ - /* Force a refresh of the display list if the parent is an armature */ - if (ob->parent && ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL){ -#if 0 /* Turn this on if there are problems with deformation lag */ - where_is_armature (ob->parent); -#endif - if (ob != G.obedit) - makeDispList (ob); - } -#endif if(base->flag & OB_RADIO); else if(ob==G.obedit || (G.obedit && ob->data==G.obedit->data)) { if(dt<=OB_WIRE) drawmeshwire(ob); @@ -4013,7 +4044,7 @@ void draw_object(Base *base) if(dtx & OB_DRAWIMAGE) drawDispListwire(&ob->disp); if((dtx & OB_DRAWWIRE) && dt>=OB_SOLID) draw_extra_wire(ob); } - + if(dt<OB_SHADED) { if((ob->gameflag & OB_ACTOR) && (ob->gameflag & OB_DYNAMIC)) { float tmat[4][4], imat[4][4], vec[3]; @@ -4040,6 +4071,9 @@ void draw_object(Base *base) if((G.f & (G_BACKBUFSEL+G_PICKSEL))==0) { ListBase *list; + /* draw hook center and offset line */ + if(ob->hooks.first && ob!=G.obedit) draw_hooks(ob); + /* help lines and so */ if(ob->parent && (ob->parent->lay & G.vd->lay)) { setlinestyle(3); diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index f6fc8500642..1b2c202ae55 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -450,6 +450,8 @@ void separate_nurb() G.obedit= 0; /* displists behave different in edit mode */ makeDispList(OBACT); /* this is the separated one */ + + curve_changes_other_objects(oldob); G.obedit= oldob; BASACT= oldbase; @@ -1053,6 +1055,8 @@ void switchdirectionNurb2(void) } makeDispList(G.obedit); + curve_changes_other_objects(G.obedit); + allqueue(REDRAWVIEW3D, 0); } @@ -1714,6 +1718,8 @@ void subdivideNurb() makeDispList(G.obedit); + curve_changes_other_objects(G.obedit); + countall(); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); @@ -2298,7 +2304,10 @@ void merge_nurb() countall(); lastnu= NULL; + makeDispList(G.obedit); + curve_changes_other_objects(G.obedit); + allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); } @@ -2455,6 +2464,8 @@ void addsegment_nurb() lastnu= NULL; /* for selected */ makeDispList(G.obedit); + curve_changes_other_objects(G.obedit); + countall(); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); @@ -2653,6 +2664,24 @@ void spinNurb(float *dvec, short mode) } } +void curve_changes_other_objects(Object *ob) +{ + Base *base= FIRSTBASE; + while(base) { + if(base->lay & G.vd->lay) { + if(base->object->parent==ob && base->object->partype==PARSKEL) + freedisplist(&base->object->disp); + + if(base->object->type==OB_CURVE) { + Curve *cu= base->object->data; + if(ob==cu->bevobj || ob==cu->taperobj) + makeDispList(base->object); + } + } + base= base->next; + } +} + void addvert_Nurb(int mode) { Nurb *nu; @@ -2787,17 +2816,7 @@ void addvert_Nurb(int mode) if(mode!='e') { /* dependencies with other objects, should become event */ - Base *base= FIRSTBASE; - while(base) { - if(base->lay & G.vd->lay) { - if(base->object->type==OB_CURVE) { - Curve *cu= base->object->data; - if(G.obedit==cu->bevobj || G.obedit==cu->taperobj) - makeDispList(base->object); - } - } - base= base->next; - } + curve_changes_other_objects(G.obedit); } } @@ -2941,6 +2960,8 @@ void makecyclicNurb() nu= nu->next; } makeDispList(G.obedit); + curve_changes_other_objects(G.obedit); + } void selectconnected_nurb() @@ -3325,6 +3346,8 @@ void delNurb() countall(); makeDispList(G.obedit); + curve_changes_other_objects(G.obedit); + allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); } @@ -3880,7 +3903,8 @@ void add_primitiveCurve(int stype) BLI_addtail(&editNurb, nu); makeDispList(G.obedit); - + curve_changes_other_objects(G.obedit); + countall(); allqueue(REDRAWALL, 0); } @@ -4061,7 +4085,6 @@ void undo_push_curve(char *name) /* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at previous step */ void undo_curve_step(int step) { - Base *base; UndoElem *uel, *next; /* prevent undo to happen on wrong object */ @@ -4108,19 +4131,7 @@ void undo_curve_step(int step) lastnu= NULL; /* for selected */ makeDispList(G.obedit); - - /* dependencies with other objects */ - base= FIRSTBASE; - while(base) { - if(base->lay & G.vd->lay) { - if(base->object->type==OB_CURVE) { - Curve *cu= base->object->data; - if(G.obedit==cu->bevobj || G.obedit==cu->taperobj) - makeDispList(base->object); - } - } - base= base->next; - } + curve_changes_other_objects(G.obedit); countall(); allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index b3fdef709ec..a8399aa0bc7 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -224,14 +224,11 @@ void free_and_unlink_base(Base *base) void delete_obj(int ok) { Base *base; -extern int undo_push(char *); if(G.obpose) return; if(G.obedit) return; if(G.scene->id.lib) return; -//if (undo_push("Erase")) return; - base= FIRSTBASE; while(base) { Base *nbase= base->next; @@ -260,6 +257,381 @@ extern int undo_push(char *); allqueue(REDRAWNLA, 0); } +int return_editmesh_indexar(int **indexar, float *cent) +{ + EditMesh *em = G.editMesh; + EditVert *eve; + int *index, nr, totvert=0; + + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f & SELECT) totvert++; + } + if(totvert==0) return 0; + + *indexar= index= MEM_mallocN(4*totvert, "hook indexar"); + nr= 0; + cent[0]= cent[1]= cent[2]= 0.0; + + for(eve= em->verts.first; eve; eve= eve->next) { + if(eve->f & SELECT) { + *index= nr; index++; + VecAddf(cent, cent, eve->co); + } + nr++; + } + + VecMulf(cent, 1.0/(float)totvert); + + return totvert; +} + +static void select_editmesh_hook(ObHook *hook) +{ + EditMesh *em = G.editMesh; + EditVert *eve; + int index=0, nr=0; + + for(eve= em->verts.first; eve; eve= eve->next, nr++) { + if(nr==hook->indexar[index]) { + eve->f |= SELECT; + if(index < hook->totindex-1) index++; + } + } +} + +int return_editlattice_indexar(int **indexar, float *cent) +{ + BPoint *bp; + int *index, nr, totvert=0, a; + + // count + a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; + bp= editLatt->def; + while(a--) { + if(bp->f1 & SELECT) { + if(bp->hide==0) totvert++; + } + bp++; + } + + if(totvert==0) return 0; + + *indexar= index= MEM_mallocN(4*totvert, "hook indexar"); + nr= 0; + cent[0]= cent[1]= cent[2]= 0.0; + + a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; + bp= editLatt->def; + while(a--) { + if(bp->f1 & SELECT) { + if(bp->hide==0) { + *index= nr; index++; + VecAddf(cent, cent, bp->vec); + } + } + bp++; + nr++; + } + + VecMulf(cent, 1.0/(float)totvert); + + return totvert; +} + +static void select_editlattice_hook(ObHook *hook) +{ + BPoint *bp; + int index=0, nr=0, a; + + // count + a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw; + bp= editLatt->def; + while(a--) { + if(hook->indexar[index]==nr) { + bp->f1 |= SELECT; + if(index < hook->totindex-1) index++; + } + nr++; + bp++; + } +} + +int return_editcurve_indexar(int **indexar, float *cent) +{ + extern ListBase editNurb; + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int *index, a, nr, totvert=0; + + for(nu= editNurb.first; nu; nu= nu->next) { + if((nu->type & 7)==CU_BEZIER) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(bezt->f1 & SELECT) totvert++; + if(bezt->f2 & SELECT) totvert++; + if(bezt->f3 & SELECT) totvert++; + bezt++; + } + } + else { + bp= nu->bp; + a= nu->pntsu*nu->pntsv; + while(a--) { + if(bp->f1 & SELECT) totvert++; + bp++; + } + } + } + if(totvert==0) return 0; + + *indexar= index= MEM_mallocN(4*totvert, "hook indexar"); + nr= 0; + cent[0]= cent[1]= cent[2]= 0.0; + + for(nu= editNurb.first; nu; nu= nu->next) { + if((nu->type & 7)==CU_BEZIER) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(bezt->f1 & SELECT) { + *index= nr; index++; + VecAddf(cent, cent, bezt->vec[0]); + } + nr++; + if(bezt->f2 & SELECT) { + *index= nr; index++; + VecAddf(cent, cent, bezt->vec[1]); + } + nr++; + if(bezt->f3 & SELECT) { + *index= nr; index++; + VecAddf(cent, cent, bezt->vec[2]); + } + nr++; + bezt++; + } + } + else { + bp= nu->bp; + a= nu->pntsu*nu->pntsv; + while(a--) { + if(bp->f1 & SELECT) { + *index= nr; index++; + VecAddf(cent, cent, bp->vec); + } + nr++; + bp++; + } + } + } + + VecMulf(cent, 1.0/(float)totvert); + + return totvert; +} + +static void select_editcurve_hook(ObHook *hook) +{ + extern ListBase editNurb; + Nurb *nu; + BPoint *bp; + BezTriple *bezt; + int index=0, a, nr=0; + + for(nu= editNurb.first; nu; nu= nu->next) { + if((nu->type & 7)==CU_BEZIER) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(nr == hook->indexar[index]) { + bezt->f1 |= SELECT; + if(index<hook->totindex-1) index++; + } + nr++; + if(nr == hook->indexar[index]) { + bezt->f2 |= SELECT; + if(index<hook->totindex-1) index++; + } + nr++; + if(nr == hook->indexar[index]) { + bezt->f3 |= SELECT; + if(index<hook->totindex-1) index++; + } + nr++; + + bezt++; + } + } + else { + bp= nu->bp; + a= nu->pntsu*nu->pntsv; + while(a--) { + if(nr == hook->indexar[index]) { + bp->f1 |= SELECT; + if(index<hook->totindex-1) index++; + } + nr++; + bp++; + } + } + } +} + +void add_hook(void) +{ + Object *ob=NULL; + ObHook *hook=NULL; + float cent[3]; + int tot=0, *indexar, mode; + + if(G.obedit==NULL) return; + + if(G.obedit->hooks.first) + mode= pupmenu("Hooks %t|Add Hook, To New Empty %x1|Add Hook, To Selected Object %x2|Remove... %x3|Reassign... %x4|Select... %x5|Clear Offset...%x6"); + else + mode= pupmenu("Hooks %t|Add, New Empty %x1|Add, To Selected Object %x2"); + + if(mode<1) return; + + /* preconditions */ + + if(mode==2) { // selected object + Base *base= FIRSTBASE; + while(base) { + if TESTBASELIB(base) { + if(base!=BASACT) { + ob= base->object; + break; + } + } + base= base->next; + } + if(ob==NULL) { + error("Requires selected Object"); + return; + } + } + else if(mode!=1) { + int maxlen=0, a, nr; + char *cp; + + // make pupmenu with hooks + for(hook= G.obedit->hooks.first; hook; hook= hook->next) maxlen+=32; + + if(maxlen==0) { + error("Object has no hooks yet"); + return; + } + + cp= MEM_callocN(maxlen+32, "temp string"); + if(mode==3) strcpy(cp, "Remove %t|"); + else if(mode==4) strcpy(cp, "Reassign %t|"); + else if(mode==5) strcpy(cp, "Select %t|"); + else if(mode==6) strcpy(cp, "Clear Offset %t|"); + + for(hook= G.obedit->hooks.first; hook; hook= hook->next) { + strcat(cp, hook->name); + strcat(cp, " |"); + } + + nr= pupmenu(cp); + MEM_freeN(cp); + + if(nr<1) return; + + a= 1; + for(hook= G.obedit->hooks.first; hook; hook= hook->next, a++) { + if(a==nr) break; + } + ob= hook->parent; + } + + /* do it, new hooks or reassign */ + if(mode==1 || mode==2 || mode==4) { + + switch(G.obedit->type) { + case OB_MESH: + tot= return_editmesh_indexar(&indexar, cent); + break; + case OB_CURVE: + case OB_SURF: + tot= return_editcurve_indexar(&indexar, cent); + break; + case OB_LATTICE: + tot= return_editlattice_indexar(&indexar, cent); + break; + } + + if(tot==0) { + error("Requires selected vertices"); + } + else { + + if(mode==1) { + Base *base= BASACT; + + ob= add_object(OB_EMPTY); + /* transform cent to global coords for loc */ + VecMat4MulVecfl(ob->loc, G.obedit->obmat, cent); + + /* restore, add_object sets active */ + BASACT= base; + } + /* if mode is 2 or 4, ob has been set */ + + /* new hook */ + if(mode==1 || mode==2) { + hook= MEM_callocN(sizeof(ObHook), "new hook"); + BLI_addtail(&G.obedit->hooks, hook); + strncpy(hook->name, ob->id.name+2, 30); + hook->force= 1.0; + } + else MEM_freeN(hook->indexar); // reassign, hook was set + + hook->parent= ob; + hook->indexar= indexar; + VECCOPY(hook->cent, cent); + hook->totindex= tot; + + if(mode==1 || mode==2) { + /* matrix calculus */ + /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */ + /* (parentinv ) */ + + where_is_object(ob); + + Mat4Invert(ob->imat, ob->obmat); + /* apparently this call goes from right to left... */ + Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, + NULL, NULL, NULL, NULL, NULL); + } + } + } + else if(mode==3) { // remove + BLI_remlink(&G.obedit->hooks, hook); + MEM_freeN(hook->indexar); + MEM_freeN(hook); + } + else if(mode==5) { // select + if(G.obedit->type==OB_MESH) select_editmesh_hook(hook); + else if(G.obedit->type==OB_LATTICE) select_editlattice_hook(hook); + else if(G.obedit->type==OB_CURVE) select_editcurve_hook(hook); + else if(G.obedit->type==OB_SURF) select_editcurve_hook(hook); + } + else if(mode==6) { // clear offset + where_is_object(ob); // ob is hook->parent + + Mat4Invert(ob->imat, ob->obmat); + /* this call goes from right to left... */ + Mat4MulSerie(hook->parentinv, ob->imat, G.obedit->obmat, NULL, + NULL, NULL, NULL, NULL, NULL); + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); +} void make_track(void) { @@ -463,6 +835,7 @@ void clear_track(void) void clear_object(char mode) { Base *base; + Object *ob; float *v1, *v3, mat[3][3]; if(G.obedit) return; @@ -492,28 +865,30 @@ void clear_object(char mode) base= FIRSTBASE; while(base) { if TESTBASELIB(base) { + ob= base->object; + if(mode=='r') { - memset(base->object->rot, 0, 3*sizeof(float)); - memset(base->object->drot, 0, 3*sizeof(float)); - QuatOne(base->object->quat); - QuatOne(base->object->dquat); + memset(ob->rot, 0, 3*sizeof(float)); + memset(ob->drot, 0, 3*sizeof(float)); + QuatOne(ob->quat); + QuatOne(ob->dquat); } else if(mode=='g') { - memset(base->object->loc, 0, 3*sizeof(float)); - memset(base->object->dloc, 0, 3*sizeof(float)); + memset(ob->loc, 0, 3*sizeof(float)); + memset(ob->dloc, 0, 3*sizeof(float)); } else if(mode=='s') { - memset(base->object->dsize, 0, 3*sizeof(float)); - base->object->size[0]= 1.0; - base->object->size[1]= 1.0; - base->object->size[2]= 1.0; + memset(ob->dsize, 0, 3*sizeof(float)); + ob->size[0]= 1.0; + ob->size[1]= 1.0; + ob->size[2]= 1.0; } else if(mode=='o') { - if(base->object->parent) { - v1= base->object->loc; - v3= base->object->parentinv[3]; + if(ob->parent) { + v1= ob->loc; + v3= ob->parentinv[3]; - Mat3CpyMat4(mat, base->object->parentinv); + Mat3CpyMat4(mat, ob->parentinv); VECCOPY(v3, v1); v3[0]= -v3[0]; v3[1]= -v3[1]; @@ -521,6 +896,11 @@ void clear_object(char mode) Mat3MulVecfl(mat, v3); } } + + if(ob->parent && ob->partype==PARSKEL) + freedisplist(&ob->disp); + else if(ob->hooks.first) + freedisplist(&ob->disp); } base= base->next; } @@ -768,11 +1148,17 @@ void make_parent(void) bConstraint *con; bFollowPathConstraint *data; - mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2"); - if (mode == 0){ + mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2|Curve Deform %x3"); + if(mode==0){ return; } - else if (mode == 2){ + else if(mode==1) { + mode= PAROBJECT; + } + else if(mode==3) { + mode= PARSKEL; + } + else if(mode==2) { base= FIRSTBASE; while(base) { @@ -936,6 +1322,8 @@ void make_parent(void) } else { + /* the ifs below are horrible code (ton) */ + if(par->type==OB_IKA){ base->object->partype= mode; base->object->par1= limbnr; @@ -947,14 +1335,17 @@ void make_parent(void) else base->object->parsubstr[0]=0; } - - else if(qual & LR_ALTKEY) { - base->object->partype= PARVERT1; - } else { - base->object->partype= PAROBJECT; + if(qual & LR_ALTKEY) { + base->object->partype= PARVERT1; + } + else if(par->type==OB_CURVE) { + base->object->partype= mode; + } + else { + base->object->partype= PAROBJECT; + } } - base->object->parent= par; /* calculate inverse parent matrix? */ @@ -983,7 +1374,7 @@ void make_parent(void) } if(par->type==OB_LATTICE) makeDispList(base->object); - if(par->type==OB_IKA && mode==PARSKEL) makeDispList(base->object); + if(par->type==OB_CURVE && mode==PARSKEL) makeDispList(base->object); if(par->type==OB_ARMATURE && mode == PARSKEL){ verify_defgroups(base->object); makeDispList(base->object); @@ -3100,8 +3491,18 @@ static void setbaseflags_for_editing(int mode) /* 0,'g','r','s' */ base->flag= BA_PARSEL */ - GHash *object_to_base_hash= NULL; /* built on demand, see below - zr */ + GHash *object_to_base_hash= NULL; Base *base; + + /* moved to start of function, it is needed for hooks now too */ + if (!object_to_base_hash) { + Base *b; + object_to_base_hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + for (b= FIRSTBASE; b; b= b->next) + BLI_ghash_insert(object_to_base_hash, b->object, b); + } + copy_baseflags(); @@ -3133,14 +3534,36 @@ static void setbaseflags_for_editing(int mode) /* 0,'g','r','s' */ if(ika->parent && parsel) base->flag |= BA_WHERE_UPDATE; } + if(ob->hooks.first) { + Base *b; + ObHook *hook= ob->hooks.first; + + while(hook) { + if(hook->parent) { + Object *parsel= is_a_parent_selected(hook->parent); + + b= BLI_ghash_lookup(object_to_base_hash, hook->parent); + if(parsel || ((base->flag | b->flag) & (SELECT | BA_PARSEL)) ) { + base->flag |= BA_DISP_UPDATE; + } + } + hook= hook->next; + } + } + + if(ob->parent && ob->parent->type==OB_LATTICE) + if(ob->parent->hooks.first) base->flag |= BA_DISP_UPDATE; + if(base->flag & (SELECT | BA_PARSEL)) { base->flag |= BA_WHERE_UPDATE; if(ob->parent) { if(ob->parent->type==OB_LATTICE) base->flag |= BA_DISP_UPDATE; - if(ob->parent->type==OB_IKA && ob->partype==PARSKEL) base->flag |= BA_DISP_UPDATE; - if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) base->flag |= BA_DISP_UPDATE; + else if(ob->partype==PARSKEL) { + if ELEM3(ob->parent->type, OB_IKA, OB_CURVE, OB_ARMATURE) + base->flag |= BA_DISP_UPDATE; + } } if(ob->track) { ; @@ -3151,16 +3574,6 @@ static void setbaseflags_for_editing(int mode) /* 0,'g','r','s' */ if(ob->type==OB_MBALL) { Base *b; - /* Only bother building the object to base - * hash if we are going to be needing it... - zr - */ - if (!object_to_base_hash) { - object_to_base_hash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - - for (b= FIRSTBASE; b; b= b->next) - BLI_ghash_insert(object_to_base_hash, b->object, b); - } - b= BLI_ghash_lookup(object_to_base_hash, find_basis_mball(ob)); b->flag |= BA_DISP_UPDATE; } @@ -3693,14 +4106,16 @@ void special_trans_update(int keyflags) if(G.obedit) { if(G.obedit->type==OB_CURVE) { cu= G.obedit->data; - if(cu->flag & CU_3D) makeBevelList(G.obedit); + makeBevelList(G.obedit); // might be needed for deform calc_curvepath(G.obedit); base= FIRSTBASE; while(base) { if(base->lay & G.vd->lay) { - if(base->object->type==OB_CURVE) { + if(base->object->parent==G.obedit && base->object->partype==PARSKEL) + makeDispList(base->object); + else if(base->object->type==OB_CURVE) { Curve *cu= base->object->data; if(G.obedit==cu->bevobj || G.obedit==cu->taperobj) makeDispList(base->object); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 6300139888c..64a62af930f 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -1127,7 +1127,9 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case HKEY: if(G.obedit) { if(G.obedit->type==OB_MESH) { - if(G.qual==LR_ALTKEY) + if(G.qual==LR_CTRLKEY) + add_hook(); + else if(G.qual==LR_ALTKEY) reveal_mesh(); else if((G.qual==LR_SHIFTKEY)) hide_mesh(1); @@ -1135,7 +1137,9 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) hide_mesh(0); } else if(G.obedit->type== OB_SURF) { - if(G.qual==LR_ALTKEY) + if(G.qual==LR_CTRLKEY) + add_hook(); + else if(G.qual==LR_ALTKEY) revealNurb(); else if((G.qual==LR_SHIFTKEY)) hideNurb(1); @@ -1143,17 +1147,24 @@ void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) hideNurb(0); } else if(G.obedit->type==OB_CURVE) { - undo_push_curve("Handle change"); if(G.qual==LR_CTRLKEY) - autocalchandlesNurb_all(1); /* flag=1, selected */ - else if((G.qual==LR_SHIFTKEY)) - sethandlesNurb(1); - else if((G.qual==0)) - sethandlesNurb(3); - - makeDispList(G.obedit); - - allqueue(REDRAWVIEW3D, 0); + add_hook(); + else { + undo_push_curve("Handle change"); + if(G.qual==LR_CTRLKEY) + autocalchandlesNurb_all(1); /* flag=1, selected */ + else if((G.qual==LR_SHIFTKEY)) + sethandlesNurb(1); + else if((G.qual==0)) + sethandlesNurb(3); + + makeDispList(G.obedit); + + allqueue(REDRAWVIEW3D, 0); + } + } + else if(G.obedit->type==OB_LATTICE) { + if(G.qual==LR_CTRLKEY) add_hook(); } } else if(G.f & G_FACESELECT) |