New feature: Face Duplicators. Like vertex-duplicator, but now on a face
authorTon Roosendaal <ton@blender.org>
Wed, 29 Nov 2006 08:57:32 +0000 (08:57 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 29 Nov 2006 08:57:32 +0000 (08:57 +0000)
center, rotated according to face edges, and optionally with scale of the
face.

http://www.blender3d.org/cms/Face_Duplicator.828.0.html

Also: bugfix in undo/redo for relinking data to the UI. It was not checking
for Library data, accidentally linking non-library data with same names.

source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/library.c
source/blender/blenloader/intern/readfile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_object_types.h
source/blender/src/buttons_object.c

index db03a9581ac4c85df3db9b61bb42e868a379484f..462a5c09387c6ff7df3ccebfe453e2405131b2b5 100644 (file)
@@ -872,7 +872,7 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
 
        /* store vertexes indices in tmp union */
        for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
-               ev->tmp.l = (long) i++;
+               ev->tmp.l = (long) i;
 
        for( ; ef; ef = ef->next, ++face_r) {
                face_r->mat_nr = ef->mat_nr;
index 88af4da590d04f7432efaf236b586a1c2b0cc2a7..11099ac0d72a5b0fc4193f3906d123a2b18ab23d 100644 (file)
@@ -457,6 +457,107 @@ static void vertex_duplilist(ListBase *lb, Scene *sce, Object *par)
        dm->release(dm);
 }
 
+static void face_duplilist(ListBase *lb, Scene *sce, Object *par)
+{
+       Object *ob;
+       Base *base;
+       DerivedMesh *dm;
+       MFace *mface;
+       MVert *mvert;
+       float pmat[4][4];
+       int lay, totface, a;
+       
+       Mat4CpyMat4(pmat, par->obmat);
+       
+       lay= G.scene->lay;
+       
+       if(par==G.obedit) {
+               int totvert;
+               dm= editmesh_get_derived_cage();
+               
+               totface= dm->getNumFaces(dm);
+               mface= MEM_mallocN(sizeof(MFace)*totface, "mface temp");
+               dm->copyFaceArray(dm, mface);
+               totvert= dm->getNumVerts(dm);
+               mvert= MEM_mallocN(sizeof(MVert)*totvert, "mvert temp");
+               dm->copyVertArray(dm, mvert);
+       }
+       else {
+               dm = mesh_get_derived_deform(par);
+               
+               totface= dm->getNumFaces(dm);
+               mface= dm->getFaceArray(dm);
+               mvert= dm->getVertArray(dm);
+       }
+       
+       
+       for(base= sce->base.first; base; base= base->next) {
+               
+               if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) {
+                       ob= base->object->parent;
+                       while(ob) {
+                               if(ob==par) {
+                                       
+                                       ob= base->object;
+                                       
+                                       /* mballs have a different dupli handling */
+                                       if(ob->type!=OB_MBALL) ob->flag |= OB_DONE;     /* doesnt render */
+
+                                       for(a=0; a<totface; a++) {
+                                               float *v1= mvert[ mface[a].v1 ].co;
+                                               float *v2= mvert[ mface[a].v2 ].co;
+                                               float *v3= mvert[ mface[a].v3 ].co;
+                                               float *v4= mface[a].v4?mvert[ mface[a].v4 ].co:NULL;
+                                               float cent[3], quat[4], mat[3][3], tmat[4][4], obmat[4][4];
+
+                                               /* translation */
+                                               if(v4)
+                                                       CalcCent4f(cent, v1, v2, v3, v4);
+                                               else
+                                                       CalcCent3f(cent, v1, v2, v3);
+                                               Mat4MulVecfl(pmat, cent);
+                                               
+                                               VecSubf(cent, cent, pmat[3]);
+                                               VecAddf(cent, cent, ob->obmat[3]);
+                                               
+                                               Mat4CpyMat4(obmat, ob->obmat);
+                                               VECCOPY(obmat[3], cent);
+                                               
+                                               /* rotation */
+                                               triatoquat(v1, v2, v3, quat);
+                                               QuatToMat3(quat, mat);
+                                               
+                                               /* scale */
+                                               if(par->transflag & OB_DUPLIFACES_SCALE) {
+                                                       float size= v4?AreaQ3Dfl(v1, v2, v3, v4):AreaT3Dfl(v1, v2, v3);
+                                                       size= sqrt(size);
+                                                       Mat3MulFloat(mat[0], size);
+                                               }
+                                               
+                                               Mat4CpyMat4(tmat, obmat);
+                                               Mat4MulMat43(obmat, tmat, mat);
+                                               
+                                               new_dupli_object(lb, ob, obmat, lay, a);
+
+                                       }
+                                       
+                                       break;
+                               }
+                               ob= ob->parent;
+                       }
+               }
+       }
+       
+       if(par==G.obedit) {
+               MEM_freeN(mface);
+               MEM_freeN(mvert);
+       }
+       
+       dm->release(dm);
+}
+
+
+
 static void particle_duplilist(ListBase *lb, Scene *sce, Object *par, PartEff *paf)
 {
        Object *ob, copyob;
@@ -670,16 +771,20 @@ ListBase *object_duplilist(Scene *sce, Object *ob)
        if(ob->transflag & OB_DUPLI) {
                if(ob->transflag & OB_DUPLIVERTS) {
                        if(ob->type==OB_MESH) {
-                               if(ob->transflag & OB_DUPLIVERTS) {
-                                       PartEff *paf;
-                                       if( (paf=give_parteff(ob)) ) particle_duplilist(&duplilist, sce, ob, paf);
-                                       else vertex_duplilist(&duplilist, sce, ob);
-                               }
+                               PartEff *paf;
+                               if( (paf=give_parteff(ob)) ) 
+                                       particle_duplilist(&duplilist, sce, ob, paf);
+                               else 
+                                       vertex_duplilist(&duplilist, sce, ob);
                        }
                        else if(ob->type==OB_FONT) {
                                font_duplilist(&duplilist, ob);
                        }
                }
+               else if(ob->transflag & OB_DUPLIFACES) {
+                       if(ob->type==OB_MESH)
+                               face_duplilist(&duplilist, sce, ob);
+               }
                else if(ob->transflag & OB_DUPLIFRAMES) 
                        frames_duplilist(&duplilist, ob);
                else if(ob->transflag & OB_DUPLIGROUP) {
index 6038e70f6f22f77cab35067f6819d5401f1acfa4..68f814e6fb7349aff978c9f04b978d8a8941dfa4 100644 (file)
@@ -538,7 +538,8 @@ ID *find_id(char *type, char *name)         /* type: "OB" or "MA" etc */
        
        id= lb->first;
        while(id) {
-               if( strcmp(id->name+2, name)==0 ) return id;
+               if(id->name[2]==name[0] && strcmp(id->name+2, name)==0 ) 
+                       return id;
                id= id->next;
        }
        return 0;
index 858ec8d85467b76c39f993313c6c26500c3f345c..a80604ac3abe5ff3e0cb8e0da8f0421412b3a02e 100644 (file)
@@ -3419,26 +3419,30 @@ static void lib_link_screen(FileData *fd, Main *main)
        }
 }
 
+/* Only for undo files, or to restore a screen after reading without UI... */
 static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
 {
-       ListBase *lb;
-       ID *idn=NULL;
                
        if(id) {
-               lb= wich_libbase(mainp, GS(id->name));
+               ListBase *lb= wich_libbase(mainp, GS(id->name));
                
                if(lb) {        // there's still risk of checking corrupt mem (freed Ids in oops)
-                       idn= lb->first;
+                       ID *idn= lb->first;
+                       char *name= id->name+2;
+                       
                        while(idn) {
-                               if( strcmp(idn->name, id->name)==0) {
-                                       if(user && idn->us==0) idn->us++;
-                                       break;
+                               if(idn->name[2]==name[0] && strcmp(idn->name+2, name)==0) {
+                                       if(idn->lib==id->lib) {
+                                               if(user && idn->us==0) idn->us++;
+                                               break;
+                                       }
                                }
                                idn= idn->next;
                        }
+                       return idn;
                }
        }
-       return idn;
+       return NULL;
 }
 
 /* called from kernel/blender.c */
index 9c37e4ab4b5eab81bbde36a194f60aa556236b62..46c6d7b6696959037bf0cd3dcd76abf98d94d357 100644 (file)
@@ -253,6 +253,11 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
 
 #define B_RECALCPATH   1401
 #define B_TRACKBUTS            1402
+#define B_DUPLI_FRAME  1403
+#define B_DUPLI_VERTS  1404
+#define B_DUPLI_FACES  1405
+#define B_DUPLI_GROUP  1406
+
 
 #define B_PRINTSPEED   1413
 #define B_PRINTLEN             1414
index e336699bd65c150216621667411a2eeabb73b6c0..dd79835b0331f2d0fe21205e8702b2132ff7a7e2 100644 (file)
@@ -266,16 +266,18 @@ extern Object workob;
 #define PARSLOW                        16
 
 /* (short) transflag */
-#define OB_OFFS_LOCAL  1
-#define OB_QUAT                        2
-#define OB_NEG_SCALE   4
-#define OB_DUPLI               (8+16+256)
-#define OB_DUPLIFRAMES 8
-#define OB_DUPLIVERTS  16
-#define OB_DUPLIROT            32
-#define OB_DUPLINOSPEED        64
-#define OB_POWERTRACK  128
-#define OB_DUPLIGROUP  256
+#define OB_OFFS_LOCAL          1
+#define OB_QUAT                                2
+#define OB_NEG_SCALE           4
+#define OB_DUPLI                       (8+16+256+512)
+#define OB_DUPLIFRAMES         8
+#define OB_DUPLIVERTS          16
+#define OB_DUPLIROT                    32
+#define OB_DUPLINOSPEED                64
+#define OB_POWERTRACK          128
+#define OB_DUPLIGROUP          256
+#define OB_DUPLIFACES          512
+#define OB_DUPLIFACES_SCALE    1024
 
 /* (short) ipoflag */
 #define OB_DRAWKEY                     1
index a708e8786b5494c6c452b826c1e57a303d9f978f..39ca3703cd9c83e7df9bf80523582e5fcef57ac4 100644 (file)
@@ -1530,10 +1530,11 @@ void do_object_panels(unsigned short event)
        Effect *eff;
        
        ob= OBACT;
-
+       if(ob==NULL)
+               return;
+       
        switch(event) {
        case B_TRACKBUTS:
-               ob= OBACT;
                DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
                allqueue(REDRAWVIEW3D, 0);
                break;
@@ -1541,9 +1542,29 @@ void do_object_panels(unsigned short event)
                DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
                allqueue(REDRAWVIEW3D, 0);
                break;
+       case B_DUPLI_FRAME:
+               ob->transflag &= ~(OB_DUPLIVERTS|OB_DUPLIFACES|OB_DUPLIGROUP);
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWBUTSOBJECT, 0);
+               break;
+       case B_DUPLI_VERTS:
+               ob->transflag &= ~(OB_DUPLIFRAMES|OB_DUPLIFACES|OB_DUPLIGROUP);
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWBUTSOBJECT, 0);
+               break;
+       case B_DUPLI_FACES:
+               ob->transflag &= ~(OB_DUPLIVERTS|OB_DUPLIFRAMES|OB_DUPLIGROUP);
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWBUTSOBJECT, 0);
+               break;
+       case B_DUPLI_GROUP:
+               ob->transflag &= ~(OB_DUPLIVERTS|OB_DUPLIFRAMES|OB_DUPLIFACES);
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWBUTSOBJECT, 0);
+               break;
+               
        case B_PRINTSPEED:
