Blender V2.61 - r43446

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