Blender V2.61 - r43446
|
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 }