-               ob= OBACT;
-               if(ob) {
+               {
                        float vec[3];
                        CFRA++;
                        do_ob_ipo(ob);
@@ -1558,8 +1579,7 @@ void do_object_panels(unsigned short event)
                }
                break;
        case B_PRINTLEN:
-               ob= OBACT;
-               if(ob && ob->type==OB_CURVE) {
+               if(ob->type==OB_CURVE) {
                        Curve *cu=ob->data;
                        
                        if(cu->path) prlen= cu->path->totdist; else prlen= -1.0;
@@ -1571,24 +1591,20 @@ void do_object_panels(unsigned short event)
                allqueue(REDRAWBUTSOBJECT, 0);
                allqueue(REDRAWBUTSEDIT, 0);
                allqueue(REDRAWIPO, 0);
-               DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                break;
        case B_CURVECHECK:
-               DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
+               DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                allqueue(REDRAWVIEW3D, 0);
                break;
        
        case B_SOFTBODY_CHANGE:
-               ob= OBACT;
-               if(ob) {
-                       ob->softflag |= OB_SB_REDO;
-                       allqueue(REDRAWBUTSOBJECT, 0);
-                       allqueue(REDRAWVIEW3D, 0);
-               }
+               ob->softflag |= OB_SB_REDO;
+               allqueue(REDRAWBUTSOBJECT, 0);
+               allqueue(REDRAWVIEW3D, 0);
                break;
        case B_SOFTBODY_DEL_VG:
-               ob= OBACT;
-               if(ob && ob->soft) {
+               if(ob->soft) {
                        ob->soft->vertgroup= 0;
                        ob->softflag |= OB_SB_REDO;
                        allqueue(REDRAWBUTSOBJECT, 0);
@@ -1596,23 +1612,19 @@ void do_object_panels(unsigned short event)
                }
                break;
        case B_SOFTBODY_BAKE:
-               ob= OBACT;
-               if(ob && ob->soft) softbody_bake(ob);
+               if(ob->soft) softbody_bake(ob);
                break;
        case B_SOFTBODY_BAKE_FREE:
-               ob= OBACT;
-               if(ob && ob->soft) sbObjectToSoftbody(ob);
+               if(ob->soft) sbObjectToSoftbody(ob);
                allqueue(REDRAWBUTSOBJECT, 0);
                allqueue(REDRAWVIEW3D, 0);
                break;
        case B_FLUIDSIM_BAKE:
-               ob= OBACT;
                /* write config files (currently no simulation) */
                fluidsimBake(ob);
                break;
        case B_FLUIDSIM_MAKEPART:
-               ob= OBACT;
-               if(1) {
+               {
                        PartEff *paf= NULL;
                        /* prepare fluidsim particle display */
                        // simplified delete effect, create new - recalc some particles...
@@ -1634,9 +1646,9 @@ void do_object_panels(unsigned short event)
                allqueue(REDRAWVIEW3D, 0);
                allqueue(REDRAWBUTSOBJECT, 0);
                break;
-       case B_FLUIDSIM_SELDIR: {
+       case B_FLUIDSIM_SELDIR: 
+               {
                        ScrArea *sa = closest_bigger_area();
-                       ob= OBACT;
                        /* choose dir for surface files */
                        areawinset(sa->win);
                        activate_fileselect(FILE_SPECIAL, "Select Directory", ob->fluidsimSettings->surfdataPath, fluidsimFilesel);
@@ -1649,26 +1661,23 @@ void do_object_panels(unsigned short event)
                DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                break;
        case B_GROUP_RELINK:
-               group_relink_nla_objects(OBACT);
+               group_relink_nla_objects(ob);
                allqueue(REDRAWVIEW3D, 0);
                break;
                
        default:
                if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
-                       ob= OBACT;
-                       if(ob) {
-                               int a=B_SELEFFECT;
+                       int a=B_SELEFFECT;
+                       
+                       eff= ob->effect.first;
+                       while(eff) {
+                               if(event==a) eff->flag |= SELECT;
+                               else eff->flag &= ~SELECT;
                                
-                               eff= ob->effect.first;
-                               while(eff) {
-                                       if(event==a) eff->flag |= SELECT;
-                                       else eff->flag &= ~SELECT;
-                                       
-                                       a++;
-                                       eff= eff->next;
-                               }
-                               allqueue(REDRAWBUTSOBJECT, 0);
+                               a++;
+                               eff= eff->next;
                        }
+                       allqueue(REDRAWBUTSOBJECT, 0);
                }
        }
 
@@ -1839,13 +1848,18 @@ static void object_panel_anim(Object *ob)
        uiDefButBitS(block, TOG, PARSLOW, 0, "SlowPar",                                 260,155,56,19, &ob->partype, 0, 0, 0, 0, "Create a delay in the parent relationship");
        uiBlockBeginAlign(block);
        
-       uiDefButBitS(block, TOG, OB_DUPLIFRAMES, REDRAWVIEW3D, "DupliFrames",   24,130,89,20, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
-       uiDefButBitS(block, TOG, OB_DUPLIVERTS, REDRAWVIEW3D, "DupliVerts",             114,130,82,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
-       uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot",                              200,130,31,20, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to vertnormal");
-       uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed",             234,130,82,20, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
-       
-       uiDefButBitS(block, TOG, OB_DUPLIGROUP, REDRAWVIEW3D, "DupliGroup",             24,110,150,20, &ob->transflag, 0, 0, 0, 0, "Enable group instancing");
-       uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_GROUP_RELINK, "GR:", 174,110,142,20, &ob->dup_group, "Instance an existing group");
+       uiDefButBitS(block, TOG, OB_DUPLIFRAMES, B_DUPLI_FRAME, "DupliFrames",  24,130,95,20, &ob->transflag, 0, 0, 0, 0, "Make copy of object for every frame");
+       uiDefButBitS(block, TOG, OB_DUPLIVERTS, B_DUPLI_VERTS, "DupliVerts",            119,130,95,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all vertices");
+       uiDefButBitS(block, TOG, OB_DUPLIFACES, B_DUPLI_FACES, "DupliFaces",            214,130,102,20, &ob->transflag, 0, 0, 0, 0, "Duplicate child objects on all faces");
+       uiDefButBitS(block, TOG, OB_DUPLIGROUP, B_DUPLI_GROUP, "DupliGroup",            24,110,150,20, &ob->transflag, 0, 0, 0, 0, "Enable group instancing");
+       if(ob->transflag & OB_DUPLIFRAMES)
+               uiDefButBitS(block, TOG, OB_DUPLINOSPEED, REDRAWVIEW3D, "No Speed",             174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Set dupliframes to still, regardless of frame");
+       else if(ob->transflag & OB_DUPLIVERTS)
+               uiDefButBitS(block, TOG, OB_DUPLIROT, REDRAWVIEW3D, "Rot",                              174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Rotate dupli according to vertex normal");
+       else if(ob->transflag & OB_DUPLIFACES)
+               uiDefButBitS(block, TOG, OB_DUPLIFACES_SCALE, REDRAWVIEW3D, "Scale",                    174,110,142,20, &ob->transflag, 0, 0, 0, 0, "Scale dupli based on face size");
+       else
+               uiDefIDPoinBut(block, test_grouppoin_but, ID_GR, B_GROUP_RELINK, "GR:", 174,110,142,20, &ob->dup_group, "Instance an existing group");
 
        uiBlockBeginAlign(block);
        /* DupSta and DupEnd are both shorts, so the maxframe is greater then their range