Lot of code... 2 new features:
authorTon Roosendaal <ton@blender.org>
Tue, 14 Sep 2004 19:03:11 +0000 (19:03 +0000)
committerTon Roosendaal <ton@blender.org>
Tue, 14 Sep 2004 19:03:11 +0000 (19:03 +0000)
1) Curve deform
http://www.blender3d.org/cms/Curve_Deform.392.0.html
Works simple as expected, but keep track of the rotation axis
in F7 buttons (Track X Y Z)
Only Mesh deform supported now.

Code changes:
- centralized deformation calls in curve_modifiers() mesh_modifiers()
etcetera. Here also other effects can be added like wave. Now the
evaluation order is fixed, but should become optional. It also doesnt
use the Displist anymore as deform-input. That latter part is unfinished
yet.
This code also is used for Hooks and will be needed for softbody

- made convention stricter that displists are being checked on in
drawobject(), this to prevent routines to make new displists recursively
(like armature does). Now a freedisplist() is sufficient to signal that
a new displaylist should be made.

2) Object Hooks
http://www.blender3d.org/cms/Object_Hooks.391.0.html
Support for Hooks is added to Mesh, Lattice, Curve and Surface objects.
For Armatures this would require some more work & research.
Main goal for this feature is to provide quick & simple access to the
underlying geometry in Objects on Object level, supporting hierarchies and
Ipos etc.

22 files changed:
source/blender/blenkernel/BKE_deform.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/deform.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/object.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BDR_editcurve.h
source/blender/include/BDR_editobject.h
source/blender/include/butspace.h
source/blender/makesdna/DNA_curve_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/renderconverter/intern/convertBlenderScene.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/drawobject.c
source/blender/src/editcurve.c
source/blender/src/editobject.c
source/blender/src/space.c

index e7494f28fc446347ba0e3c2825990d2309b617e7..411225b0635054c68624170d9cf9e3ce0822f902 100644 (file)
@@ -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
 
index 3bd2ff432b9ab17ecdec6c99568de25e04a3f034..a5384ee2ae238a7c73b96faedc8fe3603d879e67 100644 (file)
@@ -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
index fc7953c051d03cf0de47a9043ca4bd607192376a..1cd442a539126a9840d346f29fc91840ea6d2935 100644 (file)
@@ -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);
index ae73d7f5059d7b32a9ddb1bbcdf0acdec0ddb487..0c30e53ec16cb54f64fce3a4f91bc3994bb2fcc1 100644 (file)
@@ -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)
index f1ba0324fc8c151fe561d2051a5b0e4e78694688..f3eab76a46565ce850826610e78da809ff9f8f0c 100644 (file)
  */
 
 #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;
+}
+
index 821a1a5bd7c1d09939dcb63c8e9a33cfc1e4a855..932eccb23573cccf3cb4cf96a20871de129aa85a 100644 (file)
@@ -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;
index 3cb2f20925f941c0c8c70a84894ec253498d39b8..959cb7001fb3af3343963c00e1f4259579769ba9 100644 (file)
 #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;
        }
        
index bd7cb626182b8ea237162f8504be4fd8bc72af06..b4b8203355bf2a35b6809f84c8c88ae2b04f1ba6 100644 (file)
@@ -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]);
index 8da7ff687c83dc6ff318d90614f51a0eddc92410..a9a5b16b46237f464ea56d13a6fa6b874e88ee9e 100644 (file)
@@ -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 ***************** */
index 94e2e8040738aa4183654ce7f91bbea69e7efcc3..0bb8d3789782d3789a35d8601b9cf092a1b4e42f 100644 (file)
@@ -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;
        }
index e99ce2c625f6405f600f6540842cec790268330c..839bf4c68025a51e3a159e42eb8e16b0e209f2d0 100644 (file)
@@ -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);
index 5b1fe2552aa97d20f962c935d7f64e45cab07e7e..a00878448fa869742de2a7695a852615ab34e82d 100644 (file)
@@ -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 */
 
index 54af18adfb337620d0474addb88cb5a4d3543180..2c83b50e6e3fc5e27f1b7c2b46adc43dc68dbcd2 100644 (file)
@@ -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    
index 59e91fa861b152de6752cfc1bf5fcf049009930a..bdf91f35a2f01cd87ca3b26054f49c32739fe3b7 100644 (file)
@@ -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
index ac6e75f03e5f7a02037e0cc471292de8cb57bedb..2905b2eeb0962206b23e184c1baa66feb119a565 100644 (file)
@@ -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;
 
index 3f5765c3fb5f5df84c3d5460c8e495f80ce54f98..25698bfe5ca0f0579c56d5179a1b9e1054b6419d 100644 (file)
 #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);
index fb1bb652be3891998a7825333a93131f0eb523f5..8d40bb2307f2ee2ea4e2b44f61cb1e9b9ec57c68 100644 (file)
@@ -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);
index 4314b3fa408d313ac4e7033cd842fa2b88a1fd2f..29fa70a1644571205c6e5e00a472f31ffdce5b80 100644 (file)
@@ -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);
index 127ba5d5582cf8b44d2bcbeb73dc46bcdaae5b35..935901548d4f5c90a14a807c1aeca742d5861347 100644 (file)
 #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);
index f6fc850064231f3c300129ca00f41071dd9f3944..1b2c202ae55dc298d5e72c059029c6837a3aa6fe 100644 (file)
@@ -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);
index b3fdef709ecc4c838858348282853737420b4bb3..a8399aa0bc73a689f1c81b5c2d3df6ca641b505c 100644 (file)
@@ -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);
index 6300139888c1651c47848e2dbc18669216f8f529..64a62af930f6b2191ab09b13ffc7f688231d9809 100644 (file)
@@ -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)