Blender V2.61 - r43446

editmesh_lib.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2004 by Blender Foundation
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 /*
00034 
00035 editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data
00036 
00037 */
00038 
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <math.h>
00042 
00043 #include "MEM_guardedalloc.h"
00044 
00045 #include "DNA_meshdata_types.h"
00046 #include "DNA_modifier_types.h"
00047 #include "DNA_object_types.h"
00048 #include "DNA_scene_types.h"
00049 
00050 #include "BLI_blenlib.h"
00051 #include "BLI_math.h"
00052 #include "BLI_editVert.h"
00053 #include "BLI_edgehash.h"
00054 #include "BLI_utildefines.h"
00055 
00056 #include "BKE_customdata.h"
00057 #include "BKE_context.h"
00058 #include "BKE_global.h"
00059 #include "BKE_mesh.h"
00060 
00061 
00062 #include "ED_mesh.h"
00063 #include "ED_screen.h"
00064 #include "ED_view3d.h"
00065 #include "ED_transform.h"
00066 
00067 #include "mesh_intern.h"
00068 
00069 /* Helpers for EM_set_flag_all_selectmode */
00070 #define SET_EVE_FLAG(eve, flag) \
00071     if (eve->h==0) { \
00072         if (flag & SELECT && !(eve->f & SELECT)) { \
00073             ++selvert; \
00074         } \
00075         eve->f |= flag; \
00076     }
00077 
00078 #define SET_EED_FLAG(eed, flag) \
00079     if (eed->h==0) { \
00080         if (flag & SELECT && !(eed->f & SELECT)) { \
00081             ++seledge; \
00082         } \
00083         eed->f |= flag; \
00084         SET_EVE_FLAG(eed->v1, flag); \
00085         SET_EVE_FLAG(eed->v2, flag); \
00086     }
00087 
00088 
00089 /* ****************** stats *************** */
00090 
00091 int EM_nfaces_selected(EditMesh *em)
00092 {
00093     EditFace *efa;
00094     int count= 0;
00095     
00096     for (efa= em->faces.first; efa; efa= efa->next)
00097         if (efa->f & SELECT)
00098             count++;
00099     
00100     em->totfacesel= count;
00101     
00102     return count;
00103 }
00104 
00105 int EM_nedges_selected(EditMesh *em)
00106 {
00107     EditEdge *eed;
00108     int count= 0;
00109     
00110     for (eed= em->edges.first; eed; eed= eed->next) 
00111         if(eed->f & SELECT)
00112             count++;
00113     
00114     em->totedgesel= count;
00115     
00116     return count;
00117 }
00118 
00119 int EM_nvertices_selected(EditMesh *em)
00120 {
00121     EditVert *eve;
00122     int count= 0;
00123     
00124     for (eve= em->verts.first; eve; eve= eve->next)
00125         if (eve->f & SELECT)
00126             count++;
00127     
00128     em->totvertsel= count;
00129     
00130     return count;
00131 }
00132 
00133 void EM_stats_update(EditMesh *em)
00134 {
00135     
00136     em->totvert= BLI_countlist(&em->verts);
00137     em->totedge= BLI_countlist(&em->edges);
00138     em->totface= BLI_countlist(&em->faces);
00139     
00140     EM_nvertices_selected(em);
00141     EM_nedges_selected(em);
00142     EM_nfaces_selected(em);
00143 }
00144 
00145 /* ************************************** */
00146 
00147 /* this replaces the active flag used in uv/face mode */
00148 void EM_set_actFace(EditMesh *em, EditFace *efa)
00149 {
00150     em->act_face = efa;
00151 }
00152 
00153 EditFace *EM_get_actFace(EditMesh *em, int sloppy)
00154 {
00155     if (em->act_face) {
00156         return em->act_face;
00157     } else if (sloppy) {
00158         EditFace *efa= NULL;
00159         EditSelection *ese;
00160         
00161         ese = em->selected.last;
00162         for (; ese; ese=ese->prev){
00163             if(ese->type == EDITFACE) {
00164                 efa = (EditFace *)ese->data;
00165                 
00166                 if (efa->h) efa= NULL;
00167                 else        break;
00168             }
00169         }
00170         if (efa==NULL) {
00171             for (efa= em->faces.first; efa; efa= efa->next) {
00172                 if (efa->f & SELECT)
00173                     break;
00174             }
00175         }
00176         return efa; /* can still be null */
00177     }
00178     return NULL;
00179 }
00180 
00181 int EM_get_actSelection(EditMesh *em, EditSelection *ese)
00182 {
00183     EditSelection *ese_last = em->selected.last;
00184     EditFace *efa = EM_get_actFace(em, 0);
00185 
00186     ese->next = ese->prev = NULL;
00187     
00188     if (ese_last) {
00189         if (ese_last->type == EDITFACE) { /* if there is an active face, use it over the last selected face */
00190             if (efa) {
00191                 ese->data = (void *)efa;
00192             } else {
00193                 ese->data = ese_last->data;
00194             }
00195             ese->type = EDITFACE;
00196         } else {
00197             ese->data = ese_last->data;
00198             ese->type = ese_last->type;
00199         }
00200     } else if (efa) { /* no */
00201         ese->data = (void *)efa;
00202         ese->type = EDITFACE;
00203     } else {
00204         ese->data = NULL;
00205         return 0;
00206     }
00207     return 1;
00208 }
00209 
00210 /* ********* Selection History ************ */
00211 static int EM_check_selection(EditMesh *em, void *data)
00212 {
00213     EditSelection *ese;
00214     
00215     for(ese = em->selected.first; ese; ese = ese->next){
00216         if(ese->data == data) return 1;
00217     }
00218     
00219     return 0;
00220 }
00221 
00222 void EM_remove_selection(EditMesh *em, void *data, int UNUSED(type))
00223 {
00224     EditSelection *ese;
00225     for(ese=em->selected.first; ese; ese = ese->next){
00226         if(ese->data == data){
00227             BLI_freelinkN(&(em->selected),ese);
00228             break;
00229         }
00230     }
00231 }
00232 
00233 void EM_store_selection(EditMesh *em, void *data, int type)
00234 {
00235     EditSelection *ese;
00236     if(!EM_check_selection(em, data)){
00237         ese = (EditSelection*) MEM_callocN( sizeof(EditSelection), "Edit Selection");
00238         ese->type = type;
00239         ese->data = data;
00240         BLI_addtail(&(em->selected),ese);
00241     }
00242 }
00243 
00244 void EM_validate_selections(EditMesh *em)
00245 {
00246     EditSelection *ese, *nextese;
00247 
00248     ese = em->selected.first;
00249 
00250     while(ese){
00251         nextese = ese->next;
00252         if(ese->type == EDITVERT && !(((EditVert*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
00253         else if(ese->type == EDITEDGE && !(((EditEdge*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
00254         else if(ese->type == EDITFACE && !(((EditFace*)ese->data)->f & SELECT)) BLI_freelinkN(&(em->selected), ese);
00255         ese = nextese;
00256     }
00257 }
00258 
00259 static void EM_strip_selections(EditMesh *em)
00260 {
00261     EditSelection *ese, *nextese;
00262     if(!(em->selectmode & SCE_SELECT_VERTEX)){
00263         ese = em->selected.first;
00264         while(ese){
00265             nextese = ese->next; 
00266             if(ese->type == EDITVERT) BLI_freelinkN(&(em->selected),ese);
00267             ese = nextese;
00268         }
00269     }
00270     if(!(em->selectmode & SCE_SELECT_EDGE)){
00271         ese=em->selected.first;
00272         while(ese){
00273             nextese = ese->next;
00274             if(ese->type == EDITEDGE) BLI_freelinkN(&(em->selected), ese);
00275             ese = nextese;
00276         }
00277     }
00278     if(!(em->selectmode & SCE_SELECT_FACE)){
00279         ese=em->selected.first;
00280         while(ese){
00281             nextese = ese->next;
00282             if(ese->type == EDITFACE) BLI_freelinkN(&(em->selected), ese);
00283             ese = nextese;
00284         }
00285     }
00286 }
00287 
00288 /* generic way to get data from an EditSelection type 
00289 These functions were written to be used by the Modifier widget when in Rotate about active mode,
00290 but can be used anywhere.
00291 EM_editselection_center
00292 EM_editselection_normal
00293 EM_editselection_plane
00294 */
00295 void EM_editselection_center(float *center, EditSelection *ese)
00296 {
00297     if (ese->type==EDITVERT) {
00298         EditVert *eve= ese->data;
00299         copy_v3_v3(center, eve->co);
00300     } else if (ese->type==EDITEDGE) {
00301         EditEdge *eed= ese->data;
00302         add_v3_v3v3(center, eed->v1->co, eed->v2->co);
00303         mul_v3_fl(center, 0.5);
00304     } else if (ese->type==EDITFACE) {
00305         EditFace *efa= ese->data;
00306         copy_v3_v3(center, efa->cent);
00307     }
00308 }
00309 
00310 void EM_editselection_normal(float *normal, EditSelection *ese)
00311 {
00312     if (ese->type==EDITVERT) {
00313         EditVert *eve= ese->data;
00314         copy_v3_v3(normal, eve->no);
00315     } else if (ese->type==EDITEDGE) {
00316         EditEdge *eed= ese->data;
00317         float plane[3]; /* need a plane to correct the normal */
00318         float vec[3]; /* temp vec storage */
00319         
00320         add_v3_v3v3(normal, eed->v1->no, eed->v2->no);
00321         sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
00322         
00323         /* the 2 vertex normals will be close but not at rightangles to the edge
00324         for rotate about edge we want them to be at right angles, so we need to
00325         do some extra colculation to correct the vert normals,
00326         we need the plane for this */
00327         cross_v3_v3v3(vec, normal, plane);
00328         cross_v3_v3v3(normal, plane, vec); 
00329         normalize_v3(normal);
00330         
00331     } else if (ese->type==EDITFACE) {
00332         EditFace *efa= ese->data;
00333         copy_v3_v3(normal, efa->n);
00334     }
00335 }
00336 
00337 /* Calculate a plane that is rightangles to the edge/vert/faces normal
00338 also make the plane run along an axis that is related to the geometry,
00339 because this is used for the manipulators Y axis.*/
00340 void EM_editselection_plane(float *plane, EditSelection *ese)
00341 {
00342     if (ese->type==EDITVERT) {
00343         EditVert *eve= ese->data;
00344         float vec[3]={0,0,0};
00345         
00346         if (ese->prev) { /*use previously selected data to make a useful vertex plane */
00347             EM_editselection_center(vec, ese->prev);
00348             sub_v3_v3v3(plane, vec, eve->co);
00349         } else {
00350             /* make a fake  plane thats at rightangles to the normal
00351             we cant make a crossvec from a vec thats the same as the vec
00352             unlikely but possible, so make sure if the normal is (0,0,1)
00353             that vec isnt the same or in the same direction even.*/
00354             if (eve->no[0]<0.5f)        vec[0]=1;
00355             else if (eve->no[1]<0.5f)   vec[1]=1;
00356             else                        vec[2]=1;
00357             cross_v3_v3v3(plane, eve->no, vec);
00358         }
00359     } else if (ese->type==EDITEDGE) {
00360         EditEdge *eed= ese->data;
00361 
00362         /*the plane is simple, it runs along the edge
00363         however selecting different edges can swap the direction of the y axis.
00364         this makes it less likely for the y axis of the manipulator
00365         (running along the edge).. to flip less often.
00366         at least its more predictable */
00367         if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
00368             sub_v3_v3v3(plane, eed->v2->co, eed->v1->co);
00369         else
00370             sub_v3_v3v3(plane, eed->v1->co, eed->v2->co);
00371         
00372     } else if (ese->type==EDITFACE) {
00373         EditFace *efa= ese->data;
00374         float vec[3];
00375         if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
00376             float vecA[3], vecB[3];
00377             sub_v3_v3v3(vecA, efa->v4->co, efa->v3->co);
00378             sub_v3_v3v3(vecB, efa->v1->co, efa->v2->co);
00379             add_v3_v3v3(plane, vecA, vecB);
00380             
00381             sub_v3_v3v3(vecA, efa->v1->co, efa->v4->co);
00382             sub_v3_v3v3(vecB, efa->v2->co, efa->v3->co);
00383             add_v3_v3v3(vec, vecA, vecB);                       
00384             /*use the biggest edge length*/
00385             if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
00386                 copy_v3_v3(plane, vec);
00387         } else {
00388             /*start with v1-2 */
00389             sub_v3_v3v3(plane, efa->v1->co, efa->v2->co);
00390             
00391             /*test the edge between v2-3, use if longer */
00392             sub_v3_v3v3(vec, efa->v2->co, efa->v3->co);
00393             if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
00394                 copy_v3_v3(plane, vec);
00395             
00396             /*test the edge between v1-3, use if longer */
00397             sub_v3_v3v3(vec, efa->v3->co, efa->v1->co);
00398             if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
00399                 copy_v3_v3(plane, vec);
00400         }
00401     }
00402     normalize_v3(plane);
00403 }
00404 
00405 
00406 
00407 void EM_select_face(EditFace *efa, int sel)
00408 {
00409     if(sel) {
00410         efa->f |= SELECT;
00411         efa->e1->f |= SELECT;
00412         efa->e2->f |= SELECT;
00413         efa->e3->f |= SELECT;
00414         if(efa->e4) efa->e4->f |= SELECT;
00415         efa->v1->f |= SELECT;
00416         efa->v2->f |= SELECT;
00417         efa->v3->f |= SELECT;
00418         if(efa->v4) efa->v4->f |= SELECT;
00419     }
00420     else {
00421         efa->f &= ~SELECT;
00422         efa->e1->f &= ~SELECT;
00423         efa->e2->f &= ~SELECT;
00424         efa->e3->f &= ~SELECT;
00425         if(efa->e4) efa->e4->f &= ~SELECT;
00426         efa->v1->f &= ~SELECT;
00427         efa->v2->f &= ~SELECT;
00428         efa->v3->f &= ~SELECT;
00429         if(efa->v4) efa->v4->f &= ~SELECT;
00430     }
00431 }
00432 
00433 void EM_select_edge(EditEdge *eed, int sel)
00434 {
00435     if(sel) {
00436         eed->f |= SELECT;
00437         eed->v1->f |= SELECT;
00438         eed->v2->f |= SELECT;
00439     }
00440     else {
00441         eed->f &= ~SELECT;
00442         eed->v1->f &= ~SELECT;
00443         eed->v2->f &= ~SELECT;
00444     }
00445 }
00446 
00447 void EM_select_face_fgon(EditMesh *em, EditFace *efa, int val)
00448 {
00449     short index=0;
00450     
00451     if(efa->fgonf==0) EM_select_face(efa, val);
00452     else {
00453         if(efa->e1->fgoni) index= efa->e1->fgoni;
00454         if(efa->e2->fgoni) index= efa->e2->fgoni;
00455         if(efa->e3->fgoni) index= efa->e3->fgoni;
00456         if(efa->v4 && efa->e4->fgoni) index= efa->e4->fgoni;
00457         
00458         if((index==0) && (G.f & G_DEBUG))printf("wrong fgon select\n");
00459         
00460         // select all ngon faces with index
00461         for(efa= em->faces.first; efa; efa= efa->next) {
00462             if(efa->fgonf) {
00463                 if(efa->e1->fgoni==index || efa->e2->fgoni==index || 
00464                    efa->e3->fgoni==index || (efa->e4 && efa->e4->fgoni==index) ) {
00465                     EM_select_face(efa, val);
00466                 }
00467             }
00468         }
00469     }
00470 }
00471 
00472 
00473 /* only vertices */
00474 int faceselectedOR(EditFace *efa, int flag)
00475 {
00476     if ((efa->v1->f | efa->v2->f | efa->v3->f | (efa->v4?efa->v4->f:0))&flag) {
00477         return 1;
00478     } else {
00479         return 0;
00480     }
00481 }
00482 
00483 // replace with (efa->f & SELECT)
00484 int faceselectedAND(EditFace *efa, int flag)
00485 {
00486     if ((efa->v1->f & efa->v2->f & efa->v3->f & (efa->v4?efa->v4->f:flag))&flag) {
00487         return 1;
00488     } else {
00489         return 0;
00490     }
00491 }
00492 
00493 void EM_clear_flag_all(EditMesh *em, int flag)
00494 {
00495     EditVert *eve;
00496     EditEdge *eed;
00497     EditFace *efa;
00498     
00499     for (eve= em->verts.first; eve; eve= eve->next) eve->f &= ~flag;
00500     for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~flag;
00501     for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~flag;
00502     
00503     if(flag & SELECT) {
00504         BLI_freelistN(&(em->selected));
00505         em->totvertsel= em->totedgesel= em->totfacesel= 0;
00506     }
00507 }
00508 
00509 void EM_set_flag_all(EditMesh *em, int flag)
00510 {
00511     EditVert *eve;
00512     EditEdge *eed;
00513     EditFace *efa;
00514     
00515     for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag;
00516     for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag;
00517     for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag;
00518     
00519     if(flag & SELECT) {
00520         em->totvertsel= em->totvert;
00521         em->totedgesel= em->totedge;
00522         em->totfacesel= em->totface;
00523     }
00524 }
00525 
00526 void EM_set_flag_all_selectmode(EditMesh *em, int flag)
00527 {
00528     EditVert *eve;
00529     EditEdge *eed;
00530     EditFace *efa;
00531 
00532     int selvert= 0, seledge= 0, selface= 0;
00533 
00534     if (em->selectmode & SCE_SELECT_VERTEX) {
00535         /* If vertex select mode enabled all the data could be affected */
00536         for (eve= em->verts.first; eve; eve= eve->next) if(eve->h==0) eve->f |= flag;
00537         for (eed= em->edges.first; eed; eed= eed->next) if(eed->h==0) eed->f |= flag;
00538         for (efa= em->faces.first; efa; efa= efa->next) if(efa->h==0) efa->f |= flag;
00539 
00540         if (flag & SELECT) {
00541             selvert= em->totvert;
00542             seledge= em->totedge;
00543             selface= em->totface;
00544         }
00545     } else if (em->selectmode & SCE_SELECT_EDGE) {
00546         /* If edge select mode is enabled we should affect on all edges, faces and */
00547         /* vertices, connected to them */
00548 
00549         for (eed= em->edges.first; eed; eed= eed->next) {
00550             SET_EED_FLAG(eed, flag)
00551         }
00552 
00553         for (efa= em->faces.first; efa; efa= efa->next) {
00554             if(efa->h==0) {
00555                 efa->f |= flag;
00556 
00557                 if (flag & SELECT) {
00558                     ++selface;
00559                 }
00560             }
00561         }
00562     } else if (em->selectmode & SCE_SELECT_FACE) {
00563         /* No vertex and edge select mode, only face selection */
00564         /* In face select mode only edges and vertices belongs to faces should be affected */
00565 
00566         for (efa= em->faces.first; efa; efa= efa->next) {
00567             if(efa->h==0) {
00568                 efa->f |= flag;
00569                 SET_EED_FLAG(efa->e1, flag);
00570                 SET_EED_FLAG(efa->e2, flag);
00571                 SET_EED_FLAG(efa->e3, flag);
00572 
00573                 if (efa->e4) {
00574                     SET_EED_FLAG(efa->e4, flag);
00575                 }
00576 
00577                 if (flag & SELECT) {
00578                     ++selface;
00579                 }
00580             }
00581         }
00582     }
00583 
00584     if(flag & SELECT) {
00585         em->totvertsel= selvert;
00586         em->totedgesel= seledge;
00587         em->totfacesel= selface;
00588      }
00589  }
00590 /* flush for changes in vertices only */
00591 void EM_deselect_flush(EditMesh *em)
00592 {
00593     EditEdge *eed;
00594     EditFace *efa;
00595     
00596     for(eed= em->edges.first; eed; eed= eed->next) {
00597         if(eed->v1->f & eed->v2->f & SELECT);
00598         else eed->f &= ~SELECT;
00599     }
00600     for(efa= em->faces.first; efa; efa= efa->next) {
00601         if(efa->v4) {
00602             if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT );
00603             else efa->f &= ~SELECT;
00604         }
00605         else {
00606             if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT );
00607             else efa->f &= ~SELECT;
00608         }
00609     }
00610     EM_nedges_selected(em);
00611     EM_nfaces_selected(em);
00612 }
00613 
00614 
00615 /* flush selection to edges & faces */
00616 
00617 /*  this only based on coherent selected vertices, for example when adding new
00618     objects. call clear_flag_all() before you select vertices to be sure it ends OK!
00619     
00620 */
00621 
00622 void EM_select_flush(EditMesh *em)
00623 {
00624     EditEdge *eed;
00625     EditFace *efa;
00626     
00627     for(eed= em->edges.first; eed; eed= eed->next) {
00628         if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
00629     }
00630     for(efa= em->faces.first; efa; efa= efa->next) {
00631         if(efa->v4) {
00632             if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT ) efa->f |= SELECT;
00633         }
00634         else {
00635             if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT ) efa->f |= SELECT;
00636         }
00637     }
00638     EM_nedges_selected(em);
00639     EM_nfaces_selected(em);
00640 }
00641 
00642 /* when vertices or edges can be selected, also make fgon consistent */
00643 static void check_fgons_selection(EditMesh *em)
00644 {
00645     EditFace *efa, *efan;
00646     EditEdge *eed;
00647     ListBase *lbar;
00648     int sel, desel, index, totfgon= 0;
00649     
00650     /* count amount of fgons */
00651     for(eed= em->edges.first; eed; eed= eed->next) 
00652         if(eed->fgoni>totfgon) totfgon= eed->fgoni;
00653     
00654     if(totfgon==0) return;
00655     
00656     lbar= MEM_callocN((totfgon+1)*sizeof(ListBase), "listbase array");
00657     
00658     /* put all fgons in lbar */
00659     for(efa= em->faces.first; efa; efa= efan) {
00660         efan= efa->next;
00661         index= efa->e1->fgoni;
00662         if(index==0) index= efa->e2->fgoni;
00663         if(index==0) index= efa->e3->fgoni;
00664         if(index==0 && efa->e4) index= efa->e4->fgoni;
00665         if(index) {
00666             BLI_remlink(&em->faces, efa);
00667             BLI_addtail(&lbar[index], efa);
00668         }
00669     }
00670     
00671     /* now check the fgons */
00672     for(index=1; index<=totfgon; index++) {
00673         /* we count on vertices/faces/edges being set OK, so we only have to set ngon itself */
00674         sel= desel= 0;
00675         for(efa= lbar[index].first; efa; efa= efa->next) {
00676             if(efa->e1->fgoni==0) {
00677                 if(efa->e1->f & SELECT) sel++;
00678                 else desel++;
00679             }
00680             if(efa->e2->fgoni==0) {
00681                 if(efa->e2->f & SELECT) sel++;
00682                 else desel++;
00683             }
00684             if(efa->e3->fgoni==0) {
00685                 if(efa->e3->f & SELECT) sel++;
00686                 else desel++;
00687             }
00688             if(efa->e4 && efa->e4->fgoni==0) {
00689                 if(efa->e4->f & SELECT) sel++;
00690                 else desel++;
00691             }
00692             
00693             if(sel && desel) break;
00694         }
00695 
00696         if(sel && desel) sel= 0;
00697         else if(sel) sel= 1;
00698         else sel= 0;
00699         
00700         /* select/deselect and put back */
00701         for(efa= lbar[index].first; efa; efa= efa->next) {
00702             if(sel) efa->f |= SELECT;
00703             else efa->f &= ~SELECT;
00704         }
00705         BLI_movelisttolist(&em->faces, &lbar[index]);
00706     }
00707     
00708     MEM_freeN(lbar);
00709 }
00710 
00711 
00712 /* flush to edges & faces */
00713 
00714 /* based on select mode it selects edges/faces 
00715    assumed is that verts/edges/faces were properly selected themselves
00716    with the calls above
00717 */
00718 
00719 void EM_selectmode_flush(EditMesh *em)
00720 {
00721     EditEdge *eed;
00722     EditFace *efa;
00723     
00724     // flush to edges & faces
00725     if(em->selectmode & SCE_SELECT_VERTEX) {
00726         for(eed= em->edges.first; eed; eed= eed->next) {
00727             if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
00728             else eed->f &= ~SELECT;
00729         }
00730         for(efa= em->faces.first; efa; efa= efa->next) {
00731             if(efa->v4) {
00732                 if(efa->v1->f & efa->v2->f & efa->v3->f & efa->v4->f & SELECT) efa->f |= SELECT;
00733                 else efa->f &= ~SELECT;
00734             }
00735             else {
00736                 if(efa->v1->f & efa->v2->f & efa->v3->f & SELECT) efa->f |= SELECT;
00737                 else efa->f &= ~SELECT;
00738             }
00739         }
00740     }
00741     // flush to faces
00742     else if(em->selectmode & SCE_SELECT_EDGE) {
00743         for(efa= em->faces.first; efa; efa= efa->next) {
00744             if(efa->e4) {
00745                 if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT) efa->f |= SELECT;
00746                 else efa->f &= ~SELECT;
00747             }
00748             else {
00749                 if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT) efa->f |= SELECT;
00750                 else efa->f &= ~SELECT;
00751             }
00752         }
00753     }   
00754     // make sure selected faces have selected edges too, for extrude (hack?)
00755     else if(em->selectmode & SCE_SELECT_FACE) {
00756         for(efa= em->faces.first; efa; efa= efa->next) {
00757             if(efa->f & SELECT) EM_select_face(efa, 1);
00758         }
00759     }
00760     
00761     if(!(em->selectmode & SCE_SELECT_FACE))
00762         check_fgons_selection(em);
00763 
00764     EM_nvertices_selected(em);
00765     EM_nedges_selected(em);
00766     EM_nfaces_selected(em);
00767 }
00768 
00769 void EM_convertsel(EditMesh *em, short oldmode, short selectmode)
00770 {
00771     EditVert *eve;
00772     EditEdge *eed;
00773     EditFace *efa;
00774     /*clear flags*/
00775     for(eve= em->verts.first; eve; eve= eve->next) eve->f1 = 0;
00776     for(eed= em->edges.first; eed; eed= eed->next) eed->f1 = 0;
00777     for(efa= em->faces.first; efa; efa= efa->next) efa->f1 = 0;
00778     
00779     /*have to find out what the selectionmode was previously*/
00780     if(oldmode == SCE_SELECT_VERTEX) {
00781         if(selectmode == SCE_SELECT_EDGE){
00782             /*select all edges associated with every selected vertex*/
00783             for(eed= em->edges.first; eed; eed= eed->next){
00784                 if(eed->v1->f&SELECT) eed->f1 = 1;
00785                 else if(eed->v2->f&SELECT) eed->f1 = 1;
00786             }
00787             
00788             for(eed= em->edges.first; eed; eed= eed->next){
00789                 if(eed->f1 == 1) EM_select_edge(eed,1); 
00790             }
00791         }       
00792         else if(selectmode == SCE_SELECT_FACE){
00793             /*select all faces associated with every selected vertex*/
00794             for(efa= em->faces.first; efa; efa= efa->next){
00795                 if(efa->v1->f&SELECT) efa->f1 = 1;
00796                 else if(efa->v2->f&SELECT) efa->f1 = 1;
00797                 else if(efa->v3->f&SELECT) efa->f1 = 1;
00798                 else{ 
00799                     if(efa->v4){
00800                         if(efa->v4->f&SELECT) efa->f1 =1;
00801                     }
00802                 }
00803             }
00804             for(efa= em->faces.first; efa; efa= efa->next){
00805                 if(efa->f1 == 1) EM_select_face(efa,1);
00806             }
00807         }
00808     }
00809     
00810     if(oldmode == SCE_SELECT_EDGE){
00811         if(selectmode == SCE_SELECT_FACE){
00812             for(efa= em->faces.first; efa; efa= efa->next){
00813                 if(efa->e1->f&SELECT) efa->f1 = 1;
00814                 else if(efa->e2->f&SELECT) efa->f1 = 1;
00815                 else if(efa->e3->f&SELECT) efa->f1 = 1;
00816                 else if(efa->e4){
00817                     if(efa->e4->f&SELECT) efa->f1 = 1;
00818                 }
00819             }
00820             for(efa= em->faces.first; efa; efa= efa->next){
00821                 if(efa->f1 == 1) EM_select_face(efa,1);
00822             }
00823         }
00824     }
00825     
00826     check_fgons_selection(em);
00827 
00828     EM_nvertices_selected(em);
00829     EM_nedges_selected(em);
00830     EM_nfaces_selected(em);
00831 }
00832 
00833 void EM_selectmode_to_scene(struct Scene *scene, struct Object *obedit)
00834 {
00835     scene->toolsettings->selectmode= get_mesh(obedit)->edit_mesh->selectmode;
00836 }
00837 
00838 /* when switching select mode, makes sure selection is consistent for editing */
00839 /* also for paranoia checks to make sure edge or face mode works */
00840 void EM_selectmode_set(EditMesh *em)
00841 {
00842     EditVert *eve;
00843     EditEdge *eed;
00844     EditFace *efa;
00845     
00846     EM_strip_selections(em); /*strip EditSelections from em->selected that are not relevant to new mode*/
00847     
00848     if(em->selectmode & SCE_SELECT_VERTEX) {
00849         /* vertices -> edges -> faces */
00850         for (eed= em->edges.first; eed; eed= eed->next) eed->f &= ~SELECT;
00851         for (efa= em->faces.first; efa; efa= efa->next) efa->f &= ~SELECT;
00852         
00853         EM_select_flush(em);
00854     }
00855     else if(em->selectmode & SCE_SELECT_EDGE) {
00856         /* deselect vertices, and select again based on edge select */
00857         for(eve= em->verts.first; eve; eve= eve->next) eve->f &= ~SELECT;
00858         for(eed= em->edges.first; eed; eed= eed->next) 
00859             if(eed->f & SELECT) EM_select_edge(eed, 1);
00860         /* selects faces based on edge status */
00861         EM_selectmode_flush(em);
00862     }
00863     else if(em->selectmode & SCE_SELECT_FACE) {
00864         /* deselect eges, and select again based on face select */
00865         for(eed= em->edges.first; eed; eed= eed->next) EM_select_edge(eed, 0);
00866         
00867         for(efa= em->faces.first; efa; efa= efa->next) 
00868             if(efa->f & SELECT) EM_select_face(efa, 1);
00869     }
00870 
00871     EM_nvertices_selected(em);
00872     EM_nedges_selected(em);
00873     EM_nfaces_selected(em);
00874 }
00875 
00876 /* paranoia check, actually only for entering editmode. rule:
00877 - vertex hidden, always means edge is hidden too
00878 - edge hidden, always means face is hidden too
00879 - face hidden, dont change anything
00880 */
00881 void EM_hide_reset(EditMesh *em)
00882 {
00883     EditEdge *eed;
00884     EditFace *efa;
00885     
00886     for(eed= em->edges.first; eed; eed= eed->next) 
00887         if(eed->v1->h || eed->v2->h) eed->h |= 1;
00888         
00889     for(efa= em->faces.first; efa; efa= efa->next) 
00890         if((efa->e1->h & 1) || (efa->e2->h & 1) || (efa->e3->h & 1) || (efa->e4 && (efa->e4->h & 1)))
00891             efa->h= 1;
00892         
00893 }
00894 
00895 void EM_data_interp_from_verts(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *eve, float fac)
00896 {
00897     void *src[2];
00898     float w[2];
00899 
00900     if (v1->data && v2->data) {
00901         src[0]= v1->data;
00902         src[1]= v2->data;
00903         w[0] = 1.0f-fac;
00904         w[1] = fac;
00905 
00906         CustomData_em_interp(&em->vdata, src, w, NULL, 2, eve->data);
00907     }
00908 }
00909 
00910 void EM_data_interp_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4)
00911 {
00912     float w[2][4][4];
00913     void *src[2];
00914     int count = (efa2)? 2: 1;
00915 
00916     if (efa1->data) {
00917         /* set weights for copying from corners directly to other corners */
00918         memset(w, 0, sizeof(w));
00919 
00920         w[i1/4][0][i1%4]= 1.0f;
00921         w[i2/4][1][i2%4]= 1.0f;
00922         w[i3/4][2][i3%4]= 1.0f;
00923         if (i4 != -1)
00924             w[i4/4][3][i4%4]= 1.0f;
00925 
00926         src[0]= efa1->data;
00927         src[1]= (efa2)? efa2->data: NULL;
00928 
00929         CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data);
00930     }
00931 }
00932 
00933 EditFace *EM_face_from_faces(EditMesh *em, EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4)
00934 {
00935     EditFace *efan;
00936     EditVert **v[2];
00937     
00938     v[0]= &efa1->v1;
00939     v[1]= (efa2)? &efa2->v1: NULL;
00940 
00941     efan= addfacelist(em, v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4],
00942         (i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL);
00943 
00944     EM_data_interp_from_faces(em, efa1, efa2, efan, i1, i2, i3, i4);
00945     
00946     return efan;
00947 }
00948 
00949 static void update_data_blocks(EditMesh *em, CustomData *olddata, CustomData *data)
00950 {
00951     EditFace *efa;
00952     EditVert *eve;
00953     void *block;
00954 
00955     if (data == &em->vdata) {
00956         for(eve= em->verts.first; eve; eve= eve->next) {
00957             block = NULL;
00958             CustomData_em_set_default(data, &block);
00959             CustomData_em_copy_data(olddata, data, eve->data, &block);
00960             CustomData_em_free_block(olddata, &eve->data);
00961             eve->data= block;
00962         }
00963     }
00964     else if (data == &em->fdata) {
00965         for(efa= em->faces.first; efa; efa= efa->next) {
00966             block = NULL;
00967             CustomData_em_set_default(data, &block);
00968             CustomData_em_copy_data(olddata, data, efa->data, &block);
00969             CustomData_em_free_block(olddata, &efa->data);
00970             efa->data= block;
00971         }
00972     }
00973 }
00974 
00975 void EM_add_data_layer(EditMesh *em, CustomData *data, int type, const char *name)
00976 {
00977     CustomData olddata;
00978 
00979     olddata= *data;
00980     olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
00981     CustomData_add_layer_named(data, type, CD_CALLOC, NULL, 0, name);
00982 
00983     update_data_blocks(em, &olddata, data);
00984     if (olddata.layers) MEM_freeN(olddata.layers);
00985 }
00986 
00987 void EM_free_data_layer(EditMesh *em, CustomData *data, int type)
00988 {
00989     CustomData olddata;
00990 
00991     olddata= *data;
00992     olddata.layers= (olddata.layers)? MEM_dupallocN(olddata.layers): NULL;
00993     CustomData_free_layer_active(data, type, 0);
00994 
00995     update_data_blocks(em, &olddata, data);
00996     if (olddata.layers) MEM_freeN(olddata.layers);
00997 }
00998 
00999 /* ********  EXTRUDE ********* */
01000 
01001 static void add_normal_aligned(float *nor, float *add)
01002 {
01003     if(dot_v3v3(nor, add) < -0.9999f)
01004         sub_v3_v3(nor, add);
01005     else
01006         add_v3_v3(nor, add);
01007 }
01008 
01009 static void set_edge_directions_f2(EditMesh *em, int val)
01010 {
01011     EditFace *efa;
01012     int do_all= 1;
01013     
01014     /* edge directions are used for extrude, to detect direction of edges that make new faces */
01015     /* we have set 'f2' flags in edges that need to get a direction set (e.g. get new face) */
01016     /* the val argument differs... so we need it as arg */
01017     
01018     for(efa= em->faces.first; efa; efa= efa->next) {
01019         if(efa->f & SELECT) {
01020             do_all= 0;
01021             if(efa->e1->f2<val) {
01022                 if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
01023                 else efa->e1->dir= 1;
01024             }
01025             if(efa->e2->f2<val) {
01026                 if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
01027                 else efa->e2->dir= 1;
01028             }
01029             if(efa->e3->f2<val) {
01030                 if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
01031                 else efa->e3->dir= 1;
01032             }
01033             if(efa->e4 && efa->e4->f2<val) {
01034                 if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
01035                 else efa->e4->dir= 1;
01036             }
01037         }
01038     }   
01039     /* ok, no faces done... then we at least set it for exterior edges */
01040     if(do_all) {
01041         for(efa= em->faces.first; efa; efa= efa->next) {
01042             if(efa->e1->v1 == efa->v1) efa->e1->dir= 0;
01043             else efa->e1->dir= 1;
01044             if(efa->e2->v1 == efa->v2) efa->e2->dir= 0;
01045             else efa->e2->dir= 1;
01046             if(efa->e3->v1 == efa->v3) efa->e3->dir= 0;
01047             else efa->e3->dir= 1;
01048             if(efa->e4) {
01049                 if(efa->e4->v1 == efa->v4) efa->e4->dir= 0;
01050                 else efa->e4->dir= 1;
01051             }
01052         }   
01053     }
01054 }
01055 
01056 /* individual face extrude */
01057 /* will use vertex normals for extrusion directions, so *nor is unaffected */
01058 short extrudeflag_face_indiv(EditMesh *em, short UNUSED(flag), float *UNUSED(nor))
01059 {
01060     EditVert *eve, *v1, *v2, *v3, *v4;
01061     EditEdge *eed;
01062     EditFace *efa, *nextfa;
01063     
01064     if(em==NULL) return 0;
01065     
01066     /* selected edges with 1 or more selected face become faces */
01067     /* selected faces each makes new faces */
01068     /* always remove old faces, keeps volumes manifold */
01069     /* select the new extrusion, deselect old */
01070     
01071     /* step 1; init, count faces in edges */
01072     recalc_editnormals(em);
01073     
01074     for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;  // new select flag
01075 
01076     for(eed= em->edges.first; eed; eed= eed->next) {
01077         eed->f2= 0; // amount of unselected faces
01078     }
01079     for(efa= em->faces.first; efa; efa= efa->next) {
01080         if(efa->f & SELECT);
01081         else {
01082             efa->e1->f2++;
01083             efa->e2->f2++;
01084             efa->e3->f2++;
01085             if(efa->e4) efa->e4->f2++;
01086         }
01087     }
01088 
01089     /* step 2: make new faces from faces */
01090     for(efa= em->faces.last; efa; efa= efa->prev) {
01091         if(efa->f & SELECT) {
01092             v1= addvertlist(em, efa->v1->co, efa->v1);
01093             v2= addvertlist(em, efa->v2->co, efa->v2);
01094             v3= addvertlist(em, efa->v3->co, efa->v3);
01095             
01096             v1->f1= v2->f1= v3->f1= 1;
01097             copy_v3_v3(v1->no, efa->n);
01098             copy_v3_v3(v2->no, efa->n);
01099             copy_v3_v3(v3->no, efa->n);
01100             if(efa->v4) {
01101                 v4= addvertlist(em, efa->v4->co, efa->v4); 
01102                 v4->f1= 1;
01103                 copy_v3_v3(v4->no, efa->n);
01104             }
01105             else v4= NULL;
01106             
01107             /* side faces, clockwise */
01108             addfacelist(em, efa->v2, v2, v1, efa->v1, efa, NULL);
01109             addfacelist(em, efa->v3, v3, v2, efa->v2, efa, NULL);
01110             if(efa->v4) {
01111                 addfacelist(em, efa->v4, v4, v3, efa->v3, efa, NULL);
01112                 addfacelist(em, efa->v1, v1, v4, efa->v4, efa, NULL);
01113             }
01114             else {
01115                 addfacelist(em, efa->v1, v1, v3, efa->v3, efa, NULL);
01116             }
01117             /* top face */
01118             addfacelist(em, v1, v2, v3, v4, efa, NULL);
01119         }
01120     }
01121     
01122     /* step 3: remove old faces */
01123     efa= em->faces.first;
01124     while(efa) {
01125         nextfa= efa->next;
01126         if(efa->f & SELECT) {
01127             BLI_remlink(&em->faces, efa);
01128             free_editface(em, efa);
01129         }
01130         efa= nextfa;
01131     }
01132 
01133     /* step 4: redo selection */
01134     EM_clear_flag_all(em, SELECT);
01135     
01136     for(eve= em->verts.first; eve; eve= eve->next) {
01137         if(eve->f1)  eve->f |= SELECT;
01138     }
01139     
01140     EM_select_flush(em);
01141     
01142     /* step 5; update normals after extrude */
01143     recalc_editnormals(em);
01144 
01145     return 'n';
01146 }
01147 
01148 
01149 /* extrudes individual edges */
01150 /* nor is filled with constraint vector */
01151 short extrudeflag_edges_indiv(EditMesh *em, short flag, float *nor) 
01152 {
01153     EditVert *eve;
01154     EditEdge *eed;
01155     EditFace *efa;
01156     
01157     for(eve= em->verts.first; eve; eve= eve->next) eve->tmp.v = NULL;
01158     for(eed= em->edges.first; eed; eed= eed->next) {
01159         eed->tmp.f = NULL;
01160         eed->f2= ((eed->f & flag)!=0);
01161     }
01162     
01163     set_edge_directions_f2(em, 2);
01164 
01165     /* sample for next loop */
01166     for(efa= em->faces.first; efa; efa= efa->next) {
01167         efa->e1->tmp.f = efa;
01168         efa->e2->tmp.f = efa;
01169         efa->e3->tmp.f = efa;
01170         if(efa->e4) efa->e4->tmp.f = efa;
01171     }
01172     /* make the faces */
01173     for(eed= em->edges.first; eed; eed= eed->next) {
01174         if(eed->f & flag) {
01175             if(eed->v1->tmp.v == NULL)
01176                 eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
01177             if(eed->v2->tmp.v == NULL)
01178                 eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
01179 
01180             if(eed->dir==1) 
01181                 addfacelist(em, eed->v1, eed->v2, 
01182                             eed->v2->tmp.v, eed->v1->tmp.v, 
01183                             eed->tmp.f, NULL);
01184             else 
01185                 addfacelist(em, eed->v2, eed->v1, 
01186                             eed->v1->tmp.v, eed->v2->tmp.v, 
01187                             eed->tmp.f, NULL);
01188 
01189             /* for transform */
01190             if(eed->tmp.f) {
01191                 efa = eed->tmp.f;
01192                 if (efa->f & SELECT) add_normal_aligned(nor, efa->n);
01193             }
01194         }
01195     }
01196     normalize_v3(nor);
01197     
01198     /* set correct selection */
01199     EM_clear_flag_all(em, SELECT);
01200     for(eve= em->verts.last; eve; eve= eve->prev) {
01201         if(eve->tmp.v) {
01202             eve->tmp.v->f |= flag;
01203         }
01204     }
01205 
01206     for(eed= em->edges.first; eed; eed= eed->next) {
01207         if(eed->v1->f & eed->v2->f & flag) eed->f |= flag;
01208     }
01209     
01210     /* update normals after extrude */
01211     recalc_editnormals(em);
01212 
01213     if(is_zero_v3(nor)) return 'g'; // g is grab
01214     return 'n';  // n is for normal constraint
01215 }
01216 
01217 /* extrudes individual vertices */
01218 short extrudeflag_verts_indiv(EditMesh *em, short flag, float *UNUSED(nor)) 
01219 {
01220     EditVert *eve;
01221     
01222     /* make the edges */
01223     for(eve= em->verts.first; eve; eve= eve->next) {
01224         if(eve->f & flag) {
01225             eve->tmp.v = addvertlist(em, eve->co, eve);
01226             addedgelist(em, eve, eve->tmp.v, NULL);
01227         }
01228         else eve->tmp.v = NULL;
01229     }
01230     
01231     /* set correct selection */
01232     EM_clear_flag_all(em, SELECT);
01233 
01234     for(eve= em->verts.last; eve; eve= eve->prev) 
01235         if (eve->tmp.v) 
01236             eve->tmp.v->f |= flag;
01237 
01238     return 'g'; // g is grab
01239 }
01240 
01241 
01242 /* this is actually a recode of extrudeflag(), using proper edge/face select */
01243 /* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */
01244 static short extrudeflag_edge(Object *obedit, EditMesh *em, short UNUSED(flag), float *nor, int all)
01245 {
01246     /* all select edges/faces: extrude */
01247     /* old select is cleared, in new ones it is set */
01248     EditVert *eve, *nextve;
01249     EditEdge *eed, *nexted;
01250     EditFace *efa, *nextfa, *efan;
01251     short del_old= 0;
01252     ModifierData *md;
01253     
01254     if(em==NULL) return 0;
01255 
01256     md = obedit->modifiers.first;
01257     
01258     /* selected edges with 0 or 1 selected face become faces */
01259     /* selected faces generate new faces */
01260 
01261     /* if *one* selected face has edge with unselected face; remove old selected faces */
01262     
01263     /* if selected edge is not used anymore; remove */
01264     /* if selected vertex is not used anymore: remove */
01265     
01266     /* select the new extrusion, deselect old */
01267     
01268     
01269     /* step 1; init, count faces in edges */
01270     recalc_editnormals(em);
01271     
01272     for(eve= em->verts.first; eve; eve= eve->next) {
01273         eve->tmp.v = NULL;
01274         eve->f1= 0;
01275     }
01276 
01277     for(eed= em->edges.first; eed; eed= eed->next) {
01278         eed->f1= 0; // amount of unselected faces
01279         eed->f2= 0; // amount of selected faces
01280         if(eed->f & SELECT) {
01281             eed->v1->f1= 1; // we call this 'selected vertex' now
01282             eed->v2->f1= 1;
01283         }
01284         eed->tmp.f = NULL;      // here we tuck face pointer, as sample
01285     }
01286     for(efa= em->faces.first; efa; efa= efa->next) {
01287         if(efa->f & SELECT) {
01288             efa->e1->f2++;
01289             efa->e2->f2++;
01290             efa->e3->f2++;
01291             if(efa->e4) efa->e4->f2++;
01292             
01293             // sample for next loop
01294             efa->e1->tmp.f = efa;
01295             efa->e2->tmp.f = efa;
01296             efa->e3->tmp.f = efa;
01297             if(efa->e4) efa->e4->tmp.f = efa;
01298         }
01299         else {
01300             efa->e1->f1++;
01301             efa->e2->f1++;
01302             efa->e3->f1++;
01303             if(efa->e4) efa->e4->f1++;
01304         }
01305     }
01306     
01307     /* If a mirror modifier with clipping is on, we need to adjust some 
01308      * of the cases above to handle edges on the line of symmetry.
01309      */
01310     for (; md; md=md->next) {
01311         if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
01312             MirrorModifierData *mmd = (MirrorModifierData*) md; 
01313         
01314             if(mmd->flag & MOD_MIR_CLIPPING) {
01315                 float mtx[4][4];
01316                 if (mmd->mirror_ob) {
01317                     float imtx[4][4];
01318                     invert_m4_m4(imtx, mmd->mirror_ob->obmat);
01319                     mult_m4_m4m4(mtx, imtx, obedit->obmat);
01320                 }
01321 
01322                 for (eed= em->edges.first; eed; eed= eed->next) {
01323                     if(eed->f2 == 1) {
01324                         float co1[3], co2[3];
01325 
01326                         copy_v3_v3(co1, eed->v1->co);
01327                         copy_v3_v3(co2, eed->v2->co);
01328 
01329                         if (mmd->mirror_ob) {
01330                             mul_m4_v3(mtx, co1);
01331                             mul_m4_v3(mtx, co2);
01332                         }
01333 
01334                         if (mmd->flag & MOD_MIR_AXIS_X)
01335                             if ( (fabsf(co1[0]) < mmd->tolerance) &&
01336                                  (fabsf(co2[0]) < mmd->tolerance) )
01337                                 ++eed->f2;
01338 
01339                         if (mmd->flag & MOD_MIR_AXIS_Y)
01340                             if ( (fabsf(co1[1]) < mmd->tolerance) &&
01341                                  (fabsf(co2[1]) < mmd->tolerance) )
01342                                 ++eed->f2;
01343 
01344                         if (mmd->flag & MOD_MIR_AXIS_Z)
01345                             if ( (fabsf(co1[2]) < mmd->tolerance) &&
01346                                  (fabsf(co2[2]) < mmd->tolerance) )
01347                                 ++eed->f2;
01348                     }
01349                 }
01350             }
01351         }
01352     }
01353 
01354     set_edge_directions_f2(em, 2);
01355     
01356     /* step 1.5: if *one* selected face has edge with unselected face; remove old selected faces */
01357     if(all == 0) {
01358         for(efa= em->faces.last; efa; efa= efa->prev) {
01359             if(efa->f & SELECT) {
01360                 if(efa->e1->f1 || efa->e2->f1 || efa->e3->f1 || (efa->e4 && efa->e4->f1)) {
01361                     del_old= 1;
01362                     break;
01363                 }
01364             }
01365         }
01366     }
01367                 
01368     /* step 2: make new faces from edges */
01369     for(eed= em->edges.last; eed; eed= eed->prev) {
01370         if(eed->f & SELECT) {
01371             if(eed->f2<2) {
01372                 if(eed->v1->tmp.v == NULL)
01373                     eed->v1->tmp.v = addvertlist(em, eed->v1->co, eed->v1);
01374                 if(eed->v2->tmp.v == NULL)
01375                     eed->v2->tmp.v = addvertlist(em, eed->v2->co, eed->v2);
01376 
01377                 /* if del_old, the preferred normal direction is exact 
01378                  * opposite as for keep old faces
01379                  */
01380                 if(eed->dir!=del_old) 
01381                     addfacelist(em, eed->v1, eed->v2, 
01382                                 eed->v2->tmp.v, eed->v1->tmp.v, 
01383                                 eed->tmp.f, NULL);
01384                 else 
01385                     addfacelist(em, eed->v2, eed->v1, 
01386                                 eed->v1->tmp.v, eed->v2->tmp.v,
01387                                 eed->tmp.f, NULL);
01388             }
01389         }
01390     }
01391     
01392     /* step 3: make new faces from faces */
01393     for(efa= em->faces.last; efa; efa= efa->prev) {
01394         if(efa->f & SELECT) {
01395             if (efa->v1->tmp.v == NULL)
01396                 efa->v1->tmp.v = addvertlist(em, efa->v1->co, efa->v1);
01397             if (efa->v2->tmp.v ==NULL)
01398                 efa->v2->tmp.v = addvertlist(em, efa->v2->co, efa->v2);
01399             if (efa->v3->tmp.v ==NULL)
01400                 efa->v3->tmp.v = addvertlist(em, efa->v3->co, efa->v3);
01401             if (efa->v4 && (efa->v4->tmp.v == NULL))
01402                 efa->v4->tmp.v = addvertlist(em, efa->v4->co, efa->v4);
01403             
01404             if(efa->v4)
01405                 efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v,
01406                             efa->v3->tmp.v, efa->v4->tmp.v, efa, efa);
01407             else
01408                 efan = addfacelist(em, efa->v1->tmp.v, efa->v2->tmp.v,
01409                             efa->v3->tmp.v, NULL, efa, efa);
01410 
01411             /* keep old faces means flipping normal, reverse vertex order gives bad UV's & VCols etc - [#25260] */
01412             if(del_old==0) {
01413                 flipface(em, efan);
01414             }
01415 
01416             if (em->act_face == efa) {
01417                 em->act_face = efan; 
01418             }
01419 
01420             /* for transform */
01421             add_normal_aligned(nor, efa->n);
01422         }
01423     }
01424     
01425     if(del_old) {
01426         
01427         /* step 4: remove old faces, if del_old */
01428         efa= em->faces.first;
01429         while(efa) {
01430             nextfa= efa->next;
01431             if(efa->f & SELECT) {
01432                 BLI_remlink(&em->faces, efa);
01433                 free_editface(em, efa);
01434             }
01435             efa= nextfa;
01436         }
01437         
01438         
01439         /* step 5: remove selected unused edges */
01440         /* start tagging again */
01441         for(eed= em->edges.first; eed; eed= eed->next) eed->f1=0;
01442         for(efa= em->faces.first; efa; efa= efa->next) {
01443             efa->e1->f1= 1;
01444             efa->e2->f1= 1;
01445             efa->e3->f1= 1;
01446             if(efa->e4) efa->e4->f1= 1;
01447         }
01448         /* remove */
01449         eed= em->edges.first; 
01450         while(eed) {
01451             nexted= eed->next;
01452             if(eed->f & SELECT) {
01453                 if(eed->f1==0) {
01454                     remedge(em, eed);
01455                     free_editedge(em, eed);
01456                 }
01457             }
01458             eed= nexted;
01459         }
01460     
01461         /* step 6: remove selected unused vertices */
01462         for(eed= em->edges.first; eed; eed= eed->next) 
01463             eed->v1->f1= eed->v2->f1= 0;
01464         
01465         eve= em->verts.first;
01466         while(eve) {
01467             nextve= eve->next;
01468             if(eve->f1) {
01469                 // hack... but we need it for step 7, redoing selection
01470                 if(eve->tmp.v) eve->tmp.v->tmp.v= eve->tmp.v;
01471                 
01472                 BLI_remlink(&em->verts, eve);
01473                 free_editvert(em, eve);
01474             }
01475             eve= nextve;
01476         }
01477     }
01478     
01479     normalize_v3(nor);  // translation normal grab
01480     
01481     /* step 7: redo selection */
01482     EM_clear_flag_all(em, SELECT);
01483 
01484     for(eve= em->verts.first; eve; eve= eve->next) {
01485         if(eve->tmp.v) {
01486             eve->tmp.v->f |= SELECT;
01487         }
01488     }
01489 
01490     EM_select_flush(em);
01491 
01492     /* step 8; update normals after extrude */
01493     recalc_editnormals(em);
01494 
01495     if(is_zero_v3(nor)) return 'g'; // grab
01496     return 'n'; // normal constraint 
01497 }
01498 
01499 short extrudeflag_vert(Object *obedit, EditMesh *em, short flag, float *nor, int all)
01500 {
01501     /* all verts/edges/faces with (f & 'flag'): extrude */
01502     /* from old verts, 'flag' is cleared, in new ones it is set */
01503     EditVert *eve, *v1, *v2, *v3, *v4, *nextve;
01504     EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
01505     EditFace *efa, *efa2, *nextvl;
01506     short sel=0, del_old= 0, is_face_sel=0;
01507     ModifierData *md;
01508 
01509     if(em==NULL) return 0;
01510 
01511     md = obedit->modifiers.first;
01512 
01513     /* clear vert flag f1, we use this to detect a loose selected vertice */
01514     eve= em->verts.first;
01515     while(eve) {
01516         if(eve->f & flag) eve->f1= 1;
01517         else eve->f1= 0;
01518         eve= eve->next;
01519     }
01520     /* clear edges counter flag, if selected we set it at 1 */
01521     eed= em->edges.first;
01522     while(eed) {
01523         if( (eed->v1->f & flag) && (eed->v2->f & flag) ) {
01524             eed->f2= 1;
01525             eed->v1->f1= 0;
01526             eed->v2->f1= 0;
01527         }
01528         else eed->f2= 0;
01529         
01530         eed->f1= 1;     /* this indicates it is an 'old' edge (in this routine we make new ones) */
01531         eed->tmp.f = NULL;  /* used as sample */
01532         
01533         eed= eed->next;
01534     }
01535 
01536     /* we set a flag in all selected faces, and increase the associated edge counters */
01537 
01538     efa= em->faces.first;
01539     while(efa) {
01540         efa->f1= 0;
01541 
01542         if(faceselectedAND(efa, flag)) {
01543             e1= efa->e1;
01544             e2= efa->e2;
01545             e3= efa->e3;
01546             e4= efa->e4;
01547 
01548             if(e1->f2 < 3) e1->f2++;
01549             if(e2->f2 < 3) e2->f2++;
01550             if(e3->f2 < 3) e3->f2++;
01551             if(e4 && e4->f2 < 3) e4->f2++;
01552             
01553             efa->f1= 1;
01554             is_face_sel= 1; // for del_old
01555         }
01556         else if(faceselectedOR(efa, flag)) {
01557             e1= efa->e1;
01558             e2= efa->e2;
01559             e3= efa->e3;
01560             e4= efa->e4;
01561             
01562             if( (e1->v1->f & flag) && (e1->v2->f & flag) ) e1->f1= 2;
01563             if( (e2->v1->f & flag) && (e2->v2->f & flag) ) e2->f1= 2;
01564             if( (e3->v1->f & flag) && (e3->v2->f & flag) ) e3->f1= 2;
01565             if( e4 && (e4->v1->f & flag) && (e4->v2->f & flag) ) e4->f1= 2;
01566         }
01567         
01568         // sample for next loop
01569         efa->e1->tmp.f = efa;
01570         efa->e2->tmp.f = efa;
01571         efa->e3->tmp.f = efa;
01572         if(efa->e4) efa->e4->tmp.f = efa;
01573 
01574         efa= efa->next;
01575     }
01576 
01577     set_edge_directions_f2(em, 3);
01578 
01579     /* the current state now is:
01580         eve->f1==1: loose selected vertex 
01581 
01582         eed->f2==0 : edge is not selected, no extrude
01583         eed->f2==1 : edge selected, is not part of a face, extrude
01584         eed->f2==2 : edge selected, is part of 1 face, extrude
01585         eed->f2==3 : edge selected, is part of more faces, no extrude
01586         
01587         eed->f1==0: new edge
01588         eed->f1==1: edge selected, is part of selected face, when eed->f==3: remove
01589         eed->f1==2: edge selected, part of a partially selected face
01590                     
01591         efa->f1==1 : duplicate this face
01592     */
01593 
01594     /* If a mirror modifier with clipping is on, we need to adjust some 
01595      * of the cases above to handle edges on the line of symmetry.
01596      */
01597     for (; md; md=md->next) {
01598         if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
01599             MirrorModifierData *mmd = (MirrorModifierData*) md; 
01600         
01601             if(mmd->flag & MOD_MIR_CLIPPING) {
01602                 float mtx[4][4];
01603                 if (mmd->mirror_ob) {
01604                     float imtx[4][4];
01605                     invert_m4_m4(imtx, mmd->mirror_ob->obmat);
01606                     mult_m4_m4m4(mtx, imtx, obedit->obmat);
01607                 }
01608 
01609                 for (eed= em->edges.first; eed; eed= eed->next) {
01610                     if(eed->f2 == 2) {
01611                         float co1[3], co2[3];
01612 
01613                         copy_v3_v3(co1, eed->v1->co);
01614                         copy_v3_v3(co2, eed->v2->co);
01615 
01616                         if (mmd->mirror_ob) {
01617                             mul_m4_v3(mtx, co1);
01618                             mul_m4_v3(mtx, co2);
01619                         }
01620 
01621                         if (mmd->flag & MOD_MIR_AXIS_X)
01622                             if ( (fabsf(co1[0]) < mmd->tolerance) &&
01623                                  (fabsf(co2[0]) < mmd->tolerance) )
01624                                 ++eed->f2;
01625 
01626                         if (mmd->flag & MOD_MIR_AXIS_Y)
01627                             if ( (fabsf(co1[1]) < mmd->tolerance) &&
01628                                  (fabsf(co2[1]) < mmd->tolerance) )
01629                                 ++eed->f2;
01630                         if (mmd->flag & MOD_MIR_AXIS_Z)
01631                             if ( (fabsf(co1[2]) < mmd->tolerance) &&
01632                                  (fabsf(co2[2]) < mmd->tolerance) )
01633                                 ++eed->f2;
01634                     }
01635                 }
01636             }
01637         }
01638     }
01639 
01640     /* copy all selected vertices, */
01641     /* write pointer to new vert in old struct at eve->tmp.v */
01642     eve= em->verts.last;
01643     while(eve) {
01644         eve->f &= ~128;  /* clear, for later test for loose verts */
01645         if(eve->f & flag) {
01646             sel= 1;
01647             v1= addvertlist(em, 0, NULL);
01648             
01649             copy_v3_v3(v1->co, eve->co);
01650             copy_v3_v3(v1->no, eve->no);
01651             v1->f= eve->f;
01652             eve->f &= ~flag;
01653             eve->tmp.v = v1;
01654         }
01655         else eve->tmp.v = NULL;
01656         eve= eve->prev;
01657     }
01658 
01659     if(sel==0) return 0;
01660 
01661     /* all edges with eed->f2==1 or eed->f2==2 become faces */
01662     
01663     /* if del_old==1 then extrude is in partial geometry, to keep it manifold.
01664                      verts with f1==0 and (eve->f & 128)==0) are removed
01665                      edges with eed->f2>2 are removed
01666                      faces with efa->f1 are removed
01667        if del_old==0 the extrude creates a volume.
01668     */
01669     
01670      /* find if we delete old faces */
01671     if(is_face_sel && all==0) {
01672         for(eed= em->edges.first; eed; eed= eed->next) {
01673             if( (eed->f2==1 || eed->f2==2) ) {
01674                 if(eed->f1==2) {
01675                     del_old= 1;
01676                     break;
01677                 }
01678             }
01679         }
01680     }
01681     
01682     eed= em->edges.last;
01683     while(eed) {
01684         nexted= eed->prev;
01685         if( eed->f2<3) {
01686             eed->v1->f |= 128;  /* = no loose vert! */
01687             eed->v2->f |= 128;
01688         }
01689         if( (eed->f2==1 || eed->f2==2) ) {
01690     
01691             /* if del_old, the preferred normal direction is exact opposite as for keep old faces */
01692             if(eed->dir != del_old) 
01693                 efa2 = addfacelist(em, eed->v1, eed->v2, 
01694                                   eed->v2->tmp.v, eed->v1->tmp.v, 
01695                                   eed->tmp.f, NULL);
01696             else 
01697                 efa2 = addfacelist(em, eed->v2, eed->v1, 
01698                                    eed->v1->tmp.v, eed->v2->tmp.v, 
01699                                    eed->tmp.f, NULL);
01700             
01701             /* Needs smarter adaption of existing creases.
01702              * If addedgelist is used, make sure seams are set to 0 on these
01703              * new edges, since we do not want to add any seams on extrusion.
01704              */
01705             efa2->e1->crease= eed->crease;
01706             efa2->e2->crease= eed->crease;
01707             efa2->e3->crease= eed->crease;
01708             if(efa2->e4) efa2->e4->crease= eed->crease;
01709         }
01710 
01711         eed= nexted;
01712     }
01713     
01714     /* duplicate faces, if necessary remove old ones  */
01715     efa= em->faces.first;
01716     while(efa) {
01717         nextvl= efa->next;
01718         if(efa->f1 & 1) {
01719         
01720             v1 = efa->v1->tmp.v;
01721             v2 = efa->v2->tmp.v;
01722             v3 = efa->v3->tmp.v;
01723             if(efa->v4) 
01724                 v4 = efa->v4->tmp.v; 
01725             else
01726                 v4= NULL;
01727 
01728             /* hmm .. not sure about edges here */
01729             if(del_old==0)  // if we keep old, we flip normal
01730                 efa2= addfacelist(em, v3, v2, v1, v4, efa, efa); 
01731             else
01732                 efa2= addfacelist(em, v1, v2, v3, v4, efa, efa);
01733             
01734             /* for transform */
01735             add_normal_aligned(nor, efa->n);
01736 
01737             if(del_old) {
01738                 BLI_remlink(&em->faces, efa);
01739                 free_editface(em, efa);
01740             }
01741         }
01742         efa= nextvl;
01743     }
01744     /* delete edges after copying edges above! */
01745     if(del_old) {
01746         eed= em->edges.first;
01747         while(eed) {
01748             nexted= eed->next;
01749             if(eed->f2==3 && eed->f1==1) {
01750                 remedge(em, eed);
01751                 free_editedge(em, eed);
01752             }
01753             eed= nexted;
01754         }
01755     }
01756     
01757     normalize_v3(nor);  // for grab
01758     
01759     /* for all vertices with eve->tmp.v!=0 
01760         if eve->f1==1: make edge
01761         if flag!=128 : if del_old==1: remove
01762     */
01763     eve= em->verts.last;
01764     while(eve) {
01765         nextve= eve->prev;
01766         if(eve->tmp.v) {
01767             if(eve->f1==1) addedgelist(em, eve, eve->tmp.v, NULL);
01768             else if( (eve->f & 128)==0) {
01769                 if(del_old) {
01770                     BLI_remlink(&em->verts,eve);
01771                     free_editvert(em, eve);
01772                     eve= NULL;
01773                 }
01774             }
01775         }
01776         if(eve) {
01777             eve->f &= ~128;
01778         }
01779         eve= nextve;
01780     }
01781     // since its vertex select mode now, it also deselects higher order
01782     EM_selectmode_flush(em);
01783 
01784     if(is_zero_v3(nor)) return 'g'; // g is grab, for correct undo print
01785     return 'n';
01786 }
01787 
01788 /* generic extrude */
01789 short extrudeflag(Object *obedit, EditMesh *em, short flag, float *nor, int all)
01790 {
01791     if(em->selectmode & SCE_SELECT_VERTEX)
01792         return extrudeflag_vert(obedit, em, flag, nor, all);
01793     else 
01794         return extrudeflag_edge(obedit, em, flag, nor, all);
01795         
01796 }
01797 
01798 void rotateflag(EditMesh *em, short flag, float *cent, float rotmat[][3])
01799 {
01800     /* all verts with (flag & 'flag') rotate */
01801     EditVert *eve;
01802 
01803     eve= em->verts.first;
01804     while(eve) {
01805         if(eve->f & flag) {
01806             eve->co[0]-=cent[0];
01807             eve->co[1]-=cent[1];
01808             eve->co[2]-=cent[2];
01809             mul_m3_v3(rotmat,eve->co);
01810             eve->co[0]+=cent[0];
01811             eve->co[1]+=cent[1];
01812             eve->co[2]+=cent[2];
01813         }
01814         eve= eve->next;
01815     }
01816 }
01817 
01818 void translateflag(EditMesh *em, short flag, float *vec)
01819 {
01820     /* all verts with (flag & 'flag') translate */
01821     EditVert *eve;
01822 
01823     eve= em->verts.first;
01824     while(eve) {
01825         if(eve->f & flag) {
01826             eve->co[0]+=vec[0];
01827             eve->co[1]+=vec[1];
01828             eve->co[2]+=vec[2];
01829         }
01830         eve= eve->next;
01831     }
01832 }
01833 
01834 /* helper call for below */
01835 static EditVert *adduplicate_vertex(EditMesh *em, EditVert *eve, int flag)
01836 {
01837     /* FIXME: copy deformation weight from eve ok here? */
01838     EditVert *v1= addvertlist(em, eve->co, eve);
01839     
01840     v1->f= eve->f;
01841     eve->f &= ~flag;
01842     eve->f|= 128;
01843     
01844     eve->tmp.v = v1;
01845     
01846     return v1;
01847 }
01848 
01849 /* old selection has flag 128 set, and flag 'flag' cleared
01850 new selection has flag 'flag' set */
01851 void adduplicateflag(EditMesh *em, int flag)
01852 {
01853     EditVert *eve, *v1, *v2, *v3, *v4;
01854     EditEdge *eed, *newed;
01855     EditFace *efa, *newfa, *act_efa = EM_get_actFace(em, 0);
01856 
01857     EM_clear_flag_all(em, 128);
01858     EM_selectmode_set(em);  // paranoia check, selection now is consistent
01859 
01860     /* vertices first */
01861     for(eve= em->verts.last; eve; eve= eve->prev) {
01862 
01863         if(eve->f & flag)
01864             adduplicate_vertex(em, eve, flag);
01865         else 
01866             eve->tmp.v = NULL;
01867     }
01868     
01869     /* copy edges, note that vertex selection can be independent of edge */
01870     for(eed= em->edges.last; eed; eed= eed->prev) {
01871         if( eed->f & flag ) {
01872             v1 = eed->v1->tmp.v;
01873             if(v1==NULL) v1= adduplicate_vertex(em, eed->v1, flag);
01874             v2 = eed->v2->tmp.v;
01875             if(v2==NULL) v2= adduplicate_vertex(em, eed->v2, flag);
01876             
01877             newed= addedgelist(em, v1, v2, eed);
01878             
01879             newed->f= eed->f;
01880             eed->f &= ~flag;
01881             eed->f |= 128;
01882         }
01883     }
01884 
01885     /* then duplicate faces, again create new vertices if needed */
01886     for(efa= em->faces.last; efa; efa= efa->prev) {
01887         if(efa->f & flag) {
01888             v1 = efa->v1->tmp.v;
01889             if(v1==NULL) v1= adduplicate_vertex(em, efa->v1, flag);
01890             v2 = efa->v2->tmp.v;
01891             if(v2==NULL) v2= adduplicate_vertex(em, efa->v2, flag);
01892             v3 = efa->v3->tmp.v;
01893             if(v3==NULL) v3= adduplicate_vertex(em, efa->v3, flag);
01894             if(efa->v4) {
01895                 v4 = efa->v4->tmp.v; 
01896                 if(v4==NULL) v4= adduplicate_vertex(em, efa->v4, flag);
01897             }
01898             else v4= NULL;
01899             
01900             newfa= addfacelist(em, v1, v2, v3, v4, efa, efa); 
01901             
01902             if (efa==act_efa) {
01903                 EM_set_actFace(em, newfa);
01904             }
01905             
01906             newfa->f= efa->f;
01907             efa->f &= ~flag;
01908             efa->f |= 128;
01909         }
01910     }
01911     
01912     EM_fgon_flags(em);  // redo flags and indices for fgons
01913 }
01914 
01915 void delfaceflag(EditMesh *em, int flag)
01916 {
01917     /* delete all faces with 'flag', including loose edges and loose vertices */
01918     /* this is maybe a bit weird, but this function is used for 'split' and 'separate' */
01919     /* in remaining vertices/edges 'flag' is cleared */
01920     EditVert *eve,*nextve;
01921     EditEdge *eed, *nexted;
01922     EditFace *efa,*nextvl;
01923 
01924     /* to detect loose edges, we put f2 flag on 1 */
01925     for(eed= em->edges.first; eed; eed= eed->next) {
01926         if(eed->f & flag) eed->f2= 1;
01927         else eed->f2= 0;
01928     }
01929     
01930     /* delete faces */
01931     efa= em->faces.first;
01932     while(efa) {
01933         nextvl= efa->next;
01934         if(efa->f & flag) {
01935             
01936             efa->e1->f2= 1;
01937             efa->e2->f2= 1;
01938             efa->e3->f2= 1;
01939             if(efa->e4) {
01940                 efa->e4->f2= 1;
01941             }
01942                                 
01943             BLI_remlink(&em->faces, efa);
01944             free_editface(em, efa);
01945         }
01946         efa= nextvl;
01947     }
01948     
01949     /* all remaining faces: make sure we keep the edges */
01950     for(efa= em->faces.first; efa; efa= efa->next) {
01951         efa->e1->f2= 0;
01952         efa->e2->f2= 0;
01953         efa->e3->f2= 0;
01954         if(efa->e4) {
01955             efa->e4->f2= 0;
01956         }
01957     }
01958     
01959     /* remove tagged edges, and clear remaining ones */
01960     eed= em->edges.first;
01961     while(eed) {
01962         nexted= eed->next;
01963         
01964         if(eed->f2==1) {
01965             remedge(em, eed);
01966             free_editedge(em, eed);
01967         }
01968         else {
01969             eed->f &= ~flag;
01970             eed->v1->f &= ~flag;
01971             eed->v2->f &= ~flag;
01972         }
01973         eed= nexted;
01974     }
01975     
01976     /* vertices with 'flag' now are the loose ones, and will be removed */
01977     eve= em->verts.first;
01978     while(eve) {
01979         nextve= eve->next;
01980         if(eve->f & flag) {
01981             BLI_remlink(&em->verts, eve);
01982             free_editvert(em, eve);
01983         }
01984         eve= nextve;
01985     }
01986 
01987 }
01988 
01989 /* ********************* */
01990 #if 0
01991 static int check_vnormal_flip(float *n, float *vnorm) 
01992 {
01993     float inp;
01994 
01995     inp= n[0]*vnorm[0]+n[1]*vnorm[1]+n[2]*vnorm[2];
01996 
01997     /* angles 90 degrees: dont flip */
01998     if(inp> -0.000001) return 0;
01999 
02000     return 1;
02001 }
02002 #endif
02003 
02004 
02005 
02006 /* does face centers too */
02007 void recalc_editnormals(EditMesh *em)
02008 {
02009     EditFace *efa;
02010     EditVert *eve;
02011 
02012     for(eve= em->verts.first; eve; eve=eve->next)
02013         zero_v3(eve->no);
02014 
02015     for(efa= em->faces.first; efa; efa=efa->next) {
02016         float *n4= (efa->v4)? efa->v4->no: NULL;
02017         float *c4= (efa->v4)? efa->v4->co: NULL;
02018 
02019         if(efa->v4) {
02020             normal_quad_v3(efa->n, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
02021             cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
02022         }
02023         else {
02024             normal_tri_v3(efa->n, efa->v1->co, efa->v2->co, efa->v3->co);
02025             cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
02026         }
02027 
02028         accumulate_vertex_normals(efa->v1->no, efa->v2->no, efa->v3->no, n4,
02029             efa->n, efa->v1->co, efa->v2->co, efa->v3->co, c4);
02030     }
02031 
02032     /* following Mesh convention; we use vertex coordinate itself for normal in this case */
02033     for(eve= em->verts.first; eve; eve=eve->next) {
02034         if(normalize_v3(eve->no) == 0.0f) {
02035             copy_v3_v3(eve->no, eve->co);
02036             normalize_v3(eve->no);
02037         }
02038     }
02039 }
02040 
02041 int compareface(EditFace *vl1, EditFace *vl2)
02042 {
02043     EditVert *v1, *v2, *v3, *v4;
02044     
02045     if(vl1->v4 && vl2->v4) {
02046         v1= vl2->v1;
02047         v2= vl2->v2;
02048         v3= vl2->v3;
02049         v4= vl2->v4;
02050         
02051         if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1 || vl1->v4==v1) {
02052             if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2 || vl1->v4==v2) {
02053                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3 || vl1->v4==v3) {
02054                     if(vl1->v1==v4 || vl1->v2==v4 || vl1->v3==v4 || vl1->v4==v4) {
02055                         return 1;
02056                     }
02057                 }
02058             }
02059         }
02060     }
02061     else if(vl1->v4==0 && vl2->v4==0) {
02062         v1= vl2->v1;
02063         v2= vl2->v2;
02064         v3= vl2->v3;
02065         
02066         if(vl1->v1==v1 || vl1->v2==v1 || vl1->v3==v1) {
02067             if(vl1->v1==v2 || vl1->v2==v2 || vl1->v3==v2) {
02068                 if(vl1->v1==v3 || vl1->v2==v3 || vl1->v3==v3) {
02069                     return 1;
02070                 }
02071             }
02072         }
02073     }
02074     
02075     return 0;
02076 }
02077 
02078 /* checks for existence, not tria overlapping inside quad */
02079 EditFace *exist_face(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4)
02080 {
02081     EditFace *efa, efatest;
02082     
02083     efatest.v1= v1;
02084     efatest.v2= v2;
02085     efatest.v3= v3;
02086     efatest.v4= v4;
02087     
02088     efa= em->faces.first;
02089     while(efa) {
02090         if(compareface(&efatest, efa)) return efa;
02091         efa= efa->next;
02092     }
02093     return NULL;
02094 }
02095 
02096 /* evaluate if entire quad is a proper convex quad */
02097 int convex(float *v1, float *v2, float *v3, float *v4)
02098 {
02099     float nor[3], nor1[3], nor2[3], vec[4][2];
02100     
02101     /* define projection, do both trias apart, quad is undefined! */
02102     normal_tri_v3( nor1,v1, v2, v3);
02103     normal_tri_v3( nor2,v1, v3, v4);
02104     nor[0]= ABS(nor1[0]) + ABS(nor2[0]);
02105     nor[1]= ABS(nor1[1]) + ABS(nor2[1]);
02106     nor[2]= ABS(nor1[2]) + ABS(nor2[2]);
02107 
02108     if(nor[2] >= nor[0] && nor[2] >= nor[1]) {
02109         vec[0][0]= v1[0]; vec[0][1]= v1[1];
02110         vec[1][0]= v2[0]; vec[1][1]= v2[1];
02111         vec[2][0]= v3[0]; vec[2][1]= v3[1];
02112         vec[3][0]= v4[0]; vec[3][1]= v4[1];
02113     }
02114     else if(nor[1] >= nor[0] && nor[1]>= nor[2]) {
02115         vec[0][0]= v1[0]; vec[0][1]= v1[2];
02116         vec[1][0]= v2[0]; vec[1][1]= v2[2];
02117         vec[2][0]= v3[0]; vec[2][1]= v3[2];
02118         vec[3][0]= v4[0]; vec[3][1]= v4[2];
02119     }
02120     else {
02121         vec[0][0]= v1[1]; vec[0][1]= v1[2];
02122         vec[1][0]= v2[1]; vec[1][1]= v2[2];
02123         vec[2][0]= v3[1]; vec[2][1]= v3[2];
02124         vec[3][0]= v4[1]; vec[3][1]= v4[2];
02125     }
02126     
02127     /* linetests, the 2 diagonals have to instersect to be convex */
02128     if( isect_line_line_v2(vec[0], vec[2], vec[1], vec[3]) > 0 ) return 1;
02129     return 0;
02130 }
02131 
02132 
02133 /* ********************* Fake Polgon support (FGon) ***************** */
02134 
02135 
02136 /* results in:
02137    - faces having ->fgonf flag set (also for draw)
02138    - edges having ->fgoni index set (for select)
02139 */
02140 
02141 float EM_face_area(EditFace *efa)
02142 {
02143     if(efa->v4) return area_quad_v3(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
02144     else return area_tri_v3(efa->v1->co, efa->v2->co, efa->v3->co);
02145 }
02146 
02147 float EM_face_perimeter(EditFace *efa)
02148 {   
02149     if(efa->v4) return
02150         len_v3v3(efa->v1->co, efa->v2->co)+
02151         len_v3v3(efa->v2->co, efa->v3->co)+
02152         len_v3v3(efa->v3->co, efa->v4->co)+
02153         len_v3v3(efa->v4->co, efa->v1->co);
02154     
02155     else return
02156         len_v3v3(efa->v1->co, efa->v2->co)+
02157         len_v3v3(efa->v2->co, efa->v3->co)+
02158         len_v3v3(efa->v3->co, efa->v1->co);
02159 }
02160 
02161 void EM_fgon_flags(EditMesh *em)
02162 {
02163     EditFace *efa, *efan, *efamax;
02164     EditEdge *eed;
02165     ListBase listb={NULL, NULL};
02166     float size, maxsize;
02167     short done, curindex= 1;
02168     
02169     // for each face with fgon edge AND not fgon flag set
02170     for(eed= em->edges.first; eed; eed= eed->next) eed->fgoni= 0;  // index
02171     for(efa= em->faces.first; efa; efa= efa->next) efa->fgonf= 0;  // flag
02172     
02173     // for speed & simplicity, put fgon face candidates in new listbase
02174     efa= em->faces.first;
02175     while(efa) {
02176         efan= efa->next;
02177         if( (efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) || 
02178             (efa->e3->h & EM_FGON) || (efa->e4 && (efa->e4->h & EM_FGON)) ) {
02179             BLI_remlink(&em->faces, efa);
02180             BLI_addtail(&listb, efa);
02181         }
02182         efa= efan;
02183     }
02184     
02185     // find an undone face with fgon edge
02186     for(efa= listb.first; efa; efa= efa->next) {
02187         if(efa->fgonf==0) {
02188             
02189             // init this face
02190             efa->fgonf= EM_FGON;
02191             if(efa->e1->h & EM_FGON) efa->e1->fgoni= curindex;
02192             if(efa->e2->h & EM_FGON) efa->e2->fgoni= curindex;
02193             if(efa->e3->h & EM_FGON) efa->e3->fgoni= curindex;
02194             if(efa->e4 && (efa->e4->h & EM_FGON)) efa->e4->fgoni= curindex;
02195             
02196             // we search for largest face, to give facedot drawing rights
02197             maxsize= EM_face_area(efa);
02198             efamax= efa;
02199             
02200             // now flush curendex over edges and set faceflags
02201             done= 1;
02202             while(done==1) {
02203                 done= 0;
02204                 
02205                 for(efan= listb.first; efan; efan= efan->next) {
02206                     if(efan->fgonf==0) {
02207                         // if one if its edges has index set, do other too
02208                         if( (efan->e1->fgoni==curindex) || (efan->e2->fgoni==curindex) ||
02209                             (efan->e3->fgoni==curindex) || (efan->e4 && (efan->e4->fgoni==curindex)) ) {
02210                             
02211                             efan->fgonf= EM_FGON;
02212                             if(efan->e1->h & EM_FGON) efan->e1->fgoni= curindex;
02213                             if(efan->e2->h & EM_FGON) efan->e2->fgoni= curindex;
02214                             if(efan->e3->h & EM_FGON) efan->e3->fgoni= curindex;
02215                             if(efan->e4 && (efan->e4->h & EM_FGON)) efan->e4->fgoni= curindex;
02216                             
02217                             size= EM_face_area(efan);
02218                             if(size>maxsize) {
02219                                 efamax= efan;
02220                                 maxsize= size;
02221                             }
02222                             done= 1;
02223                         }
02224                     }
02225                 }
02226             }
02227             
02228             efamax->fgonf |= EM_FGON_DRAW;
02229             curindex++;
02230 
02231         }
02232     }
02233 
02234     // put fgon face candidates back in listbase
02235     efa= listb.first;
02236     while(efa) {
02237         efan= efa->next;
02238         BLI_remlink(&listb, efa);
02239         BLI_addtail(&em->faces, efa);
02240         efa= efan;
02241     }
02242     
02243     // remove fgon flags when edge not in fgon (anymore)
02244     for(eed= em->edges.first; eed; eed= eed->next) {
02245         if(eed->fgoni==0) eed->h &= ~EM_FGON;
02246     }
02247     
02248 }
02249 
02250 /* editmesh vertmap, copied from intern.mesh.c
02251  * if do_face_idx_array is 0 it means we need to run it as well as freeing
02252  * */
02253 
02254 UvVertMap *EM_make_uv_vert_map(EditMesh *em, int selected, int do_face_idx_array, float *limit)
02255 {
02256     EditVert *ev;
02257     EditFace *efa;
02258     int totverts;
02259     
02260     /* vars from original func */
02261     UvVertMap *vmap;
02262     UvMapVert *buf;
02263     MTFace *tf;
02264     unsigned int a;
02265     int i, totuv, nverts;
02266     
02267     if (do_face_idx_array)
02268         EM_init_index_arrays(em, 0, 0, 1);
02269     
02270     /* we need the vert */
02271     for (ev= em->verts.first, totverts=0; ev; ev= ev->next, totverts++) {
02272         ev->tmp.l = totverts;
02273     }
02274     
02275     totuv = 0;
02276 
02277     /* generate UvMapVert array */
02278     for (efa= em->faces.first; efa; efa= efa->next)
02279         if(!selected || ((!efa->h) && (efa->f & SELECT)))
02280             totuv += (efa->v4)? 4: 3;
02281         
02282     if(totuv==0) {
02283         if (do_face_idx_array)
02284             EM_free_index_arrays();
02285         return NULL;
02286     }
02287     vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap");
02288     if (!vmap) {
02289         if (do_face_idx_array)
02290             EM_free_index_arrays();
02291         return NULL;
02292     }
02293 
02294     vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*");
02295     buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
02296 
02297     if (!vmap->vert || !vmap->buf) {
02298         free_uv_vert_map(vmap);
02299         if (do_face_idx_array)
02300             EM_free_index_arrays();
02301         return NULL;
02302     }
02303 
02304     for (a=0, efa= em->faces.first; efa; a++, efa= efa->next) {
02305         if(!selected || ((!efa->h) && (efa->f & SELECT))) {
02306             nverts= (efa->v4)? 4: 3;
02307             
02308             for(i=0; i<nverts; i++) {
02309                 buf->tfindex= i;
02310                 buf->f= a;
02311                 buf->separate = 0;
02312                 
02313                 buf->next= vmap->vert[(*(&efa->v1 + i))->tmp.l];
02314                 vmap->vert[(*(&efa->v1 + i))->tmp.l]= buf;
02315                 
02316                 buf++;
02317             }
02318         }
02319     }
02320     
02321     /* sort individual uvs for each vert */
02322     for(a=0, ev=em->verts.first; ev; a++, ev= ev->next) {
02323         UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
02324         UvMapVert *iterv, *v, *lastv, *next;
02325         float *uv, *uv2, uvdiff[2];
02326 
02327         while(vlist) {
02328             v= vlist;
02329             vlist= vlist->next;
02330             v->next= newvlist;
02331             newvlist= v;
02332 
02333             efa = EM_get_face_for_index(v->f);
02334             tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
02335             uv = tf->uv[v->tfindex]; 
02336             
02337             lastv= NULL;
02338             iterv= vlist;
02339 
02340             while(iterv) {
02341                 next= iterv->next;
02342                 efa = EM_get_face_for_index(iterv->f);
02343                 tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
02344                 uv2 = tf->uv[iterv->tfindex];
02345                 
02346                 sub_v2_v2v2(uvdiff, uv2, uv);
02347 
02348                 if(fabsf(uv[0]-uv2[0]) < limit[0] && fabsf(uv[1]-uv2[1]) < limit[1]) {
02349                     if(lastv) lastv->next= next;
02350                     else vlist= next;
02351                     iterv->next= newvlist;
02352                     newvlist= iterv;
02353                 }
02354                 else
02355                     lastv=iterv;
02356 
02357                 iterv= next;
02358             }
02359 
02360             newvlist->separate = 1;
02361         }
02362 
02363         vmap->vert[a]= newvlist;
02364     }
02365     
02366     if (do_face_idx_array)
02367         EM_free_index_arrays();
02368     
02369     return vmap;
02370 }
02371 
02372 UvMapVert *EM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
02373 {
02374     return vmap->vert[v];
02375 }
02376 
02377 void EM_free_uv_vert_map(UvVertMap *vmap)
02378 {
02379     if (vmap) {
02380         if (vmap->vert) MEM_freeN(vmap->vert);
02381         if (vmap->buf) MEM_freeN(vmap->buf);
02382         MEM_freeN(vmap);
02383     }
02384 }
02385 
02386 /* poll call for mesh operators requiring a view3d context */
02387 int EM_view3d_poll(bContext *C)
02388 {
02389     if(ED_operator_editmesh(C) && ED_operator_view3d_active(C))
02390         return 1;
02391     return 0;
02392 }
02393 
02394 /* higher quality normals */
02395 
02396 /* NormalCalc */
02397 /* NormalCalc modifier: calculates higher quality normals
02398 */
02399 
02400 /* each edge uses this to  */
02401 typedef struct EdgeFaceRef {
02402     int f1; /* init as -1 */
02403     int f2;
02404 } EdgeFaceRef;
02405 
02406 void EM_make_hq_normals(EditMesh *em)
02407 {
02408     EditFace *efa;
02409     EditVert *eve;
02410     int i;
02411 
02412     EdgeHash *edge_hash = BLI_edgehash_new();
02413     EdgeHashIterator *edge_iter;
02414     int edge_ref_count = 0;
02415     unsigned int ed_v1, ed_v2; /* use when getting the key */
02416     EdgeFaceRef *edge_ref_array = MEM_callocN(em->totedge * sizeof(EdgeFaceRef), "Edge Connectivity");
02417     EdgeFaceRef *edge_ref;
02418     float edge_normal[3];
02419 
02420     EM_init_index_arrays(em, 1, 1, 1);
02421 
02422     for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) {
02423         zero_v3(eve->no);
02424         eve->tmp.l= i;
02425     }
02426 
02427     /* This function adds an edge hash if its not there, and adds the face index */
02428 #define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
02429         { \
02430             const unsigned int mf_v1 = EDV1; \
02431             const unsigned int mf_v2 = EDV2; \
02432             edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, mf_v1, mf_v2); \
02433             if (!edge_ref) { \
02434                 edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \
02435                 edge_ref->f1 = i; \
02436                 edge_ref->f2 = -1; \
02437                 BLI_edgehash_insert(edge_hash, mf_v1, mf_v2, edge_ref); \
02438             } \
02439             else { \
02440                 edge_ref->f2 = i; \
02441             } \
02442         }
02443 
02444 
02445     efa= em->faces.first;
02446     for(i = 0; i < em->totface; i++, efa= efa->next) {
02447         if(efa->v4) {
02448             NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l);
02449             NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l);
02450             NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v4->tmp.l);
02451             NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v4->tmp.l, efa->v1->tmp.l);
02452         } else {
02453             NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v1->tmp.l, efa->v2->tmp.l);
02454             NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v2->tmp.l, efa->v3->tmp.l);
02455             NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(efa->v3->tmp.l, efa->v1->tmp.l);
02456         }
02457     }
02458 
02459 #undef NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE
02460 
02461 
02462     for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) {
02463         /* Get the edge vert indices, and edge value (the face indices that use it)*/
02464         BLI_edgehashIterator_getKey(edge_iter, &ed_v1, &ed_v2);
02465         edge_ref = BLI_edgehashIterator_getValue(edge_iter);
02466 
02467         if (edge_ref->f2 != -1) {
02468             EditFace *ef1= EM_get_face_for_index(edge_ref->f1), *ef2= EM_get_face_for_index(edge_ref->f2);
02469             float angle= angle_normalized_v3v3(ef1->n, ef2->n);
02470             if(angle > 0.0f) {
02471                 /* We have 2 faces using this edge, calculate the edges normal
02472                  * using the angle between the 2 faces as a weighting */
02473                 add_v3_v3v3(edge_normal, ef1->n, ef2->n);
02474                 normalize_v3(edge_normal);
02475                 mul_v3_fl(edge_normal, angle);
02476             }
02477             else {
02478                 /* cant do anything useful here!
02479                    Set the face index for a vert incase it gets a zero normal */
02480                 EM_get_vert_for_index(ed_v1)->tmp.l=
02481                 EM_get_vert_for_index(ed_v2)->tmp.l= -(edge_ref->f1 + 1);
02482                 continue;
02483             }
02484         } else {
02485             /* only one face attached to that edge */
02486             /* an edge without another attached- the weight on this is
02487              * undefined, M_PI/2 is 90d in radians and that seems good enough */
02488             copy_v3_v3(edge_normal, EM_get_face_for_index(edge_ref->f1)->n);
02489             mul_v3_fl(edge_normal, M_PI/2);
02490         }
02491         add_v3_v3(EM_get_vert_for_index(ed_v1)->no, edge_normal );
02492         add_v3_v3(EM_get_vert_for_index(ed_v2)->no, edge_normal );
02493 
02494 
02495     }
02496     BLI_edgehashIterator_free(edge_iter);
02497     BLI_edgehash_free(edge_hash, NULL);
02498     MEM_freeN(edge_ref_array);
02499 
02500     /* normalize vertex normals and assign */
02501     for(eve= em->verts.first; eve; eve= eve->next) {
02502         if(normalize_v3(eve->no) == 0.0f && eve->tmp.l < 0) {
02503             /* exceptional case, totally flat */
02504             efa= EM_get_face_for_index(-(eve->tmp.l) - 1);
02505             copy_v3_v3(eve->no, efa->n);
02506         }   
02507     }
02508 
02509     EM_free_index_arrays();
02510 }
02511 
02512 void EM_solidify(EditMesh *em, float dist)
02513 {
02514     EditFace *efa;
02515     EditVert *eve;
02516     float *vert_angles= MEM_callocN(sizeof(float) * em->totvert * 2, "EM_solidify"); /* 2 in 1 */
02517     float *vert_accum= vert_angles + em->totvert;
02518     float face_angles[4];
02519     int i, j;
02520 
02521     for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) {
02522         eve->tmp.l= i;
02523     }
02524 
02525     efa= em->faces.first;
02526     for(i = 0; i < em->totface; i++, efa= efa->next) {
02527 
02528         if(!(efa->f & SELECT))
02529             continue;
02530 
02531         if(efa->v4) {
02532             angle_quad_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
02533             j= 3;
02534         }
02535         else {
02536             angle_tri_v3(face_angles, efa->v1->co, efa->v2->co, efa->v3->co);
02537             j= 2;
02538         }
02539 
02540         for(; j>=0; j--) {
02541             eve= *(&efa->v1 + j);
02542             vert_accum[eve->tmp.l] += face_angles[j];
02543             vert_angles[eve->tmp.l]+= shell_angle_to_dist(angle_normalized_v3v3(eve->no, efa->n)) * face_angles[j];
02544         }
02545     }
02546 
02547     for(eve= em->verts.first, i=0; eve; eve= eve->next, i++) {
02548         if(vert_accum[i]) { /* zero if unselected */
02549             madd_v3_v3fl(eve->co, eve->no, dist * vert_angles[i] / vert_accum[i]);
02550         }
02551     }
02552 
02553     MEM_freeN(vert_angles);
02554 }
02555 
02556 /* not that optimal!, should be nicer with bmesh */
02557 static void tag_face_edges(EditFace *efa)
02558 {
02559     if(efa->v4)
02560         efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= efa->e4->tmp.l= 1;
02561     else
02562         efa->e1->tmp.l= efa->e2->tmp.l= efa->e3->tmp.l= 1;
02563 }
02564 static int tag_face_edges_test(EditFace *efa)
02565 {
02566     if(efa->v4)
02567         return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l || efa->e4->tmp.l) ? 1:0;
02568     else
02569         return (efa->e1->tmp.l || efa->e2->tmp.l || efa->e3->tmp.l) ? 1:0;
02570 }
02571 
02572 static void em_deselect_nth_face(EditMesh *em, int nth, EditFace *efa_act)
02573 {
02574     EditFace *efa;
02575     EditEdge *eed;
02576     int ok= 1;
02577 
02578     if(efa_act==NULL) {
02579         return;
02580     }
02581 
02582     /* to detect loose edges, we put f2 flag on 1 */
02583     for(eed= em->edges.first; eed; eed= eed->next) {
02584         eed->tmp.l= 0;
02585     }
02586 
02587     for (efa= em->faces.first; efa; efa= efa->next) {
02588         efa->tmp.l = 0;
02589     }
02590 
02591     efa_act->tmp.l = 1;
02592 
02593     while(ok) {
02594         ok = 0;
02595 
02596         for (efa= em->faces.first; efa; efa= efa->next) {
02597             if(efa->f & SELECT) {
02598                 if(efa->tmp.l==1) { /* initialize */
02599                     tag_face_edges(efa);
02600                 }
02601     
02602                 if(efa->tmp.l) {
02603                     efa->tmp.l++;
02604                 }
02605             }
02606         }
02607 
02608         for (efa= em->faces.first; efa; efa= efa->next) {
02609             if(efa->f & SELECT) {
02610                 if(efa->tmp.l==0 && tag_face_edges_test(efa)) {
02611                     efa->tmp.l= 1;
02612                     ok = 1; /* keep looping */
02613                 }
02614             }
02615         }
02616     }
02617 
02618     for (efa= em->faces.first; efa; efa= efa->next) {
02619         if(efa->tmp.l > 0 && efa->tmp.l % nth) {
02620             EM_select_face(efa, 0);
02621         }
02622     }
02623     for (efa= em->faces.first; efa; efa= efa->next) {
02624         if(efa->f & SELECT) {
02625             EM_select_face(efa, 1);
02626         }
02627     }
02628 
02629     EM_nvertices_selected(em);
02630     EM_nedges_selected(em);
02631     EM_nfaces_selected(em);
02632 }
02633 
02634 /* not that optimal!, should be nicer with bmesh */
02635 static void tag_edge_verts(EditEdge *eed)
02636 {
02637     eed->v1->tmp.l= eed->v2->tmp.l= 1;
02638 }
02639 static int tag_edge_verts_test(EditEdge *eed)
02640 {
02641     return (eed->v1->tmp.l || eed->v2->tmp.l) ? 1:0;
02642 }
02643 
02644 static void em_deselect_nth_edge(EditMesh *em, int nth, EditEdge *eed_act)
02645 {
02646     EditEdge *eed;
02647     EditVert *eve;
02648     int ok= 1;
02649 
02650     if(eed_act==NULL) {
02651         return;
02652     }
02653 
02654     for(eve= em->verts.first; eve; eve= eve->next) {
02655         eve->tmp.l= 0;
02656     }
02657 
02658     for (eed= em->edges.first; eed; eed= eed->next) {
02659         eed->tmp.l = 0;
02660     }
02661 
02662     eed_act->tmp.l = 1;
02663 
02664     while(ok) {
02665         ok = 0;
02666 
02667         for (eed= em->edges.first; eed; eed= eed->next) {
02668             if(eed->f & SELECT) {
02669                 if(eed->tmp.l==1) { /* initialize */
02670                     tag_edge_verts(eed);
02671                 }
02672     
02673                 if(eed->tmp.l) {
02674                     eed->tmp.l++;
02675                 }
02676             }
02677         }
02678 
02679         for (eed= em->edges.first; eed; eed= eed->next) {
02680             if(eed->f & SELECT) {
02681                 if(eed->tmp.l==0 && tag_edge_verts_test(eed)) {
02682                     eed->tmp.l= 1;
02683                     ok = 1; /* keep looping */
02684                 }
02685             }
02686         }
02687     }
02688 
02689     for (eed= em->edges.first; eed; eed= eed->next) {
02690         if(eed->tmp.l > 0 && eed->tmp.l % nth) {
02691             EM_select_edge(eed, 0);
02692         }
02693     }
02694     for (eed= em->edges.first; eed; eed= eed->next) {
02695         if(eed->f & SELECT) {
02696             EM_select_edge(eed, 1);
02697         }
02698     }
02699 
02700     {
02701         /* grr, should be a function */
02702         EditFace *efa;
02703         for (efa= em->faces.first; efa; efa= efa->next) {
02704             if(efa->v4) {
02705                 if(efa->e1->f & efa->e2->f & efa->e3->f & efa->e4->f & SELECT );
02706                 else efa->f &= ~SELECT;
02707             }
02708             else {
02709                 if(efa->e1->f & efa->e2->f & efa->e3->f & SELECT );
02710                 else efa->f &= ~SELECT;
02711             }
02712         }
02713     }
02714 
02715     EM_nvertices_selected(em);
02716     EM_nedges_selected(em);
02717     EM_nfaces_selected(em);
02718 }
02719 
02720 static void em_deselect_nth_vert(EditMesh *em, int nth, EditVert *eve_act)
02721 {
02722     EditVert *eve;
02723     EditEdge *eed;
02724     int ok= 1;
02725 
02726     if(eve_act==NULL) {
02727         return;
02728     }
02729 
02730     for (eve= em->verts.first; eve; eve= eve->next) {
02731         eve->tmp.l = 0;
02732     }
02733 
02734     eve_act->tmp.l = 1;
02735 
02736     while(ok) {
02737         ok = 0;
02738 
02739         for (eve= em->verts.first; eve; eve= eve->next) {
02740             if(eve->f & SELECT) {
02741                 if(eve->tmp.l)
02742                     eve->tmp.l++;
02743             }
02744         }
02745 
02746         for (eed= em->edges.first; eed; eed= eed->next) {
02747             if(eed->f & SELECT) {
02748                 if(eed->v1->tmp.l==2 && eed->v2->tmp.l==0) { /* initialize */
02749                     eed->v2->tmp.l= 1;
02750                     ok = 1; /* keep looping */
02751                 }
02752                 else if(eed->v2->tmp.l==2 && eed->v1->tmp.l==0) { /* initialize */
02753                     eed->v1->tmp.l= 1;
02754                     ok = 1; /* keep looping */
02755                 }
02756             }
02757         }
02758     }
02759 
02760     for (eve= em->verts.first; eve; eve= eve->next) {
02761         if(eve->tmp.l > 0 && eve->tmp.l % nth) {
02762             eve->f &= ~SELECT;
02763         }
02764     }
02765 
02766     EM_deselect_flush(em);
02767 
02768     EM_nvertices_selected(em);
02769     // EM_nedges_selected(em); // flush does these
02770     // EM_nfaces_selected(em); // flush does these
02771 }
02772 
02773 static void deselect_nth_active(EditMesh *em, EditVert **eve_p, EditEdge **eed_p, EditFace **efa_p)
02774 {
02775     EditSelection *ese;
02776 
02777     *eve_p= NULL;
02778     *eed_p= NULL;
02779     *efa_p= NULL;
02780 
02781     ese= (EditSelection*)em->selected.last;
02782 
02783     if(ese) {
02784         switch(ese->type) {
02785         case EDITVERT:
02786             *eve_p= (EditVert *)ese->data;
02787             return;
02788         case EDITEDGE:
02789             *eed_p= (EditEdge *)ese->data;
02790             return;
02791         case EDITFACE:
02792             *efa_p= (EditFace *)ese->data;
02793             return;
02794         }
02795     }
02796 
02797     if(em->selectmode & SCE_SELECT_VERTEX) {
02798         EditVert *eve;
02799         for (eve= em->verts.first; eve; eve= eve->next) {
02800             if(eve->f & SELECT) {
02801                 *eve_p= eve;
02802                 return;
02803             }
02804         }
02805     }
02806 
02807     if(em->selectmode & SCE_SELECT_EDGE) {
02808         EditEdge *eed;
02809         for (eed= em->edges.first; eed; eed= eed->next) {
02810             if(eed->f & SELECT) {
02811                 *eed_p= eed;
02812                 return;
02813             }
02814         }
02815     }
02816 
02817     if(em->selectmode & SCE_SELECT_FACE) {
02818         EditFace *efa= EM_get_actFace(em, 1);
02819         if(efa) {
02820             *efa_p= efa;
02821             return;
02822         }
02823     }
02824 }
02825 
02826 int EM_deselect_nth(EditMesh *em, int nth)
02827 {
02828     EditVert *eve;
02829     EditEdge *eed;
02830     EditFace *efa;
02831 
02832     deselect_nth_active(em, &eve, &eed, &efa);
02833 
02834     if(eve)
02835         em_deselect_nth_vert(em, nth, eve);
02836     else if (eed)
02837         em_deselect_nth_edge(em, nth, eed);
02838     else if (efa)
02839         em_deselect_nth_face(em, nth, efa);
02840     else
02841         return 0;
02842     
02843     return 1;
02844 }
02845 
02846 void EM_project_snap_verts(bContext *C, ARegion *ar, Object *obedit, EditMesh *em)
02847 {
02848     EditVert *eve;
02849     for(eve= em->verts.first;eve; eve=eve->next) {
02850         if(eve->f & SELECT) {
02851             float mval[2], vec[3], no_dummy[3];
02852             int dist_dummy;
02853             mul_v3_m4v3(vec, obedit->obmat, eve->co);
02854             project_float_noclip(ar, vec, mval);
02855             if(snapObjectsContext(C, mval, &dist_dummy, vec, no_dummy, SNAP_NOT_OBEDIT)) {
02856                 mul_v3_m4v3(eve->co, obedit->imat, vec);
02857             }
02858         }
02859     }
02860 }