Blender  V2.59
editmesh.c
Go to the documentation of this file.
00001 /*
00002  * $Id: editmesh.c 36296 2011-04-23 09:25:34Z nazgul $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * Contributor(s): Blender Foundation, full recode 2002-2008
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <math.h>
00037 
00038 #include "MEM_guardedalloc.h"
00039 
00040 #include "DNA_scene_types.h"
00041 #include "DNA_object_types.h"
00042 #include "DNA_key_types.h"
00043 #include "DNA_meshdata_types.h"
00044 #include "DNA_modifier_types.h"
00045 
00046 #include "BLI_blenlib.h"
00047 #include "BLI_math.h"
00048 #include "BLI_editVert.h"
00049 #include "BLI_dynstr.h"
00050 #include "BLI_rand.h"
00051 #include "BLI_utildefines.h"
00052 
00053 #include "BKE_DerivedMesh.h"
00054 #include "BKE_context.h"
00055 #include "BKE_depsgraph.h"
00056 #include "BKE_global.h"
00057 #include "BKE_key.h"
00058 #include "BKE_main.h"
00059 #include "BKE_material.h"
00060 #include "BKE_mesh.h"
00061 #include "BKE_paint.h"
00062 #include "BKE_report.h"
00063 #include "BKE_multires.h"
00064 
00065 #include "ED_mesh.h"
00066 #include "ED_object.h"
00067 #include "ED_screen.h"
00068 #include "ED_util.h"
00069 #include "ED_view3d.h"
00070 
00071 #include "RNA_access.h"
00072 #include "RNA_define.h"
00073 
00074 #include "WM_api.h"
00075 #include "WM_types.h"
00076 
00077 /* own include */
00078 #include "mesh_intern.h"
00079 
00080 /* 
00081 editmesh.c:
00082         - add/alloc/free data
00083         - hashtables
00084         - enter/exit editmode
00085 */
00086 
00087 /* XXX */
00088 static void BIF_undo_push(const char *UNUSED(arg)) {}
00089 static void error(const char *UNUSED(arg)) {}
00090 
00091 
00092 /* ***************** HASH ********************* */
00093 
00094 
00095 #define EDHASHSIZE              (512*512)
00096 #define EDHASH(a, b)    (a % EDHASHSIZE)
00097 
00098 
00099 /* ************ ADD / REMOVE / FIND ****************** */
00100 
00101 static void *calloc_em(EditMesh *UNUSED(em), size_t size, size_t nr)
00102 {
00103         return calloc(size, nr);
00104 }
00105 
00106 /* used to bypass normal calloc with fast one */
00107 static void *(*callocvert)(EditMesh *, size_t, size_t) = calloc_em;
00108 static void *(*callocedge)(EditMesh *, size_t, size_t) = calloc_em;
00109 static void *(*callocface)(EditMesh *, size_t, size_t) = calloc_em;
00110 
00111 EditVert *addvertlist(EditMesh *em, float *vec, EditVert *example)
00112 {
00113         EditVert *eve;
00114         static int hashnr= 0;
00115 
00116         eve= callocvert(em, sizeof(EditVert), 1);
00117         BLI_addtail(&em->verts, eve);
00118         em->totvert++;
00119         
00120         if(vec) VECCOPY(eve->co, vec);
00121 
00122         eve->hash= hashnr++;
00123         if( hashnr>=EDHASHSIZE) hashnr= 0;
00124 
00125         /* new verts get keyindex of -1 since they did not
00126          * have a pre-editmode vertex order
00127          */
00128         eve->keyindex = -1;
00129 
00130         if(example) {
00131                 CustomData_em_copy_data(&em->vdata, &em->vdata, example->data, &eve->data);
00132                 eve->bweight = example->bweight;
00133         }
00134         else {
00135                 CustomData_em_set_default(&em->vdata, &eve->data);
00136         }
00137 
00138         return eve;
00139 }
00140 
00141 void free_editvert (EditMesh *em, EditVert *eve)
00142 {
00143 
00144         EM_remove_selection(em, eve, EDITVERT);
00145         CustomData_em_free_block(&em->vdata, &eve->data);
00146         if(eve->fast==0)
00147                 free(eve);
00148         
00149         em->totvert--;
00150 }
00151 
00152 
00153 EditEdge *findedgelist(EditMesh *em, EditVert *v1, EditVert *v2)
00154 {
00155         EditVert *v3;
00156         struct HashEdge *he;
00157 
00158         /* swap ? */
00159         if( v1 > v2) {
00160                 v3= v2; 
00161                 v2= v1; 
00162                 v1= v3;
00163         }
00164         
00165         if(em->hashedgetab==NULL)
00166                 em->hashedgetab= MEM_callocN(EDHASHSIZE*sizeof(struct HashEdge), "hashedgetab");
00167 
00168         he= em->hashedgetab + EDHASH(v1->hash, v2->hash);
00169         
00170         while(he) {
00171                 
00172                 if(he->eed && he->eed->v1==v1 && he->eed->v2==v2) return he->eed;
00173                 
00174                 he= he->next;
00175         }
00176         return 0;
00177 }
00178 
00179 static void insert_hashedge(EditMesh *em, EditEdge *eed)
00180 {
00181         /* assuming that eed is not in the list yet, and that a find has been done before */
00182         
00183         struct HashEdge *first, *he;
00184 
00185         first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
00186 
00187         if( first->eed==0 ) {
00188                 first->eed= eed;
00189         }
00190         else {
00191                 he= &eed->hash; 
00192                 he->eed= eed;
00193                 he->next= first->next;
00194                 first->next= he;
00195         }
00196 }
00197 
00198 static void remove_hashedge(EditMesh *em, EditEdge *eed)
00199 {
00200         /* assuming eed is in the list */
00201         
00202         struct HashEdge *first, *he, *prev=NULL;
00203 
00204         he=first= em->hashedgetab + EDHASH(eed->v1->hash, eed->v2->hash);
00205 
00206         while(he) {
00207                 if(he->eed == eed) {
00208                         /* remove from list */
00209                         if(he==first) {
00210                                 if(first->next) {
00211                                         he= first->next;
00212                                         first->eed= he->eed;
00213                                         first->next= he->next;
00214                                 }
00215                                 else he->eed= 0;
00216                         }
00217                         else {
00218                                 prev->next= he->next;
00219                         }
00220                         return;
00221                 }
00222                 prev= he;
00223                 he= he->next;
00224         }
00225 }
00226 
00227 EditEdge *addedgelist(EditMesh *em, EditVert *v1, EditVert *v2, EditEdge *example)
00228 {
00229         EditVert *v3;
00230         EditEdge *eed;
00231         int swap= 0;
00232         
00233         if(v1==v2) return NULL;
00234         if(v1==NULL || v2==NULL) return NULL;
00235 
00236         /* swap ? */
00237         if(v1>v2) {
00238                 v3= v2; 
00239                 v2= v1; 
00240                 v1= v3;
00241                 swap= 1;
00242         }
00243         
00244         /* find in hashlist */
00245         eed= findedgelist(em, v1, v2);
00246 
00247         if(eed==NULL) {
00248         
00249                 eed= (EditEdge *)callocedge(em, sizeof(EditEdge), 1);
00250                 eed->v1= v1;
00251                 eed->v2= v2;
00252                 BLI_addtail(&em->edges, eed);
00253                 eed->dir= swap;
00254                 insert_hashedge(em, eed);
00255                 em->totedge++;
00256                 
00257                 /* copy edge data:
00258                    rule is to do this with addedgelist call, before addfacelist */
00259                 if(example) {
00260                         eed->crease= example->crease;
00261                         eed->bweight= example->bweight;
00262                         eed->sharp = example->sharp;
00263                         eed->seam = example->seam;
00264                         eed->h |= (example->h & EM_FGON);
00265                 }
00266         }
00267         
00268         return eed;
00269 }
00270 
00271 void remedge(EditMesh *em, EditEdge *eed)
00272 {
00273         BLI_remlink(&em->edges, eed);
00274         remove_hashedge(em, eed);
00275         
00276         em->totedge--;
00277 }
00278 
00279 void free_editedge(EditMesh *em, EditEdge *eed)
00280 {
00281         EM_remove_selection(em, eed, EDITEDGE);
00282         if(eed->fast==0){ 
00283                 free(eed);
00284         }
00285 }
00286 
00287 void free_editface(EditMesh *em, EditFace *efa)
00288 {
00289         EM_remove_selection(em, efa, EDITFACE);
00290         
00291         if (em->act_face==efa) {
00292                 EM_set_actFace(em, em->faces.first == efa ? NULL : em->faces.first);
00293         }
00294                 
00295         CustomData_em_free_block(&em->fdata, &efa->data);
00296         if(efa->fast==0)
00297                 free(efa);
00298         
00299         em->totface--;
00300 }
00301 
00302 void free_vertlist(EditMesh *em, ListBase *edve) 
00303 {
00304         EditVert *eve, *next;
00305 
00306         if (!edve) return;
00307 
00308         eve= edve->first;
00309         while(eve) {
00310                 next= eve->next;
00311                 free_editvert(em, eve);
00312                 eve= next;
00313         }
00314         edve->first= edve->last= NULL;
00315         em->totvert= em->totvertsel= 0;
00316 }
00317 
00318 void free_edgelist(EditMesh *em, ListBase *lb)
00319 {
00320         EditEdge *eed, *next;
00321         
00322         eed= lb->first;
00323         while(eed) {
00324                 next= eed->next;
00325                 free_editedge(em, eed);
00326                 eed= next;
00327         }
00328         lb->first= lb->last= NULL;
00329         em->totedge= em->totedgesel= 0;
00330 }
00331 
00332 void free_facelist(EditMesh *em, ListBase *lb)
00333 {
00334         EditFace *efa, *next;
00335         
00336         efa= lb->first;
00337         while(efa) {
00338                 next= efa->next;
00339                 free_editface(em, efa);
00340                 efa= next;
00341         }
00342         lb->first= lb->last= NULL;
00343         em->totface= em->totfacesel= 0;
00344 }
00345 
00346 EditFace *addfacelist(EditMesh *em, EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, EditFace *example, EditFace *exampleEdges)
00347 {
00348         EditFace *efa;
00349         EditEdge *e1, *e2=0, *e3=0, *e4=0;
00350 
00351         /* added sanity check... seems to happen for some tools, or for enter editmode for corrupted meshes */
00352         if(v1==v4 || v2==v4 || v3==v4) v4= NULL;
00353         
00354         /* add face to list and do the edges */
00355         if(exampleEdges) {
00356                 e1= addedgelist(em, v1, v2, exampleEdges->e1);
00357                 e2= addedgelist(em, v2, v3, exampleEdges->e2);
00358                 if(v4) e3= addedgelist(em, v3, v4, exampleEdges->e3); 
00359                 else e3= addedgelist(em, v3, v1, exampleEdges->e3);
00360                 if(v4) e4= addedgelist(em, v4, v1, exampleEdges->e4);
00361         }
00362         else {
00363                 e1= addedgelist(em, v1, v2, NULL);
00364                 e2= addedgelist(em, v2, v3, NULL);
00365                 if(v4) e3= addedgelist(em, v3, v4, NULL); 
00366                 else e3= addedgelist(em, v3, v1, NULL);
00367                 if(v4) e4= addedgelist(em, v4, v1, NULL);
00368         }
00369         
00370         if(v1==v2 || v2==v3 || v1==v3) return NULL;
00371         if(e2==0) return NULL;
00372 
00373         efa= (EditFace *)callocface(em, sizeof(EditFace), 1);
00374         efa->v1= v1;
00375         efa->v2= v2;
00376         efa->v3= v3;
00377         efa->v4= v4;
00378 
00379         efa->e1= e1;
00380         efa->e2= e2;
00381         efa->e3= e3;
00382         efa->e4= e4;
00383 
00384         if(example) {
00385                 efa->mat_nr= example->mat_nr;
00386                 efa->flag= example->flag;
00387                 CustomData_em_copy_data(&em->fdata, &em->fdata, example->data, &efa->data);
00388                 CustomData_em_validate_data(&em->fdata, efa->data, efa->v4 ? 4 : 3);
00389         }
00390         else {
00391                 efa->mat_nr= em->mat_nr;
00392 
00393                 CustomData_em_set_default(&em->fdata, &efa->data);
00394         }
00395 
00396         BLI_addtail(&em->faces, efa);
00397         em->totface++;
00398         
00399         if(efa->v4) {
00400                 normal_quad_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
00401                 cent_quad_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
00402         }
00403         else {
00404                 normal_tri_v3( efa->n,efa->v1->co, efa->v2->co, efa->v3->co);
00405                 cent_tri_v3(efa->cent, efa->v1->co, efa->v2->co, efa->v3->co);
00406         }
00407 
00408         return efa;
00409 }
00410 
00411 /* ************************ end add/new/find ************  */
00412 
00413 /* ************************ Edit{Vert,Edge,Face} utilss ***************************** */
00414 
00415 /* some nice utility functions */
00416 
00417 EditVert *editedge_getOtherVert(EditEdge *eed, EditVert *eve)
00418 {
00419         if (eve==eed->v1) {
00420                 return eed->v2;
00421         } else if (eve==eed->v2) {
00422                 return eed->v1;
00423         } else {
00424                 return NULL;
00425         }
00426 }
00427 
00428 EditVert *editedge_getSharedVert(EditEdge *eed, EditEdge *eed2) 
00429 {
00430         if (eed->v1==eed2->v1 || eed->v1==eed2->v2) {
00431                 return eed->v1;
00432         } else if (eed->v2==eed2->v1 || eed->v2==eed2->v2) {
00433                 return eed->v2;
00434         } else {
00435                 return NULL;
00436         }
00437 }
00438 
00439 int editedge_containsVert(EditEdge *eed, EditVert *eve) 
00440 {
00441         return (eed->v1==eve || eed->v2==eve);
00442 }
00443 
00444 int editface_containsVert(EditFace *efa, EditVert *eve) 
00445 {
00446         return (efa->v1==eve || efa->v2==eve || efa->v3==eve || (efa->v4 && efa->v4==eve));
00447 }
00448 
00449 int editface_containsEdge(EditFace *efa, EditEdge *eed) 
00450 {
00451         return (efa->e1==eed || efa->e2==eed || efa->e3==eed || (efa->e4 && efa->e4==eed));
00452 }
00453 
00454 
00455 /* ************************ stuct EditMesh manipulation ***************************** */
00456 
00457 /* fake callocs for fastmalloc below */
00458 static void *calloc_fastvert(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
00459 {
00460         EditVert *eve= em->curvert++;
00461         eve->fast= 1;
00462         return eve;
00463 }
00464 static void *calloc_fastedge(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
00465 {
00466         EditEdge *eed= em->curedge++;
00467         eed->fast= 1;
00468         return eed;
00469 }
00470 static void *calloc_fastface(EditMesh *em, size_t UNUSED(size), size_t UNUSED(nr))
00471 {
00472         EditFace *efa= em->curface++;
00473         efa->fast= 1;
00474         return efa;
00475 }
00476 
00477 /* allocate 1 chunk for all vertices, edges, faces. These get tagged to
00478    prevent it from being freed
00479 */
00480 static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface)
00481 {
00482         if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts");
00483         else em->allverts= NULL;
00484         em->curvert= em->allverts;
00485         
00486         if(totedge==0) totedge= 4*totface;      // max possible
00487 
00488         if(totedge) em->alledges= MEM_callocN(totedge*sizeof(EditEdge), "alledges");
00489         else em->alledges= NULL;
00490         em->curedge= em->alledges;
00491         
00492         if(totface) em->allfaces= MEM_callocN(totface*sizeof(EditFace), "allfaces");
00493         else em->allfaces= NULL;
00494         em->curface= em->allfaces;
00495 
00496         callocvert= calloc_fastvert;
00497         callocedge= calloc_fastedge;
00498         callocface= calloc_fastface;
00499 }
00500 
00501 static void end_editmesh_fastmalloc(void)
00502 {
00503         callocvert= calloc_em;
00504         callocedge= calloc_em;
00505         callocface= calloc_em;
00506 }
00507 
00508 /* do not free editmesh itself here */
00509 void free_editMesh(EditMesh *em)
00510 {
00511         if(em==NULL) return;
00512 
00513         if(em->verts.first) free_vertlist(em, &em->verts);
00514         if(em->edges.first) free_edgelist(em, &em->edges);
00515         if(em->faces.first) free_facelist(em, &em->faces);
00516         if(em->selected.first) BLI_freelistN(&(em->selected));
00517 
00518         CustomData_free(&em->vdata, 0);
00519         CustomData_free(&em->fdata, 0);
00520 
00521         if(em->derivedFinal) {
00522                 if (em->derivedFinal!=em->derivedCage) {
00523                         em->derivedFinal->needsFree= 1;
00524                         em->derivedFinal->release(em->derivedFinal);
00525                 }
00526                 em->derivedFinal= NULL;
00527         }
00528         if(em->derivedCage) {
00529                 em->derivedCage->needsFree= 1;
00530                 em->derivedCage->release(em->derivedCage);
00531                 em->derivedCage= NULL;
00532         }
00533 
00534         /* DEBUG: hashtabs are slowest part of enter/exit editmode. here a testprint */
00535 #if 0
00536         if(em->hashedgetab) {
00537                 HashEdge *he, *hen;
00538                 int a, used=0, max=0, nr;
00539                 he= em->hashedgetab;
00540                 for(a=0; a<EDHASHSIZE; a++, he++) {
00541                         if(he->eed) used++;
00542                         hen= he->next;
00543                         nr= 0;
00544                         while(hen) {
00545                                 nr++;
00546                                 hen= hen->next;
00547                         }
00548                         if(max<nr) max= nr;
00549                 }
00550                 printf("hastab used %d max %d\n", used, max);
00551         }
00552 #endif
00553         if(em->hashedgetab) MEM_freeN(em->hashedgetab);
00554         em->hashedgetab= NULL;
00555         
00556         if(em->allverts) MEM_freeN(em->allverts);
00557         if(em->alledges) MEM_freeN(em->alledges);
00558         if(em->allfaces) MEM_freeN(em->allfaces);
00559         
00560         em->allverts= em->curvert= NULL;
00561         em->alledges= em->curedge= NULL;
00562         em->allfaces= em->curface= NULL;
00563         
00564         mesh_octree_table(NULL, NULL, NULL, 'e');
00565         mesh_mirrtopo_table(NULL, 'e');
00566 
00567         em->totvert= em->totedge= em->totface= 0;
00568 
00569 // XXX  if(em->retopo_paint_data) retopo_free_paint_data(em->retopo_paint_data);
00570         em->retopo_paint_data= NULL;
00571         em->act_face = NULL;
00572 }
00573 
00574 static void editMesh_set_hash(EditMesh *em)
00575 {
00576         EditEdge *eed;
00577 
00578         if(em->hashedgetab) MEM_freeN(em->hashedgetab);
00579         em->hashedgetab= NULL;
00580         
00581         for(eed=em->edges.first; eed; eed= eed->next)  {
00582                 if( findedgelist(em, eed->v1, eed->v2)==NULL )
00583                         insert_hashedge(em, eed);
00584         }
00585 
00586 }
00587 
00588 
00589 /* ************************ IN & OUT EDITMODE ***************************** */
00590 
00591 
00592 static void edge_normal_compare(EditEdge *eed, EditFace *efa1)
00593 {
00594         EditFace *efa2;
00595         float cent1[3], cent2[3];
00596         float inp;
00597         
00598         efa2 = eed->tmp.f;
00599         if(efa1==efa2) return;
00600         
00601         inp= efa1->n[0]*efa2->n[0] + efa1->n[1]*efa2->n[1] + efa1->n[2]*efa2->n[2];
00602         if(inp<0.999f && inp >-0.999f) eed->f2= 1;
00603                 
00604         if(efa1->v4) cent_quad_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co, efa1->v4->co);
00605         else cent_tri_v3(cent1, efa1->v1->co, efa1->v2->co, efa1->v3->co);
00606         if(efa2->v4) cent_quad_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co, efa2->v4->co);
00607         else cent_tri_v3(cent2, efa2->v1->co, efa2->v2->co, efa2->v3->co);
00608         
00609         sub_v3_v3v3(cent1, cent2, cent1);
00610         normalize_v3(cent1);
00611         inp= cent1[0]*efa1->n[0] + cent1[1]*efa1->n[1] + cent1[2]*efa1->n[2]; 
00612 
00613         if(inp < -0.001f) eed->f1= 1;
00614 }
00615 
00616 #if 0
00617 typedef struct {
00618         EditEdge *eed;
00619         float noLen,no[3];
00620         int adjCount;
00621 } EdgeDrawFlagInfo;
00622 
00623 static int edgeDrawFlagInfo_cmp(const void *av, const void *bv)
00624 {
00625         const EdgeDrawFlagInfo *a = av;
00626         const EdgeDrawFlagInfo *b = bv;
00627 
00628         if (a->noLen<b->noLen) return -1;
00629         else if (a->noLen>b->noLen) return 1;
00630         else return 0;
00631 }
00632 #endif
00633 
00634 static void edge_drawflags(Mesh *me, EditMesh *em)
00635 {
00636         EditVert *eve;
00637         EditEdge *eed, *e1, *e2, *e3, *e4;
00638         EditFace *efa;
00639         
00640         /* - count number of times edges are used in faces: 0 en 1 time means draw edge
00641          * - edges more than 1 time used: in *tmp.f is pointer to first face
00642          * - check all faces, when normal differs to much: draw (flag becomes 1)
00643          */
00644 
00645         /* later on: added flags for 'cylinder' and 'sphere' intersection tests in old
00646            game engine (2.04)
00647          */
00648         
00649         recalc_editnormals(em);
00650         
00651         /* init */
00652         eve= em->verts.first;
00653         while(eve) {
00654                 eve->f1= 1;             /* during test it's set at zero */
00655                 eve= eve->next;
00656         }
00657         eed= em->edges.first;
00658         while(eed) {
00659                 eed->f2= eed->f1= 0;
00660                 eed->tmp.f = 0;
00661                 eed= eed->next;
00662         }
00663 
00664         efa= em->faces.first;
00665         while(efa) {
00666                 e1= efa->e1;
00667                 e2= efa->e2;
00668                 e3= efa->e3;
00669                 e4= efa->e4;
00670                 if(e1->f2<4) e1->f2+= 1;
00671                 if(e2->f2<4) e2->f2+= 1;
00672                 if(e3->f2<4) e3->f2+= 1;
00673                 if(e4 && e4->f2<4) e4->f2+= 1;
00674                 
00675                 if(e1->tmp.f == 0) e1->tmp.f = (void *) efa;
00676                 if(e2->tmp.f == 0) e2->tmp.f = (void *) efa;
00677                 if(e3->tmp.f ==0) e3->tmp.f = (void *) efa;
00678                 if(e4 && (e4->tmp.f == 0)) e4->tmp.f = (void *) efa;
00679                 
00680                 efa= efa->next;
00681         }
00682 
00683         if(me->drawflag & ME_ALLEDGES) {
00684                 efa= em->faces.first;
00685                 while(efa) {
00686                         if(efa->e1->f2>=2) efa->e1->f2= 1;
00687                         if(efa->e2->f2>=2) efa->e2->f2= 1;
00688                         if(efa->e3->f2>=2) efa->e3->f2= 1;
00689                         if(efa->e4 && efa->e4->f2>=2) efa->e4->f2= 1;
00690                         
00691                         efa= efa->next;
00692                 }               
00693         }       
00694         else {
00695                 
00696                 /* handle single-edges for 'test cylinder flag' (old engine) */
00697                 
00698                 eed= em->edges.first;
00699                 while(eed) {
00700                         if(eed->f2==1) eed->f1= 1;
00701                         eed= eed->next;
00702                 }
00703 
00704                 /* all faces, all edges with flag==2: compare normal */
00705                 efa= em->faces.first;
00706                 while(efa) {
00707                         if(efa->e1->f2==2) edge_normal_compare(efa->e1, efa);
00708                         else efa->e1->f2= 1;
00709                         if(efa->e2->f2==2) edge_normal_compare(efa->e2, efa);
00710                         else efa->e2->f2= 1;
00711                         if(efa->e3->f2==2) edge_normal_compare(efa->e3, efa);
00712                         else efa->e3->f2= 1;
00713                         if(efa->e4) {
00714                                 if(efa->e4->f2==2) edge_normal_compare(efa->e4, efa);
00715                                 else efa->e4->f2= 1;
00716                         }
00717                         efa= efa->next;
00718                 }
00719                 
00720                 /* sphere collision flag */
00721                 
00722                 eed= em->edges.first;
00723                 while(eed) {
00724                         if(eed->f1!=1) {
00725                                 eed->v1->f1= eed->v2->f1= 0;
00726                         }
00727                         eed= eed->next;
00728                 }
00729                 
00730         }
00731 }
00732 
00733 /* turns Mesh into editmesh */
00734 void make_editMesh(Scene *scene, Object *ob)
00735 {
00736         Mesh *me= ob->data;
00737         MFace *mface;
00738         MVert *mvert;
00739         MSelect *mselect;
00740         KeyBlock *actkey;
00741         EditMesh *em;
00742         EditVert *eve, **evlist, *eve1, *eve2, *eve3, *eve4;
00743         EditFace *efa, *efa_last_sel= NULL;
00744         EditEdge *eed;
00745         EditSelection *ese;
00746         float *co, (*keyco)[3]= NULL;
00747         int tot, a, eekadoodle= 0;
00748         const short is_paint_sel= paint_facesel_test(ob);
00749 
00750         if(me->edit_mesh==NULL)
00751                 me->edit_mesh= MEM_callocN(sizeof(EditMesh), "editmesh");
00752         else 
00753                 /* because of reload */
00754                 free_editMesh(me->edit_mesh);
00755         
00756         em= me->edit_mesh;
00757         
00758         em->selectmode= scene->toolsettings->selectmode; // warning needs to be synced
00759         em->act_face = NULL;
00760         em->totvert= tot= me->totvert;
00761         em->totedge= me->totedge;
00762         em->totface= me->totface;
00763         
00764         if(tot==0) {
00765                 return;
00766         }
00767         
00768         if(ob->actcol > 0)
00769                 em->mat_nr= ob->actcol-1;
00770 
00771         /* initialize fastmalloc for editmesh */
00772         init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface);
00773 
00774         actkey = ob_get_keyblock(ob);
00775         if(actkey) {
00776                 /* undo-ing in past for previous editmode sessions gives corrupt 'keyindex' values */
00777                 undo_editmode_clear();
00778                 keyco= actkey->data;
00779                 em->shapenr= ob->shapenr;
00780         }
00781 
00782         /* make editverts */
00783         CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
00784         mvert= me->mvert;
00785 
00786         evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
00787         for(a=0; a<tot; a++, mvert++) {
00788                 
00789                 co= mvert->co;
00790 
00791                 /* edit the shape key coordinate if available */
00792                 if(keyco && a < actkey->totelem)
00793                         co= keyco[a];
00794 
00795                 eve= addvertlist(em, co, NULL);
00796                 evlist[a]= eve;
00797                 
00798                 /* face select sets selection in next loop */
00799                 if(!is_paint_sel)
00800                         eve->f |= (mvert->flag & 1);
00801                 
00802                 if (mvert->flag & ME_HIDE) eve->h= 1;
00803                 normal_short_to_float_v3(eve->no, mvert->no);
00804 
00805                 eve->bweight= ((float)mvert->bweight)/255.0f;
00806 
00807                 /* lets overwrite the keyindex of the editvert
00808                  * with the order it used to be in before
00809                  * editmode
00810                  */
00811                 eve->keyindex = a;
00812 
00813                 CustomData_to_em_block(&me->vdata, &em->vdata, a, &eve->data);
00814         }
00815 
00816         if(actkey && actkey->totelem!=me->totvert);
00817         else {
00818                 MEdge *medge= me->medge;
00819                 
00820                 CustomData_copy(&me->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
00821                 /* make edges */
00822                 for(a=0; a<me->totedge; a++, medge++) {
00823                         eed= addedgelist(em, evlist[medge->v1], evlist[medge->v2], NULL);
00824                         /* eed can be zero when v1 and v2 are identical, dxf import does this... */
00825                         if(eed) {
00826                                 eed->crease= ((float)medge->crease)/255.0f;
00827                                 eed->bweight= ((float)medge->bweight)/255.0f;
00828                                 
00829                                 if(medge->flag & ME_SEAM) eed->seam= 1;
00830                                 if(medge->flag & ME_SHARP) eed->sharp = 1;
00831                                 if(medge->flag & SELECT) eed->f |= SELECT;
00832                                 if(medge->flag & ME_FGON) eed->h= EM_FGON;      // 2 different defines!
00833                                 if(medge->flag & ME_HIDE) eed->h |= 1;
00834                                 if(em->selectmode==SCE_SELECT_EDGE) 
00835                                         EM_select_edge(eed, eed->f & SELECT);           // force edge selection to vertices, seems to be needed ...
00836                                 CustomData_to_em_block(&me->edata,&em->edata, a, &eed->data);
00837                         }
00838                 }
00839                 
00840                 CustomData_copy(&me->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
00841 
00842                 /* make faces */
00843                 mface= me->mface;
00844 
00845                 for(a=0; a<me->totface; a++, mface++) {
00846                         eve1= evlist[mface->v1];
00847                         eve2= evlist[mface->v2];
00848                         if(!mface->v3) eekadoodle= 1;
00849                         eve3= evlist[mface->v3];
00850                         if(mface->v4) eve4= evlist[mface->v4]; else eve4= NULL;
00851                         
00852                         efa= addfacelist(em, eve1, eve2, eve3, eve4, NULL, NULL);
00853 
00854                         if(efa) {
00855                                 CustomData_to_em_block(&me->fdata, &em->fdata, a, &efa->data);
00856 
00857                                 efa->mat_nr= mface->mat_nr;
00858                                 efa->flag= mface->flag & ~ME_HIDE;
00859                                 
00860                                 /* select and hide face flag */
00861                                 if(mface->flag & ME_HIDE) {
00862                                         efa->h= 1;
00863                                 } else {
00864                                         if (a==me->act_face) {
00865                                                 EM_set_actFace(em, efa);
00866                                         }
00867                                         
00868                                         /* dont allow hidden and selected */
00869                                         if(mface->flag & ME_FACE_SEL) {
00870                                                 efa->f |= SELECT;
00871                                                 
00872                                                 if(is_paint_sel) {
00873                                                         EM_select_face(efa, 1); /* flush down */
00874                                                 }
00875 
00876                                                 efa_last_sel= efa;
00877                                         }
00878                                 }
00879                         }
00880                 }
00881         }
00882         
00883         if(EM_get_actFace(em, 0)==NULL && efa_last_sel) {
00884                 EM_set_actFace(em, efa_last_sel);
00885         }
00886 
00887         if(eekadoodle)
00888                 error("This Mesh has old style edgecodes, please put it in the bugtracker!");
00889         
00890         MEM_freeN(evlist);
00891 
00892         end_editmesh_fastmalloc();      // resets global function pointers
00893         
00894         if(me->mselect){
00895                 //restore editselections
00896                 EM_init_index_arrays(em, 1,1,1);
00897                 mselect = me->mselect;
00898                 
00899                 for(a=0; a<me->totselect; a++, mselect++){
00900                         /*check if recorded selection is still valid, if so copy into editmesh*/
00901                         if( (mselect->type == EDITVERT && me->mvert[mselect->index].flag & SELECT) || (mselect->type == EDITEDGE && me->medge[mselect->index].flag & SELECT) || (mselect->type == EDITFACE && me->mface[mselect->index].flag & ME_FACE_SEL) ){
00902                                 ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
00903                                 ese->type = mselect->type;      
00904                                 if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else
00905                                 if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else
00906                                 if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index);
00907                                 BLI_addtail(&(em->selected),ese);
00908                         }
00909                 }
00910                 EM_free_index_arrays();
00911         }
00912         /* this creates coherent selections. also needed for older files */
00913         EM_selectmode_set(em);
00914         /* paranoia check to enforce hide rules */
00915         EM_hide_reset(em);
00916         /* sets helper flags which arent saved */
00917         EM_fgon_flags(em);
00918         
00919         if (EM_get_actFace(em, 0)==NULL) {
00920                 EM_set_actFace(em, em->faces.first ); /* will use the first face, this is so we alwats have an active face */
00921         }
00922 }
00923 
00924 /* makes Mesh out of editmesh */
00925 void load_editMesh(Scene *scene, Object *obedit)
00926 {
00927         Mesh *me= obedit->data;
00928         MVert *mvert, *oldverts;
00929         MEdge *medge;
00930         MFace *mface;
00931         MSelect *mselect;
00932         EditMesh *em= me->edit_mesh;
00933         EditVert *eve;
00934         EditFace *efa, *efa_act;
00935         EditEdge *eed;
00936         EditSelection *ese;
00937         float *fp, *newkey, *oldkey;
00938         int i, a, ototvert;
00939         
00940         /* this one also tests of edges are not in faces: */
00941         /* eed->f2==0: not in face, f2==1: draw it */
00942         /* eed->f1 : flag for dynaface (cylindertest, old engine) */
00943         /* eve->f1 : flag for dynaface (sphere test, old engine) */
00944         /* eve->f2 : being used in vertexnormals */
00945         edge_drawflags(me, em);
00946         
00947         EM_stats_update(em);
00948         
00949         /* new Vertex block */
00950         if(em->totvert==0) mvert= NULL;
00951         else mvert= MEM_callocN(em->totvert*sizeof(MVert), "loadeditMesh vert");
00952 
00953         /* new Edge block */
00954         if(em->totedge==0) medge= NULL;
00955         else medge= MEM_callocN(em->totedge*sizeof(MEdge), "loadeditMesh edge");
00956         
00957         /* new Face block */
00958         if(em->totface==0) mface= NULL;
00959         else mface= MEM_callocN(em->totface*sizeof(MFace), "loadeditMesh face");
00960 
00961         /* lets save the old verts just in case we are actually working on
00962          * a key ... we now do processing of the keys at the end */
00963         oldverts= me->mvert;
00964         ototvert= me->totvert;
00965 
00966         /* don't free this yet */
00967         CustomData_set_layer(&me->vdata, CD_MVERT, NULL);
00968 
00969         /* free custom data */
00970         CustomData_free(&me->vdata, me->totvert);
00971         CustomData_free(&me->edata, me->totedge);
00972         CustomData_free(&me->fdata, me->totface);
00973 
00974         /* add new custom data */
00975         me->totvert= em->totvert;
00976         me->totedge= em->totedge;
00977         me->totface= em->totface;
00978 
00979         CustomData_copy(&em->vdata, &me->vdata, CD_MASK_MESH, CD_CALLOC, me->totvert);
00980         CustomData_copy(&em->edata, &me->edata, CD_MASK_MESH, CD_CALLOC, me->totedge);
00981         CustomData_copy(&em->fdata, &me->fdata, CD_MASK_MESH, CD_CALLOC, me->totface);
00982 
00983         CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert);
00984         CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge);
00985         CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, mface, me->totface);
00986         mesh_update_customdata_pointers(me);
00987 
00988         /* the vertices, use ->tmp.l as counter */
00989         eve= em->verts.first;
00990         a= 0;
00991 
00992         while(eve) {
00993                 VECCOPY(mvert->co, eve->co);
00994 
00995                 /* vertex normal */
00996                 normal_float_to_short_v3(mvert->no, eve->no);
00997 
00998                 /* note: it used to remove me->dvert when it was not in use, cancelled
00999                    that... annoying when you have a fresh vgroup */
01000                 CustomData_from_em_block(&em->vdata, &me->vdata, eve->data, a);
01001 
01002                 eve->tmp.l = a++;  /* counter */
01003                         
01004                 mvert->flag= 0;
01005                 mvert->flag |= (eve->f & SELECT);
01006                 if (eve->h) mvert->flag |= ME_HIDE;
01007                 
01008                 mvert->bweight= (char)(255.0f*eve->bweight);
01009 
01010                 eve= eve->next;
01011                 mvert++;
01012         }
01013 
01014         /* the edges */
01015         a= 0;
01016         eed= em->edges.first;
01017         while(eed) {
01018                 medge->v1= (unsigned int) eed->v1->tmp.l;
01019                 medge->v2= (unsigned int) eed->v2->tmp.l;
01020                 
01021                 medge->flag= (eed->f & SELECT) | ME_EDGERENDER;
01022                 if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
01023                 if(eed->f2==0) medge->flag |= ME_LOOSEEDGE;
01024                 if(eed->sharp) medge->flag |= ME_SHARP;
01025                 if(eed->seam) medge->flag |= ME_SEAM;
01026                 if(eed->h & EM_FGON) medge->flag |= ME_FGON;    // different defines yes
01027                 if(eed->h & 1) medge->flag |= ME_HIDE;
01028                 
01029                 medge->crease= (char)(255.0f*eed->crease);
01030                 medge->bweight= (char)(255.0f*eed->bweight);
01031                 CustomData_from_em_block(&em->edata, &me->edata, eed->data, a);         
01032 
01033                 eed->tmp.l = a++;
01034                 
01035                 medge++;
01036                 eed= eed->next;
01037         }
01038 
01039         /* the faces */
01040         a = 0;
01041         efa= em->faces.first;
01042         efa_act= EM_get_actFace(em, 0);
01043         i = 0;
01044         me->act_face = -1;
01045         while(efa) {
01046                 mface= &((MFace *) me->mface)[i];
01047                 
01048                 mface->v1= (unsigned int) efa->v1->tmp.l;
01049                 mface->v2= (unsigned int) efa->v2->tmp.l;
01050                 mface->v3= (unsigned int) efa->v3->tmp.l;
01051                 if (efa->v4) mface->v4 = (unsigned int) efa->v4->tmp.l;
01052 
01053                 mface->mat_nr= efa->mat_nr;
01054                 
01055                 mface->flag= efa->flag;
01056                 /* bit 0 of flag is already taken for smooth... */
01057                 
01058                 if(efa->h) {
01059                         mface->flag |= ME_HIDE;
01060                         mface->flag &= ~ME_FACE_SEL;
01061                 } else {
01062                         if(efa->f & 1) mface->flag |= ME_FACE_SEL;
01063                         else mface->flag &= ~ME_FACE_SEL;
01064                 }
01065                         
01066                 /* watch: efa->e1->f2==0 means loose edge */ 
01067                         
01068                 if(efa->e1->f2==1) {
01069                         efa->e1->f2= 2;
01070                 }                       
01071                 if(efa->e2->f2==1) {
01072                         efa->e2->f2= 2;
01073                 }
01074                 if(efa->e3->f2==1) {
01075                         efa->e3->f2= 2;
01076                 }
01077                 if(efa->e4 && efa->e4->f2==1) {
01078                         efa->e4->f2= 2;
01079                 }
01080 
01081                 CustomData_from_em_block(&em->fdata, &me->fdata, efa->data, i);
01082 
01083                 /* no index '0' at location 3 or 4 */
01084                 test_index_face(mface, &me->fdata, i, efa->v4?4:3);
01085                 
01086                 if (efa_act == efa)
01087                         me->act_face = a;
01088 
01089                 efa->tmp.l = a++;
01090                 i++;
01091                 efa= efa->next;
01092         }
01093 
01094         /* patch hook indices and vertex parents */
01095         {
01096                 Object *ob;
01097                 ModifierData *md;
01098                 EditVert **vertMap = NULL;
01099                 int j;
01100 
01101                 for (ob=G.main->object.first; ob; ob=ob->id.next) {
01102                         if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) {
01103                                 
01104                                 /* duplicate code from below, make it function later...? */
01105                                 if (!vertMap) {
01106                                         vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
01107                                         
01108                                         for (eve=em->verts.first; eve; eve=eve->next) {
01109                                                 if (eve->keyindex!=-1)
01110                                                         vertMap[eve->keyindex] = eve;
01111                                         }
01112                                 }
01113                                 if(ob->par1 < ototvert) {
01114                                         eve = vertMap[ob->par1];
01115                                         if(eve) ob->par1= eve->tmp.l;
01116                                 }
01117                                 if(ob->par2 < ototvert) {
01118                                         eve = vertMap[ob->par2];
01119                                         if(eve) ob->par2= eve->tmp.l;
01120                                 }
01121                                 if(ob->par3 < ototvert) {
01122                                         eve = vertMap[ob->par3];
01123                                         if(eve) ob->par3= eve->tmp.l;
01124                                 }
01125                                 
01126                         }
01127                         if (ob->data==me) {
01128                                 for (md=ob->modifiers.first; md; md=md->next) {
01129                                         if (md->type==eModifierType_Hook) {
01130                                                 HookModifierData *hmd = (HookModifierData*) md;
01131 
01132                                                 if (!vertMap) {
01133                                                         vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
01134 
01135                                                         for (eve=em->verts.first; eve; eve=eve->next) {
01136                                                                 if (eve->keyindex!=-1)
01137                                                                         vertMap[eve->keyindex] = eve;
01138                                                         }
01139                                                 }
01140                                                 
01141                                                 for (i=j=0; i<hmd->totindex; i++) {
01142                                                         if(hmd->indexar[i] < ototvert) {
01143                                                                 eve = vertMap[hmd->indexar[i]];
01144                                                                 
01145                                                                 if (eve) {
01146                                                                         hmd->indexar[j++] = eve->tmp.l;
01147                                                                 }
01148                                                         }
01149                                                         else j++;
01150                                                 }
01151 
01152                                                 hmd->totindex = j;
01153                                         }
01154                                 }
01155                         }
01156                 }
01157 
01158                 if (vertMap) MEM_freeN(vertMap);
01159         }
01160 
01161         /* are there keys? */
01162         if(me->key) {
01163                 KeyBlock *currkey;
01164                 KeyBlock *actkey= BLI_findlink(&me->key->block, em->shapenr-1);
01165 
01166                 float (*ofs)[3] = NULL;
01167 
01168                 /* editing the base key should update others */
01169                 if(me->key->type==KEY_RELATIVE && oldverts) {
01170                         int act_is_basis = 0;
01171                         /* find if this key is a basis for any others */
01172                         for(currkey = me->key->block.first; currkey; currkey= currkey->next) {
01173                                 if(em->shapenr-1 == currkey->relative) {
01174                                         act_is_basis = 1;
01175                                         break;
01176                                 }
01177                         }
01178 
01179                         if(act_is_basis) { /* active key is a base */
01180                                 float (*fp)[3]= actkey->data;
01181                                 i=0;
01182                                 ofs= MEM_callocN(sizeof(float) * 3 * em->totvert,  "currkey->data");
01183                                 eve= em->verts.first;
01184                                 mvert = me->mvert;
01185                                 while(eve) {
01186                                         if(eve->keyindex>=0)
01187                                                 VECSUB(ofs[i], mvert->co, fp[eve->keyindex]);
01188 
01189                                         eve= eve->next;
01190                                         i++;
01191                                         mvert++;
01192                                 }
01193                         }
01194                 }
01195 
01196 
01197                 /* Lets reorder the key data so that things line up roughly
01198                  * with the way things were before editmode */
01199                 currkey = me->key->block.first;
01200                 while(currkey) {
01201                         int apply_offset = (ofs && (currkey != actkey) && (em->shapenr-1 == currkey->relative));
01202 
01203                         fp= newkey= MEM_callocN(me->key->elemsize*em->totvert,  "currkey->data");
01204                         oldkey = currkey->data;
01205 
01206                         eve= em->verts.first;
01207 
01208                         i = 0;
01209                         mvert = me->mvert;
01210                         while(eve) {
01211                                 if (eve->keyindex >= 0 && eve->keyindex < currkey->totelem) { // valid old vertex
01212                                         if(currkey == actkey) {
01213                                                 if(actkey == me->key->refkey) {
01214                                                         VECCOPY(fp, mvert->co);
01215                                                 }
01216                                                 else {
01217                                                         VECCOPY(fp, mvert->co);
01218                                                         if(oldverts) {
01219                                                                 VECCOPY(mvert->co, oldverts[eve->keyindex].co);
01220                                                         }
01221                                                 }
01222                                         }
01223                                         else {
01224                                                 if(oldkey) {
01225                                                         VECCOPY(fp, oldkey + 3 * eve->keyindex);
01226                                                 }
01227                                         }
01228                                 }
01229                                 else {
01230                                         VECCOPY(fp, mvert->co);
01231                                 }
01232 
01233                                 /* propagate edited basis offsets to other shapes */
01234                                 if(apply_offset) {
01235                                         VECADD(fp, fp, ofs[i]);
01236                                 }
01237 
01238                                 fp+= 3;
01239                                 ++i;
01240                                 ++mvert;
01241                                 eve= eve->next;
01242                         }
01243                         currkey->totelem= em->totvert;
01244                         if(currkey->data) MEM_freeN(currkey->data);
01245                         currkey->data = newkey;
01246                         
01247                         currkey= currkey->next;
01248                 }
01249 
01250                 if(ofs) MEM_freeN(ofs);
01251         }
01252 
01253         if(oldverts) MEM_freeN(oldverts);
01254         
01255         i = 0;
01256         for(ese=em->selected.first; ese; ese=ese->next) i++;
01257         me->totselect = i;
01258         if(i==0) mselect= NULL;
01259         else mselect= MEM_callocN(i*sizeof(MSelect), "loadeditMesh selections");
01260         
01261         if(me->mselect) MEM_freeN(me->mselect);
01262         me->mselect= mselect;
01263         
01264         for(ese=em->selected.first; ese; ese=ese->next){
01265                 mselect->type = ese->type;
01266                 if(ese->type == EDITVERT) mselect->index = ((EditVert*)ese->data)->tmp.l;
01267                 else if(ese->type == EDITEDGE) mselect->index = ((EditEdge*)ese->data)->tmp.l;
01268                 else if(ese->type == EDITFACE) mselect->index = ((EditFace*)ese->data)->tmp.l;
01269                 mselect++;
01270         }
01271         
01272         /* to be sure: clear ->tmp.l pointers */
01273         eve= em->verts.first;
01274         while(eve) {
01275                 eve->tmp.l = 0;
01276                 eve= eve->next;
01277         }
01278         
01279         eed= em->edges.first;
01280         while(eed) { 
01281                 eed->tmp.l = 0;
01282                 eed= eed->next;
01283         }
01284         
01285         efa= em->faces.first;
01286         while(efa) {
01287                 efa->tmp.l = 0;
01288                 efa= efa->next;
01289         }
01290         
01291         /* remake softbody of all users */
01292         if(me->id.us>1) {
01293                 Base *base;
01294                 for(base= scene->base.first; base; base= base->next)
01295                         if(base->object->data==me)
01296                                 base->object->recalc |= OB_RECALC_DATA;
01297         }
01298 
01299         mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
01300 
01301         /* topology could be changed, ensure mdisps are ok */
01302         multires_topology_changed(scene, obedit);
01303 }
01304 
01305 void remake_editMesh(Scene *scene, Object *ob)
01306 {
01307         make_editMesh(scene, ob);
01308         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
01309         BIF_undo_push("Undo all changes");
01310 }
01311 
01312 /* *************** Operator: separate parts *************/
01313 
01314 static EnumPropertyItem prop_separate_types[] = {
01315         {0, "SELECTED", 0, "Selection", ""},
01316         {1, "MATERIAL", 0, "By Material", ""},
01317         {2, "LOOSE", 0, "By loose parts", ""},
01318         {0, NULL, 0, NULL, NULL}
01319 };
01320 
01321 /* return 1: success */
01322 static int mesh_separate_selected(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
01323 {
01324         EditMesh *em, *emnew;
01325         EditVert *eve, *v1;
01326         EditEdge *eed, *e1;
01327         EditFace *efa, *f1;
01328         Object *obedit;
01329         Mesh *me, *menew;
01330         Base *basenew;
01331         
01332         if(editbase==NULL) return 0;
01333         
01334         obedit= editbase->object;
01335         me= obedit->data;
01336         em= BKE_mesh_get_editmesh(me);
01337         if(me->key) {
01338                 BKE_report(op->reports, RPT_WARNING, "Can't separate mesh with shape keys.");
01339                 BKE_mesh_end_editmesh(me, em);
01340                 return 0;
01341         }
01342         
01343         if(em->selected.first) 
01344                 BLI_freelistN(&(em->selected)); /* clear the selection order */
01345                 
01346         EM_selectmode_set(em);  // enforce full consistent selection flags 
01347         
01348         EM_stats_update(em);
01349         
01350         if(em->totvertsel==0) {
01351                 BKE_mesh_end_editmesh(me, em);
01352                 return 0;
01353         }
01354         
01355         /* we are going to work as follows:
01356          * 1. add a linked duplicate object: this will be the new one, we remember old pointer
01357          * 2. give new object empty mesh and put in editmode
01358          * 3: do a split if needed on current editmesh.
01359          * 4. copy over: all NOT selected verts, edges, faces
01360          * 5. call load_editMesh() on the new object
01361          */
01362         
01363         /* 1 */
01364         basenew= ED_object_add_duplicate(bmain, scene, editbase, 0);    /* 0 = fully linked */
01365         ED_base_object_select(basenew, BA_DESELECT);
01366         
01367         /* 2 */
01368         basenew->object->data= menew= add_mesh(me->id.name+2);  /* empty */
01369         assign_matarar(basenew->object, give_matarar(obedit), *give_totcolp(obedit)); /* new in 2.5 */
01370         me->id.us--;
01371         make_editMesh(scene, basenew->object);
01372         emnew= menew->edit_mesh;
01373         CustomData_copy(&em->vdata, &emnew->vdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
01374         CustomData_copy(&em->edata, &emnew->edata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
01375         CustomData_copy(&em->fdata, &emnew->fdata, CD_MASK_EDITMESH, CD_DEFAULT, 0);
01376         
01377         /* 3 */
01378         /* SPLIT: first make duplicate */
01379         adduplicateflag(em, SELECT);
01380         /* SPLIT: old faces have 3x flag 128 set, delete these ones */
01381         delfaceflag(em, 128);
01382         /* since we do tricky things with verts/edges/faces, this makes sure all is selected coherent */
01383         EM_selectmode_set(em);
01384         
01385         /* 4 */
01386         /* move over: everything that is selected */
01387         for(eve= em->verts.first; eve; eve= v1) {
01388                 v1= eve->next;
01389                 if(eve->f & SELECT) {
01390                         BLI_remlink(&em->verts, eve);
01391                         BLI_addtail(&emnew->verts, eve);
01392                 }
01393         }
01394         
01395         for(eed= em->edges.first; eed; eed= e1) {
01396                 e1= eed->next;
01397                 if(eed->f & SELECT) {
01398                         BLI_remlink(&em->edges, eed);
01399                         BLI_addtail(&emnew->edges, eed);
01400                 }
01401         }
01402         
01403         for(efa= em->faces.first; efa; efa= f1) {
01404                 f1= efa->next;
01405                 if (efa == em->act_face && (efa->f & SELECT)) {
01406                         EM_set_actFace(em, NULL);
01407                 }
01408 
01409                 if(efa->f & SELECT) {
01410                         BLI_remlink(&em->faces, efa);
01411                         BLI_addtail(&emnew->faces, efa);
01412                 }
01413         }
01414 
01415         /* 5 */
01416         load_editMesh(scene, basenew->object);
01417         free_editMesh(emnew);
01418         MEM_freeN(menew->edit_mesh);
01419         menew->edit_mesh= NULL;
01420 
01421         /* copy settings */
01422         menew->texflag= me->texflag;
01423         menew->drawflag= me->drawflag;
01424         menew->flag= me->flag;
01425         menew->editflag= me->editflag;
01426         menew->smoothresh= me->smoothresh;
01427 
01428         /* hashedges are invalid now, make new! */
01429         editMesh_set_hash(em);
01430 
01431         DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); 
01432         DAG_id_tag_update(&basenew->object->id, OB_RECALC_DATA);        
01433 
01434         BKE_mesh_end_editmesh(me, em);
01435 
01436         return 1;
01437 }
01438 
01439 /* return 1: success */
01440 static int mesh_separate_material(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
01441 {
01442         Mesh *me= editbase->object->data;
01443         EditMesh *em= BKE_mesh_get_editmesh(me);
01444         unsigned char curr_mat;
01445         
01446         for (curr_mat = 1; curr_mat < editbase->object->totcol; ++curr_mat) {
01447                 /* clear selection, we're going to use that to select material group */
01448                 EM_clear_flag_all(em, SELECT);
01449                 /* select the material */
01450                 EM_select_by_material(em, curr_mat);
01451                 /* and now separate */
01452                 if(0==mesh_separate_selected(op, bmain, scene, editbase)) {
01453                         BKE_mesh_end_editmesh(me, em);
01454                         return 0;
01455                 }
01456         }
01457 
01458         BKE_mesh_end_editmesh(me, em);
01459         return 1;
01460 }
01461 
01462 /* return 1: success */
01463 static int mesh_separate_loose(wmOperator *op, Main *bmain, Scene *scene, Base *editbase)
01464 {
01465         Mesh *me;
01466         EditMesh *em;
01467         int doit= 1;
01468         
01469         me= editbase->object->data;
01470         em= BKE_mesh_get_editmesh(me);
01471         
01472         if(me->key) {
01473                 error("Can't separate with vertex keys");
01474                 BKE_mesh_end_editmesh(me, em);
01475                 return 0;
01476         }
01477         
01478         EM_clear_flag_all(em, SELECT);
01479 
01480         while(doit) {
01481                 /* Select a random vert to start with */
01482                 EditVert *eve;
01483                 int tot;
01484 
01485                 /* check if all verts that are visible have been done */
01486                 for(eve=em->verts.first; eve; eve= eve->next)
01487                         if(!eve->h) break;
01488                 if(eve==NULL) break; /* only hidden verts left, quit early */
01489 
01490                 /* first non hidden vert */
01491                 eve->f |= SELECT;
01492                 
01493                 selectconnected_mesh_all(em);
01494                 
01495                 /* don't separate the very last part */
01496                 for(eve=em->verts.first; eve; eve= eve->next)
01497                         if((eve->f & SELECT)==0) break;
01498                 if(eve==NULL) break;
01499 
01500                 tot= BLI_countlist(&em->verts);
01501 
01502                 /* and now separate */
01503                 doit= mesh_separate_selected(op, bmain, scene, editbase);
01504 
01505                 /* with hidden verts this can happen */
01506                 if(tot == BLI_countlist(&em->verts))
01507                         break;
01508         }
01509 
01510         BKE_mesh_end_editmesh(me, em);
01511         return 1;
01512 }
01513 
01514 
01515 static int mesh_separate_exec(bContext *C, wmOperator *op)
01516 {
01517         Main *bmain= CTX_data_main(C);
01518         Scene *scene= CTX_data_scene(C);
01519         Base *base= CTX_data_active_base(C);
01520         int retval= 0, type= RNA_enum_get(op->ptr, "type");
01521         
01522         if(type == 0)
01523                 retval= mesh_separate_selected(op, bmain, scene, base);
01524         else if(type == 1)
01525                 retval= mesh_separate_material(op, bmain, scene, base);
01526         else if(type == 2)
01527                 retval= mesh_separate_loose(op, bmain, scene, base);
01528            
01529         if(retval) {
01530                 WM_event_add_notifier(C, NC_GEOM|ND_DATA, base->object->data);
01531 
01532                 // XXX: new object was created, but selection wasn't actually changed
01533                 //      need this for outliner update without adding new ND. nazgul.
01534                 WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
01535 
01536                 return OPERATOR_FINISHED;
01537         }
01538         return OPERATOR_CANCELLED;
01539 }
01540 
01541 void MESH_OT_separate(wmOperatorType *ot)
01542 {
01543         /* identifiers */
01544         ot->name= "Separate";
01545         ot->description= "Separate selected geometry into a new mesh";
01546         ot->idname= "MESH_OT_separate";
01547         
01548         /* api callbacks */
01549         ot->invoke= WM_menu_invoke;
01550         ot->exec= mesh_separate_exec;
01551         ot->poll= ED_operator_editmesh;
01552         
01553         /* flags */
01554         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01555         
01556         ot->prop= RNA_def_enum(ot->srna, "type", prop_separate_types, 0, "Type", "");
01557 }
01558 
01559 
01560 /* ******************************************** */
01561 
01562 /* *************** UNDO ***************************** */
01563 /* new mesh undo, based on pushing editmesh data itself */
01564 /* reuses same code as for global and curve undo... unify that (ton) */
01565 
01566 /* only one 'hack', to save memory it doesn't store the first push, but does a remake editmesh */
01567 
01568 /* a compressed version of editmesh data */
01569 
01570 typedef struct EditVertC
01571 {
01572         float no[3];
01573         float co[3];
01574         unsigned char f, h;
01575         short bweight;
01576         int keyindex;
01577 } EditVertC;
01578 
01579 typedef struct EditEdgeC
01580 {
01581         int v1, v2;
01582         unsigned char f, h, seam, sharp, pad;
01583         short crease, bweight, fgoni;
01584 } EditEdgeC;
01585 
01586 typedef struct EditFaceC
01587 {
01588         int v1, v2, v3, v4;
01589         unsigned char flag, f, h, fgonf, pad1;
01590         short mat_nr;
01591 } EditFaceC;
01592 
01593 typedef struct EditSelectionC{
01594         short type;
01595         int index;
01596 }EditSelectionC;
01597 
01598 typedef struct UndoMesh {
01599         EditVertC *verts;
01600         EditEdgeC *edges;
01601         EditFaceC *faces;
01602         EditSelectionC *selected;
01603         int totvert, totedge, totface, totsel;
01604         int selectmode, shapenr;
01605         char retopo_mode;
01606         CustomData vdata, edata, fdata;
01607 } UndoMesh;
01608 
01609 /* for callbacks */
01610 
01611 static void free_undoMesh(void *umv)
01612 {
01613         UndoMesh *um= umv;
01614         
01615         if(um->verts) MEM_freeN(um->verts);
01616         if(um->edges) MEM_freeN(um->edges);
01617         if(um->faces) MEM_freeN(um->faces);
01618         if(um->selected) MEM_freeN(um->selected);
01619 // XXX  if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data);
01620         CustomData_free(&um->vdata, um->totvert);
01621         CustomData_free(&um->edata, um->totedge);
01622         CustomData_free(&um->fdata, um->totface);
01623         MEM_freeN(um);
01624 }
01625 
01626 static void *editMesh_to_undoMesh(void *emv)
01627 {
01628         EditMesh *em= (EditMesh *)emv;
01629         UndoMesh *um;
01630         EditVert *eve;
01631         EditEdge *eed;
01632         EditFace *efa;
01633         EditSelection *ese;
01634         EditVertC *evec=NULL;
01635         EditEdgeC *eedc=NULL;
01636         EditFaceC *efac=NULL;
01637         EditSelectionC *esec=NULL;
01638         int a;
01639 
01640         um= MEM_callocN(sizeof(UndoMesh), "undomesh");
01641         
01642         um->selectmode = em->selectmode;
01643         um->shapenr = em->shapenr;
01644         
01645         for(eve=em->verts.first; eve; eve= eve->next) um->totvert++;
01646         for(eed=em->edges.first; eed; eed= eed->next) um->totedge++;
01647         for(efa=em->faces.first; efa; efa= efa->next) um->totface++;
01648         for(ese=em->selected.first; ese; ese=ese->next) um->totsel++; 
01649         /* malloc blocks */
01650         
01651         if(um->totvert) evec= um->verts= MEM_callocN(um->totvert*sizeof(EditVertC), "allvertsC");
01652         if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC");
01653         if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC");
01654         if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections");
01655 
01656         if(um->totvert) CustomData_copy(&em->vdata, &um->vdata, CD_MASK_EDITMESH, CD_CALLOC, um->totvert);
01657         if(um->totedge) CustomData_copy(&em->edata, &um->edata, CD_MASK_EDITMESH, CD_CALLOC, um->totedge);
01658         if(um->totface) CustomData_copy(&em->fdata, &um->fdata, CD_MASK_EDITMESH, CD_CALLOC, um->totface);
01659         
01660         /* now copy vertices */
01661         a = 0;
01662         for(eve=em->verts.first; eve; eve= eve->next, evec++, a++) {
01663                 VECCOPY(evec->co, eve->co);
01664                 VECCOPY(evec->no, eve->no);
01665 
01666                 evec->f= eve->f;
01667                 evec->h= eve->h;
01668                 evec->keyindex= eve->keyindex;
01669                 eve->tmp.l = a; /*store index*/
01670                 evec->bweight= (short)(eve->bweight*255.0f);
01671 
01672                 CustomData_from_em_block(&em->vdata, &um->vdata, eve->data, a);
01673         }
01674         
01675         /* copy edges */
01676         a = 0;
01677         for(eed=em->edges.first; eed; eed= eed->next, eedc++, a++)  {
01678                 eedc->v1= (int)eed->v1->tmp.l;
01679                 eedc->v2= (int)eed->v2->tmp.l;
01680                 eedc->f= eed->f;
01681                 eedc->h= eed->h;
01682                 eedc->seam= eed->seam;
01683                 eedc->sharp= eed->sharp;
01684                 eedc->crease= (short)(eed->crease*255.0f);
01685                 eedc->bweight= (short)(eed->bweight*255.0f);
01686                 eedc->fgoni= eed->fgoni;
01687                 eed->tmp.l = a; /*store index*/
01688                 CustomData_from_em_block(&em->edata, &um->edata, eed->data, a);
01689         
01690         }
01691         
01692         /* copy faces */
01693         a = 0;
01694         for(efa=em->faces.first; efa; efa= efa->next, efac++, a++) {
01695                 efac->v1= (int)efa->v1->tmp.l;
01696                 efac->v2= (int)efa->v2->tmp.l;
01697                 efac->v3= (int)efa->v3->tmp.l;
01698                 if(efa->v4) efac->v4= (int)efa->v4->tmp.l;
01699                 else efac->v4= -1;
01700                 
01701                 efac->mat_nr= efa->mat_nr;
01702                 efac->flag= efa->flag;
01703                 efac->f= efa->f;
01704                 efac->h= efa->h;
01705                 efac->fgonf= efa->fgonf;
01706 
01707                 efa->tmp.l = a; /*store index*/
01708 
01709                 CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a);
01710         }
01711         
01712         a = 0;
01713         for(ese=em->selected.first; ese; ese=ese->next, esec++){
01714                 esec->type = ese->type;
01715                 if(ese->type == EDITVERT) a = esec->index = ((EditVert*)ese->data)->tmp.l; 
01716                 else if(ese->type == EDITEDGE) a = esec->index = ((EditEdge*)ese->data)->tmp.l; 
01717                 else if(ese->type == EDITFACE) a = esec->index = ((EditFace*)ese->data)->tmp.l;
01718         }
01719 
01720 // XXX  um->retopo_paint_data= retopo_paint_data_copy(em->retopo_paint_data);
01721 //      um->retopo_mode= scene->toolsettings->retopo_mode;
01722         
01723         return um;
01724 }
01725 
01726 static void undoMesh_to_editMesh(void *umv, void *emv)
01727 {
01728         EditMesh *em= (EditMesh *)emv;
01729         UndoMesh *um= (UndoMesh *)umv;
01730         EditVert *eve, **evar=NULL;
01731         EditEdge *eed;
01732         EditFace *efa;
01733         EditSelection *ese;
01734         EditVertC *evec;
01735         EditEdgeC *eedc;
01736         EditFaceC *efac;
01737         EditSelectionC *esec;
01738         int a=0;
01739 
01740         free_editMesh(em);
01741         
01742         /* malloc blocks */
01743         memset(em, 0, sizeof(EditMesh));
01744                 
01745         em->selectmode = um->selectmode;
01746         em->shapenr = um->shapenr;
01747         
01748         init_editmesh_fastmalloc(em, um->totvert, um->totedge, um->totface);
01749 
01750         CustomData_free(&em->vdata, 0);
01751         CustomData_free(&em->edata, 0);
01752         CustomData_free(&em->fdata, 0);
01753 
01754         CustomData_copy(&um->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
01755         CustomData_copy(&um->edata, &em->edata, CD_MASK_EDITMESH, CD_CALLOC, 0);
01756         CustomData_copy(&um->fdata, &em->fdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
01757 
01758         /* now copy vertices */
01759 
01760         if(um->totvert) evar= MEM_mallocN(um->totvert*sizeof(EditVert *), "vertex ar");
01761         for(a=0, evec= um->verts; a<um->totvert; a++, evec++) {
01762                 eve= addvertlist(em, evec->co, NULL);
01763                 evar[a]= eve;
01764 
01765                 VECCOPY(eve->no, evec->no);
01766                 eve->f= evec->f;
01767                 eve->h= evec->h;
01768                 eve->keyindex= evec->keyindex;
01769                 eve->bweight= ((float)evec->bweight)/255.0f;
01770 
01771                 CustomData_to_em_block(&um->vdata, &em->vdata, a, &eve->data);
01772         }
01773 
01774         /* copy edges */
01775         for(a=0, eedc= um->edges; a<um->totedge; a++, eedc++) {
01776                 eed= addedgelist(em, evar[eedc->v1], evar[eedc->v2], NULL);
01777 
01778                 eed->f= eedc->f;
01779                 eed->h= eedc->h;
01780                 eed->seam= eedc->seam;
01781                 eed->sharp= eedc->sharp;
01782                 eed->fgoni= eedc->fgoni;
01783                 eed->crease= ((float)eedc->crease)/255.0f;
01784                 eed->bweight= ((float)eedc->bweight)/255.0f;
01785                 CustomData_to_em_block(&um->edata, &em->edata, a, &eed->data);
01786         }
01787         
01788         /* copy faces */
01789         for(a=0, efac= um->faces; a<um->totface; a++, efac++) {
01790                 if(efac->v4 != -1)
01791                         efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL);
01792                 else 
01793                         efa= addfacelist(em, evar[efac->v1], evar[efac->v2], evar[efac->v3], NULL, NULL ,NULL);
01794 
01795                 efa->mat_nr= efac->mat_nr;
01796                 efa->flag= efac->flag;
01797                 efa->f= efac->f;
01798                 efa->h= efac->h;
01799                 efa->fgonf= efac->fgonf;
01800                 
01801                 CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data);
01802         }
01803         
01804         end_editmesh_fastmalloc();
01805         if(evar) MEM_freeN(evar);
01806         
01807         em->totvert = um->totvert;
01808         em->totedge = um->totedge;
01809         em->totface = um->totface;
01810         /*restore stored editselections*/
01811         if(um->totsel){
01812                 EM_init_index_arrays(em, 1,1,1);
01813                 for(a=0, esec= um->selected; a<um->totsel; a++, esec++){
01814                         ese = MEM_callocN(sizeof(EditSelection), "Edit Selection");
01815                         ese->type = esec->type;
01816                         if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(esec->index); else
01817                         if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(esec->index); else
01818                         if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(esec->index);
01819                         BLI_addtail(&(em->selected),ese);
01820                 }
01821                 EM_free_index_arrays();
01822         }
01823 
01824         /* restore total selections */
01825         EM_nvertices_selected(em);
01826         EM_nedges_selected(em);
01827         EM_nfaces_selected(em);
01828 
01829 // XXX  retopo_free_paint();
01830 //      em->retopo_paint_data= retopo_paint_data_copy(um->retopo_paint_data);
01831 //      scene->toolsettings->retopo_mode= um->retopo_mode;
01832 //      if(scene->toolsettings->retopo_mode) {
01833 // XXX          if(G.vd->depths) G.vd->depths->damaged= 1;
01834 //              retopo_queue_updates(G.vd);
01835 //              retopo_paint_view_update(G.vd);
01836 //      }
01837         
01838 }
01839 
01840 static void *getEditMesh(bContext *C)
01841 {
01842         Object *obedit= CTX_data_edit_object(C);
01843         if(obedit && obedit->type==OB_MESH) {
01844                 Mesh *me= obedit->data;
01845                 return me->edit_mesh;
01846         }
01847         return NULL;
01848 }
01849 
01850 /* and this is all the undo system needs to know */
01851 void undo_push_mesh(bContext *C, const char *name)
01852 {
01853         undo_editmode_push(C, name, getEditMesh, free_undoMesh, undoMesh_to_editMesh, editMesh_to_undoMesh, NULL);
01854 }
01855 
01856 
01857 
01858 /* *************** END UNDO *************/
01859 
01860 static EditVert **g_em_vert_array = NULL;
01861 static EditEdge **g_em_edge_array = NULL;
01862 static EditFace **g_em_face_array = NULL;
01863 
01864 void EM_init_index_arrays(EditMesh *em, int forVert, int forEdge, int forFace)
01865 {
01866         EditVert *eve;
01867         EditEdge *eed;
01868         EditFace *efa;
01869         int i;
01870 
01871         if (forVert) {
01872                 em->totvert= BLI_countlist(&em->verts);
01873 
01874                 if(em->totvert) {
01875                         g_em_vert_array = MEM_mallocN(sizeof(*g_em_vert_array)*em->totvert, "em_v_arr");
01876 
01877                         for (i=0,eve=em->verts.first; eve; i++,eve=eve->next)
01878                                 g_em_vert_array[i] = eve;
01879                 }
01880         }
01881 
01882         if (forEdge) {
01883                 em->totedge= BLI_countlist(&em->edges);
01884 
01885                 if(em->totedge) {
01886                         g_em_edge_array = MEM_mallocN(sizeof(*g_em_edge_array)*em->totedge, "em_e_arr");
01887 
01888                         for (i=0,eed=em->edges.first; eed; i++,eed=eed->next)
01889                                 g_em_edge_array[i] = eed;
01890                 }
01891         }
01892 
01893         if (forFace) {
01894                 em->totface= BLI_countlist(&em->faces);
01895 
01896                 if(em->totface) {
01897                         g_em_face_array = MEM_mallocN(sizeof(*g_em_face_array)*em->totface, "em_f_arr");
01898 
01899                         for (i=0,efa=em->faces.first; efa; i++,efa=efa->next)
01900                                 g_em_face_array[i] = efa;
01901                 }
01902         }
01903 }
01904 
01905 void EM_free_index_arrays(void)
01906 {
01907         if (g_em_vert_array) MEM_freeN(g_em_vert_array);
01908         if (g_em_edge_array) MEM_freeN(g_em_edge_array);
01909         if (g_em_face_array) MEM_freeN(g_em_face_array);
01910         g_em_vert_array = NULL;
01911         g_em_edge_array = NULL;
01912         g_em_face_array = NULL;
01913 }
01914 
01915 EditVert *EM_get_vert_for_index(int index)
01916 {
01917         return g_em_vert_array?g_em_vert_array[index]:NULL;
01918 }
01919 
01920 EditEdge *EM_get_edge_for_index(int index)
01921 {
01922         return g_em_edge_array?g_em_edge_array[index]:NULL;
01923 }
01924 
01925 EditFace *EM_get_face_for_index(int index)
01926 {
01927         return g_em_face_array?g_em_face_array[index]:NULL;
01928 }
01929 
01930 /* can we edit UV's for this mesh?*/
01931 int EM_texFaceCheck(EditMesh *em)
01932 {
01933         /* some of these checks could be a touch overkill */
01934         if (    (em) &&
01935                         (em->faces.first) &&
01936                         (CustomData_has_layer(&em->fdata, CD_MTFACE)))
01937                 return 1;
01938         return 0;
01939 }
01940 
01941 /* can we edit colors for this mesh?*/
01942 int EM_vertColorCheck(EditMesh *em)
01943 {
01944         /* some of these checks could be a touch overkill */
01945         if (    (em) &&
01946                         (em->faces.first) &&
01947                         (CustomData_has_layer(&em->fdata, CD_MCOL)))
01948                 return 1;
01949         return 0;
01950 }
01951 
01952 
01953 void em_setup_viewcontext(bContext *C, ViewContext *vc)
01954 {
01955         view3d_set_viewcontext(C, vc);
01956         
01957         if(vc->obedit) {
01958                 Mesh *me= vc->obedit->data;
01959                 vc->em= me->edit_mesh;
01960         }
01961 }