Two in one:
[blender.git] / source / blender / src / editmesh_mods.c
index c5958be912b61ae4e34dd339302cce02142a199a..5944c77e045fe2aab415ac3ac2b226b7dad560d9 100644 (file)
@@ -102,6 +102,7 @@ editmesh_mods.c, UI level access, no geometry changes
 
 #include "RE_render_ext.h"  /* externtex */
 
+#include "multires.h"
 #include "mydevice.h"
 #include "blendef.h"
 
@@ -331,7 +332,7 @@ int EM_init_backbuf_circle(short xs, short ys, short rads)
 
 static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int y, int index)
 {
-       struct { short mval[2], pass, select; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
+       struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } *data = userData;
 
        if (data->pass==0) {
                if (index<=data->lastIndex)
@@ -343,7 +344,12 @@ static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int
 
        if (data->dist>3) {
                int temp = abs(data->mval[0] - x) + abs(data->mval[1]- y);
-               if ((eve->f&1)==data->select) temp += 5;
+               if ((eve->f&1) == data->select) {
+                       if (data->strict == 1)
+                               return;
+                       else
+                               temp += 5;
+               }
 
                if (temp<data->dist) {
                        data->dist = temp;
@@ -352,26 +358,49 @@ static void findnearestvert__doClosest(void *userData, EditVert *eve, int x, int
                }
        }
 }
-EditVert *findnearestvert(short *dist, short sel)
+
+
+
+
+static unsigned int findnearestvert__backbufIndextest(unsigned int index){
+               EditVert *eve = BLI_findlink(&G.editMesh->verts, index-1);
+               if(eve && (eve->f & SELECT)) return 0;
+               return 1; 
+}
+/**
+ * findnearestvert
+ * 
+ * dist (in/out): minimal distance to the nearest and at the end, actual distance
+ * sel: selection bias
+ *             if SELECT, selected vertice are given a 5 pixel bias to make them farter than unselect verts
+ *             if 0, unselected vertice are given the bias
+ * strict: if 1, the vertice corresponding to the sel parameter are ignored and not just biased 
+ */
+EditVert *findnearestvert(int *dist, short sel, short strict)
 {
        short mval[2];
 
        getmouseco_areawin(mval);
+       if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)){
+               int distance;
+               unsigned int index;
+               EditVert *eve;
                
-       if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
-               short distance;
-               unsigned int index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance);
-               EditVert *eve = BLI_findlink(&G.editMesh->verts, index-1);
-
-               if (eve && distance < *dist) {
+               if(strict) index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance, strict, findnearestvert__backbufIndextest); 
+               else index = sample_backbuf_rect(mval, 50, em_wireoffs, 0xFFFFFF, &distance, 0, NULL); 
+               
+               eve = BLI_findlink(&G.editMesh->verts, index-1);
+               
+               if(eve && distance < *dist) {
                        *dist = distance;
                        return eve;
                } else {
                        return NULL;
                }
+                       
        }
        else {
-               struct { short mval[2], pass, select; int dist, lastIndex, closestIndex; EditVert *closest; } data;
+               struct { short mval[2], pass, select, strict; int dist, lastIndex, closestIndex; EditVert *closest; } data;
                static int lastSelectedIndex=0;
                static EditVert *lastSelected=NULL;
 
@@ -385,6 +414,7 @@ EditVert *findnearestvert(short *dist, short sel)
                data.mval[1] = mval[1];
                data.select = sel;
                data.dist = *dist;
+               data.strict = strict;
                data.closest = NULL;
                data.closestIndex = 0;
 
@@ -421,9 +451,9 @@ static float labda_PdistVL2Dfl( float *v1, float *v2, float *v3)
 /* note; uses G.vd, so needs active 3d window */
 static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
 {
-       struct { float mval[2]; short dist; EditEdge *closest; } *data = userData;
+       struct { float mval[2]; int dist; EditEdge *closest; } *data = userData;
        float v1[2], v2[2];
-       short distance;
+       int distance;
                
        v1[0] = x0;
        v1[1] = y0;
@@ -454,15 +484,15 @@ static void findnearestedge__doClosest(void *userData, EditEdge *eed, int x0, in
                }
        }
 }
-EditEdge *findnearestedge(short *dist)
+EditEdge *findnearestedge(int *dist)
 {
        short mval[2];
                
        getmouseco_areawin(mval);
 
        if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
-               short distance;
-               unsigned int index = sample_backbuf_rect(mval, 50, em_solidoffs, em_wireoffs, &distance);
+               int distance;
+               unsigned int index = sample_backbuf_rect(mval, 50, em_solidoffs, em_wireoffs, &distance,0, NULL);
                EditEdge *eed = BLI_findlink(&G.editMesh->edges, index-1);
 
                if (eed && distance<*dist) {
@@ -473,7 +503,7 @@ EditEdge *findnearestedge(short *dist)
                }
        }
        else {
-               struct { float mval[2]; short dist; EditEdge *closest; } data;
+               struct { float mval[2]; int dist; EditEdge *closest; } data;
 
                data.mval[0] = mval[0];
                data.mval[1] = mval[1];
@@ -489,10 +519,10 @@ EditEdge *findnearestedge(short *dist)
 
 static void findnearestface__getDistance(void *userData, EditFace *efa, int x, int y, int index)
 {
-       struct { short mval[2], dist; EditFace *toFace; } *data = userData;
+       struct { short mval[2]; int dist; EditFace *toFace; } *data = userData;
 
        if (efa==data->toFace) {
-               short temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+               int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
 
                if (temp<data->dist)
                        data->dist = temp;
@@ -500,7 +530,7 @@ static void findnearestface__getDistance(void *userData, EditFace *efa, int x, i
 }
 static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int y, int index)
 {
-       struct { short mval[2], pass, dist; int lastIndex, closestIndex; EditFace *closest; } *data = userData;
+       struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } *data = userData;
 
        if (data->pass==0) {
                if (index<=data->lastIndex)
@@ -511,7 +541,7 @@ static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int
        }
 
        if (data->dist>3) {
-               short temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
+               int temp = abs(data->mval[0]-x) + abs(data->mval[1]-y);
 
                if (temp<data->dist) {
                        data->dist = temp;
@@ -520,7 +550,7 @@ static void findnearestface__doClosest(void *userData, EditFace *efa, int x, int
                }
        }
 }
-static EditFace *findnearestface(short *dist)
+static EditFace *findnearestface(int *dist)
 {
        short mval[2];
 
@@ -531,7 +561,7 @@ static EditFace *findnearestface(short *dist)
                EditFace *efa = BLI_findlink(&G.editMesh->faces, index-1);
 
                if (efa) {
-                       struct { short mval[2], dist; EditFace *toFace; } data;
+                       struct { short mval[2]; int dist; EditFace *toFace; } data;
 
                        data.mval[0] = mval[0];
                        data.mval[1] = mval[1];
@@ -549,7 +579,7 @@ static EditFace *findnearestface(short *dist)
                return NULL;
        }
        else {
-               struct { short mval[2], pass, dist; int lastIndex, closestIndex; EditFace *closest; } data;
+               struct { short mval[2], pass; int dist, lastIndex, closestIndex; EditFace *closest; } data;
                static int lastSelectedIndex=0;
                static EditFace *lastSelected=NULL;
 
@@ -625,8 +655,7 @@ static void draw_dm_mapped_face_center(DerivedMesh *dm, EditFace *efa)
 
 static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
 {
-       int dmNeedsFree;
-       DerivedMesh *dm = editmesh_get_derived_cage(&dmNeedsFree);
+       DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
 
        glDrawBuffer(GL_FRONT);
 
@@ -714,9 +743,7 @@ static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
        /* signal that frontbuf differs from back */
        curarea->win_swap= WIN_FRONT_OK;
 
-       if (dmNeedsFree) {
-               dm->release(dm);
-       }
+       dm->release(dm);
 }
 
 
@@ -727,14 +754,14 @@ static void unified_select_draw(EditVert *eve, EditEdge *eed, EditFace *efa)
 */
 static int unified_findnearest(EditVert **eve, EditEdge **eed, EditFace **efa) 
 {
-       short dist= 75;
+       int dist= 75;
        
        *eve= NULL;
        *eed= NULL;
        *efa= NULL;
        
        if(G.scene->selectmode & SCE_SELECT_VERTEX)
-               *eve= findnearestvert(&dist, SELECT);
+               *eve= findnearestvert(&dist, SELECT, 0);
        if(G.scene->selectmode & SCE_SELECT_FACE)
                *efa= findnearestface(&dist);
 
@@ -825,18 +852,18 @@ int facegroup_select(short mode)
                                        }
                                }
                        } else if (mode==2) { /* same image */
-                               TFace *tf, *base_tf;
+                               MTFace *tf, *base_tf;
 
-                               base_tf = (TFace*)CustomData_em_get(&em->fdata, base_efa->data,
-                                                                   LAYERTYPE_TFACE);
+                               base_tf = (MTFace*)CustomData_em_get(&em->fdata, base_efa->data,
+                                                                    CD_MTFACE);
 
                                if(!base_tf)
                                        return selcount;
 
                                for(efa= em->faces.first; efa; efa= efa->next) {
                                        if (!(efa->f & SELECT) && !efa->h) {
-                                               tf = (TFace*)CustomData_em_get(&em->fdata, efa->data,
-                                                                              LAYERTYPE_TFACE);
+                                               tf = (MTFace*)CustomData_em_get(&em->fdata, efa->data,
+                                                                               CD_MTFACE);
 
                                                if(base_tf->tpage == tf->tpage) {
                                                        EM_select_face(efa, 1);
@@ -1167,20 +1194,26 @@ int vertgroup_select(short mode)
                                                        return selcount;
                                        }
                                }
-                       } else if (mode==3 && base_eve->totweight != 0) { /* vertex groups */
-                               short i,j; /*weight index*/
+                       } else if (mode==3) { /* vertex groups */
+                               MDeformVert *dvert, *base_dvert;
+                               short i, j; /* weight index */
+
+                               base_dvert= CustomData_em_get(&em->vdata, base_eve->data,
+                                       CD_MDEFORMVERT);
+
+                               if (!base_dvert || base_dvert->totweight == 0)
+                                       return selcount;
                                
                                for(eve= em->verts.first; eve; eve= eve->next) {
-                                       if (
-                                               !(eve->f & SELECT) &&
-                                               !eve->h &&
-                                               eve->totweight
-                                       ) {
+                                       dvert= CustomData_em_get(&em->vdata, eve->data,
+                                               CD_MDEFORMVERT);
+
+                                       if (dvert && !(eve->f & SELECT) && !eve->h && dvert->totweight) {
                                                /* do the extra check for selection in the following if, so were not
                                                checking verts that may be alredy selected */
-                                               for (i=0; base_eve->totweight >i && !(eve->f & SELECT); i++) { 
-                                                       for (j=0; eve->totweight >j; j++) {
-                                                               if (base_eve->dw[i].def_nr==eve->dw[j].def_nr) {
+                                               for (i=0; base_dvert->totweight >i && !(eve->f & SELECT); i++) { 
+                                                       for (j=0; dvert->totweight >j; j++) {
+                                                               if (base_dvert->dw[i].def_nr==dvert->dw[j].def_nr) {
                                                                        eve->f |= SELECT;
                                                                        selcount++;
                                                                        deselcount--;
@@ -1202,26 +1235,47 @@ int vertgroup_select(short mode)
 handles face/edge vert context and
 facegroup_select/edgegroup_select/vertgroup_select do all the work
 */
+
 void select_mesh_group_menu()
 {
        short ret;
-       int selcount;
+       int selcount, first_item=1;
+       char str[512] = "Select Grouped%t"; /* total max length is 404 at the moment */
+
+       if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+               first_item=0;
+               strcat(str, "|Verts...%x-1|    Similar Normal %x1|    Same Face Users %x2|    Shared Vertex Groups%x3");
+       }
+
+       if(G.scene->selectmode & SCE_SELECT_EDGE) {
+               if (!first_item)        strcat(str, "|%l");
+               else                            first_item=1;
+               
+               strcat(str, "|Edges...%x-1|    Similar Length %x10|    Similar Direction %x20|    Same Face Users%x30|    Similar Face Angle%x40|    Similar Crease%x50");
+       }
        
        if(G.scene->selectmode & SCE_SELECT_FACE) {
-               ret= pupmenu("Select Grouped Faces %t|Same Material %x1|Same Image %x2|Similar Area %x3|Similar Perimeter %x4|Similar Normal %x5|Similar Co-Planer %x6");
-               if (ret<1) return;
-               selcount= facegroup_select(ret);
-               
+               if (!first_item)        strcat(str, "|%l");
+               strcat(str, "|Faces...%x-1|    Same Material %x100|    Same Image %x200|    Similar Area %x300|    Similar Perimeter %x400|    Similar Normal %x500|    Similar Co-Planer %x600");
+       
+       }
+       
+       ret= pupmenu(str);
+       if (ret<1) return;
+       
+       if (ret<10) {
+               selcount= vertgroup_select(ret);
                if (selcount) { /* update if data was selected */
-                       G.totfacesel+=selcount;
+                       EM_select_flush(); /* so that selected verts, go onto select faces */
+                       G.totvertsel += selcount;
                        allqueue(REDRAWVIEW3D, 0);
-                       BIF_undo_push("Select Grouped Faces");
+                       BIF_undo_push("Select Grouped Verts");
                }
-               
-       } else if(G.scene->selectmode & SCE_SELECT_EDGE) {
-               ret= pupmenu("Select Grouped Edges%t|Similar Length %x1|Similar Direction %x2|Same Face Users%x3|Similar Adjacent Face Angle%x4|Similar Crease%x5");
-               if (ret<1) return;
-               selcount= edgegroup_select(ret);
+               return;
+       }
+       
+       if (ret<100) {
+               selcount= edgegroup_select(ret/10);
                
                if (selcount) { /* update if data was selected */
                        /*EM_select_flush();*/ /* dont use because it can end up selecting more edges and is not usefull*/
@@ -1229,20 +1283,18 @@ void select_mesh_group_menu()
                        allqueue(REDRAWVIEW3D, 0);
                        BIF_undo_push("Select Grouped Edges");
                }
-               
-       } else if(G.scene->selectmode & SCE_SELECT_VERTEX) {
-               ret= pupmenu("Select Grouped Verts%t|Similar Normal %x1|Same Face Users %x2|Shared Vertex Groups%x3");
-               if (ret<1) return;
-               selcount= vertgroup_select(ret);
-               
+               return;
+       }
+       
+       if (ret<1000) {
+               selcount= facegroup_select(ret/100);
                if (selcount) { /* update if data was selected */
-                       EM_select_flush(); /* so that selected verts, go onto select faces */
-                       G.totedgesel+=selcount;
+                       G.totfacesel+=selcount;
                        allqueue(REDRAWVIEW3D, 0);
-                       BIF_undo_push("Select Grouped Verts");
+                       BIF_undo_push("Select Grouped Faces");
                }
+               return;
        }
-       
 }
 
 
@@ -1528,8 +1580,8 @@ void loop_multiselect(int looptype)
 static void mouse_mesh_loop(void)
 {
        EditEdge *eed;
-       int select;
-       short dist= 50;
+       int select= 1;
+       int dist= 50;
        
        eed= findnearestedge(&dist);
        if(eed) {
@@ -2533,6 +2585,8 @@ void editmesh_mark_seam(int clear)
 {
        EditMesh *em= G.editMesh;
        EditEdge *eed;
+       
+       if(multires_level1_test()) return;
 
        /* auto-enable seams drawing */
        if(clear==0) {
@@ -2598,6 +2652,18 @@ void editmesh_mark_sharp(int set)
        allqueue(REDRAWVIEW3D, 0);
 }
 
+void BME_Menu()        {
+       short ret;
+       ret= pupmenu("BME modeller%t|Select Edges of Vert%x1");
+       
+       switch(ret)
+       {
+               case 1:
+               //BME_edges_of_vert();
+               break;
+       }
+}
+
 void Edge_Menu() {
        short ret;
 
@@ -2897,7 +2963,7 @@ static void editmesh_calc_selvert_center(float cent_r[3])
        }
 }
 
-static int tface_is_selected(TFace *tf)
+static int tface_is_selected(MTFace *tf)
 {
        return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT));
 }
@@ -2915,7 +2981,7 @@ void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis)
        norm[0]= norm[1]= norm[2]= 0.0;
        for (i=0; i<me->totface; i++) {
                MFace *mf= ((MFace*) me->mface) + i;
-               TFace *tf= ((TFace*) me->tface) + i;
+               MTFace *tf= ((MTFace*) me->mtface) + i;
 
                if (tface_is_selected(tf)) {
                        float *v1, *v2, *v3, fno[3];