|
Blender
V2.59
|
00001 /* 00002 * $Id: editface.c 36644 2011-05-12 16:47:36Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * Contributor(s): Blender Foundation, Campbell Barton 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00034 #include <math.h> 00035 #include <string.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "BLI_blenlib.h" 00040 #include "BLI_math.h" 00041 #include "BLI_heap.h" 00042 #include "BLI_edgehash.h" 00043 #include "BLI_editVert.h" 00044 #include "BLI_utildefines.h" 00045 00046 #include "IMB_imbuf_types.h" 00047 #include "IMB_imbuf.h" 00048 00049 #include "DNA_meshdata_types.h" 00050 #include "DNA_object_types.h" 00051 #include "DNA_scene_types.h" 00052 00053 #include "BKE_DerivedMesh.h" 00054 #include "BKE_global.h" 00055 #include "BKE_mesh.h" 00056 #include "BKE_context.h" 00057 00058 #include "BIF_gl.h" 00059 00060 #include "ED_mesh.h" 00061 #include "ED_screen.h" 00062 #include "ED_view3d.h" 00063 00064 #include "WM_api.h" 00065 #include "WM_types.h" 00066 00067 /* own include */ 00068 #include "mesh_intern.h" 00069 00070 /* copy the face flags, most importantly selection from the mesh to the final derived mesh, 00071 * use in object mode when selecting faces (while painting) */ 00072 void paintface_flush_flags(Object *ob) 00073 { 00074 Mesh *me= get_mesh(ob); 00075 DerivedMesh *dm= ob->derivedFinal; 00076 MFace *faces, *mf, *mf_orig; 00077 int *index_array = NULL; 00078 int totface; 00079 int i; 00080 00081 if(me==NULL || dm==NULL) 00082 return; 00083 00084 index_array = dm->getFaceDataArray(dm, CD_ORIGINDEX); 00085 00086 if(!index_array) 00087 return; 00088 00089 faces = dm->getFaceArray(dm); 00090 totface = dm->getNumFaces(dm); 00091 00092 mf= faces; 00093 00094 for (i= 0; i<totface; i++, mf++) { /* loop over derived mesh faces */ 00095 mf_orig= me->mface + index_array[i]; 00096 mf->flag= mf_orig->flag; 00097 } 00098 } 00099 00100 /* returns 0 if not found, otherwise 1 */ 00101 static int facesel_face_pick(struct bContext *C, Mesh *me, const int mval[2], unsigned int *index, short rect) 00102 { 00103 ViewContext vc; 00104 view3d_set_viewcontext(C, &vc); 00105 00106 if (!me || me->totface==0) 00107 return 0; 00108 00109 // XXX if (v3d->flag & V3D_INVALID_BACKBUF) { 00110 // XXX drawview.c! check_backbuf(); 00111 // XXX persp(PERSP_VIEW); 00112 // XXX } 00113 00114 if (rect) { 00115 /* sample rect to increase changes of selecting, so that when clicking 00116 on an edge in the backbuf, we can still select a face */ 00117 00118 int dist; 00119 *index = view3d_sample_backbuf_rect(&vc, mval, 3, 1, me->totface+1, &dist,0,NULL, NULL); 00120 } 00121 else { 00122 /* sample only on the exact position */ 00123 *index = view3d_sample_backbuf(&vc, mval[0], mval[1]); 00124 } 00125 00126 if ((*index)<=0 || (*index)>(unsigned int)me->totface) 00127 return 0; 00128 00129 (*index)--; 00130 00131 return 1; 00132 } 00133 00134 /* last_sel, use em->act_face otherwise get the last selected face in the editselections 00135 * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */ 00136 MTFace *EM_get_active_mtface(EditMesh *em, EditFace **act_efa, MCol **mcol, int sloppy) 00137 { 00138 EditFace *efa = NULL; 00139 00140 if(!EM_texFaceCheck(em)) 00141 return NULL; 00142 00143 efa = EM_get_actFace(em, sloppy); 00144 00145 if (efa) { 00146 if (mcol) { 00147 if (CustomData_has_layer(&em->fdata, CD_MCOL)) 00148 *mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL); 00149 else 00150 *mcol = NULL; 00151 } 00152 if (act_efa) *act_efa = efa; 00153 return CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); 00154 } 00155 if (act_efa) *act_efa= NULL; 00156 if(mcol) *mcol = NULL; 00157 return NULL; 00158 } 00159 00160 void paintface_hide(Object *ob, const int unselected) 00161 { 00162 Mesh *me; 00163 MFace *mface; 00164 int a; 00165 00166 me= get_mesh(ob); 00167 if(me==NULL || me->totface==0) return; 00168 00169 mface= me->mface; 00170 a= me->totface; 00171 while(a--) { 00172 if((mface->flag & ME_HIDE) == 0) { 00173 if(unselected) { 00174 if( (mface->flag & ME_FACE_SEL)==0) mface->flag |= ME_HIDE; 00175 } 00176 else { 00177 if( (mface->flag & ME_FACE_SEL)) mface->flag |= ME_HIDE; 00178 } 00179 } 00180 if(mface->flag & ME_HIDE) mface->flag &= ~ME_FACE_SEL; 00181 00182 mface++; 00183 } 00184 00185 paintface_flush_flags(ob); 00186 } 00187 00188 00189 void paintface_reveal(Object *ob) 00190 { 00191 Mesh *me; 00192 MFace *mface; 00193 int a; 00194 00195 me= get_mesh(ob); 00196 if(me==NULL || me->totface==0) return; 00197 00198 mface= me->mface; 00199 a= me->totface; 00200 while(a--) { 00201 if(mface->flag & ME_HIDE) { 00202 mface->flag |= ME_FACE_SEL; 00203 mface->flag -= ME_HIDE; 00204 } 00205 mface++; 00206 } 00207 00208 paintface_flush_flags(ob); 00209 } 00210 00211 /* Set tface seams based on edge data, uses hash table to find seam edges. */ 00212 00213 static void hash_add_face(EdgeHash *ehash, MFace *mf) 00214 { 00215 BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); 00216 BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); 00217 if(mf->v4) { 00218 BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); 00219 BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); 00220 } 00221 else 00222 BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); 00223 } 00224 00225 00226 static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index) 00227 { 00228 MFace *mf; 00229 int a, doit=1, mark=0; 00230 char *linkflag; 00231 EdgeHash *ehash, *seamhash; 00232 MEdge *med; 00233 00234 ehash= BLI_edgehash_new(); 00235 seamhash = BLI_edgehash_new(); 00236 linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv"); 00237 00238 for(med=me->medge, a=0; a < me->totedge; a++, med++) 00239 if(med->flag & ME_SEAM) 00240 BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL); 00241 00242 if (mode==0 || mode==1) { 00243 /* only put face under cursor in array */ 00244 mf= ((MFace*)me->mface) + index; 00245 hash_add_face(ehash, mf); 00246 linkflag[index]= 1; 00247 } 00248 else { 00249 /* fill array by selection */ 00250 mf= me->mface; 00251 for(a=0; a<me->totface; a++, mf++) { 00252 if(mf->flag & ME_HIDE); 00253 else if(mf->flag & ME_FACE_SEL) { 00254 hash_add_face(ehash, mf); 00255 linkflag[a]= 1; 00256 } 00257 } 00258 } 00259 00260 while(doit) { 00261 doit= 0; 00262 00263 /* expand selection */ 00264 mf= me->mface; 00265 for(a=0; a<me->totface; a++, mf++) { 00266 if(mf->flag & ME_HIDE) 00267 continue; 00268 00269 if(!linkflag[a]) { 00270 mark= 0; 00271 00272 if(!BLI_edgehash_haskey(seamhash, mf->v1, mf->v2)) 00273 if(BLI_edgehash_haskey(ehash, mf->v1, mf->v2)) 00274 mark= 1; 00275 if(!BLI_edgehash_haskey(seamhash, mf->v2, mf->v3)) 00276 if(BLI_edgehash_haskey(ehash, mf->v2, mf->v3)) 00277 mark= 1; 00278 if(mf->v4) { 00279 if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v4)) 00280 if(BLI_edgehash_haskey(ehash, mf->v3, mf->v4)) 00281 mark= 1; 00282 if(!BLI_edgehash_haskey(seamhash, mf->v4, mf->v1)) 00283 if(BLI_edgehash_haskey(ehash, mf->v4, mf->v1)) 00284 mark= 1; 00285 } 00286 else if(!BLI_edgehash_haskey(seamhash, mf->v3, mf->v1)) 00287 if(BLI_edgehash_haskey(ehash, mf->v3, mf->v1)) 00288 mark = 1; 00289 00290 if(mark) { 00291 linkflag[a]= 1; 00292 hash_add_face(ehash, mf); 00293 doit= 1; 00294 } 00295 } 00296 } 00297 00298 } 00299 00300 BLI_edgehash_free(ehash, NULL); 00301 BLI_edgehash_free(seamhash, NULL); 00302 00303 if(mode==0 || mode==2) { 00304 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00305 if(linkflag[a]) 00306 mf->flag |= ME_FACE_SEL; 00307 else 00308 mf->flag &= ~ME_FACE_SEL; 00309 } 00310 else if(mode==1) { 00311 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00312 if(linkflag[a] && (mf->flag & ME_FACE_SEL)) 00313 break; 00314 00315 if (a<me->totface) { 00316 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00317 if(linkflag[a]) 00318 mf->flag &= ~ME_FACE_SEL; 00319 } 00320 else { 00321 for(a=0, mf=me->mface; a<me->totface; a++, mf++) 00322 if(linkflag[a]) 00323 mf->flag |= ME_FACE_SEL; 00324 } 00325 } 00326 00327 MEM_freeN(linkflag); 00328 } 00329 00330 void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]), int mode) 00331 { 00332 Mesh *me; 00333 unsigned int index=0; 00334 00335 me = get_mesh(ob); 00336 if(me==NULL || me->totface==0) return; 00337 00338 if (mode==0 || mode==1) { 00339 // XXX - Causes glitches, not sure why 00340 /* 00341 if (!facesel_face_pick(C, me, mval, &index, 1)) 00342 return; 00343 */ 00344 } 00345 00346 select_linked_tfaces_with_seams(mode, me, index); 00347 00348 paintface_flush_flags(ob); 00349 } 00350 00351 /* note: caller needs to run paintface_flush_flags(ob) after this */ 00352 void paintface_deselect_all_visible(Object *ob, int action, short flush_flags) 00353 { 00354 Mesh *me; 00355 MFace *mface; 00356 int a; 00357 00358 me= get_mesh(ob); 00359 if(me==NULL) return; 00360 00361 if(action == SEL_INVERT) { 00362 mface= me->mface; 00363 a= me->totface; 00364 while(a--) { 00365 if((mface->flag & ME_HIDE) == 0) { 00366 mface->flag ^= ME_FACE_SEL; 00367 } 00368 mface++; 00369 } 00370 } 00371 else { 00372 if (action == SEL_TOGGLE) { 00373 action = SEL_SELECT; 00374 00375 mface= me->mface; 00376 a= me->totface; 00377 while(a--) { 00378 if((mface->flag & ME_HIDE) == 0 && mface->flag & ME_FACE_SEL) { 00379 action = SEL_DESELECT; 00380 break; 00381 } 00382 mface++; 00383 } 00384 } 00385 00386 mface= me->mface; 00387 a= me->totface; 00388 while(a--) { 00389 if((mface->flag & ME_HIDE) == 0) { 00390 switch (action) { 00391 case SEL_SELECT: 00392 mface->flag |= ME_FACE_SEL; 00393 break; 00394 case SEL_DESELECT: 00395 mface->flag &= ~ME_FACE_SEL; 00396 break; 00397 case SEL_INVERT: 00398 mface->flag ^= ME_FACE_SEL; 00399 break; 00400 } 00401 } 00402 mface++; 00403 } 00404 } 00405 00406 if(flush_flags) { 00407 paintface_flush_flags(ob); 00408 } 00409 } 00410 00411 int paintface_minmax(Object *ob, float *min, float *max) 00412 { 00413 Mesh *me= get_mesh(ob); 00414 MFace *mf; 00415 MVert *mv; 00416 int a, ok=0; 00417 float vec[3]; 00418 00419 if(me==NULL) 00420 return ok; 00421 00422 mv= me->mvert; 00423 mf= me->mface; 00424 for (a=me->totface; a>0; a--, mf++) { 00425 if ((mf->flag & ME_HIDE || !(mf->flag & ME_FACE_SEL)) == 0) { 00426 int i= mf->v4 ? 3:2; 00427 do { 00428 mul_v3_m4v3(vec, ob->obmat, (mv + (*(&mf->v1 + i)))->co); 00429 DO_MINMAX(vec, min, max); 00430 } while (i--); 00431 ok= 1; 00432 } 00433 } 00434 return ok; 00435 } 00436 00437 /* ******************** edge loop shortest path ********************* */ 00438 00439 #define ME_SEAM_DONE 2 /* reuse this flag */ 00440 00441 static float edgetag_cut_cost(int e1, int e2, int vert) 00442 { 00443 EditVert *v = EM_get_vert_for_index(vert); 00444 EditEdge *eed1 = EM_get_edge_for_index(e1), *eed2 = EM_get_edge_for_index(e2); 00445 EditVert *v1 = EM_get_vert_for_index( (eed1->v1->tmp.l == vert)? eed1->v2->tmp.l: eed1->v1->tmp.l ); 00446 EditVert *v2 = EM_get_vert_for_index( (eed2->v1->tmp.l == vert)? eed2->v2->tmp.l: eed2->v1->tmp.l ); 00447 float cost, d1[3], d2[3]; 00448 00449 cost = len_v3v3(v1->co, v->co); 00450 cost += len_v3v3(v->co, v2->co); 00451 00452 sub_v3_v3v3(d1, v->co, v1->co); 00453 sub_v3_v3v3(d2, v2->co, v->co); 00454 00455 cost = cost + 0.5f*cost*(2.0f - fabsf(d1[0]*d2[0] + d1[1]*d2[1] + d1[2]*d2[2])); 00456 00457 return cost; 00458 } 00459 00460 static void edgetag_add_adjacent(Heap *heap, int mednum, int vertnum, int *nedges, int *edges, int *prevedge, float *cost) 00461 { 00462 int startadj, endadj = nedges[vertnum+1]; 00463 00464 for (startadj = nedges[vertnum]; startadj < endadj; startadj++) { 00465 int adjnum = edges[startadj]; 00466 EditEdge *eedadj = EM_get_edge_for_index(adjnum); 00467 float newcost; 00468 00469 if (eedadj->f2 & ME_SEAM_DONE) 00470 continue; 00471 00472 newcost = cost[mednum] + edgetag_cut_cost(mednum, adjnum, vertnum); 00473 00474 if (cost[adjnum] > newcost) { 00475 cost[adjnum] = newcost; 00476 prevedge[adjnum] = mednum; 00477 BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum)); 00478 } 00479 } 00480 } 00481 00482 void edgetag_context_set(Scene *scene, EditEdge *eed, int val) 00483 { 00484 00485 switch (scene->toolsettings->edge_mode) { 00486 case EDGE_MODE_SELECT: 00487 EM_select_edge(eed, val); 00488 break; 00489 case EDGE_MODE_TAG_SEAM: 00490 if (val) {eed->seam = 255;} 00491 else {eed->seam = 0;} 00492 break; 00493 case EDGE_MODE_TAG_SHARP: 00494 if (val) {eed->sharp = 1;} 00495 else {eed->sharp = 0;} 00496 break; 00497 case EDGE_MODE_TAG_CREASE: 00498 if (val) {eed->crease = 1.0f;} 00499 else {eed->crease = 0.0f;} 00500 break; 00501 case EDGE_MODE_TAG_BEVEL: 00502 if (val) {eed->bweight = 1.0f;} 00503 else {eed->bweight = 0.0f;} 00504 break; 00505 } 00506 } 00507 00508 int edgetag_context_check(Scene *scene, EditEdge *eed) 00509 { 00510 switch (scene->toolsettings->edge_mode) { 00511 case EDGE_MODE_SELECT: 00512 return (eed->f & SELECT) ? 1 : 0; 00513 case EDGE_MODE_TAG_SEAM: 00514 return eed->seam ? 1 : 0; 00515 case EDGE_MODE_TAG_SHARP: 00516 return eed->sharp ? 1 : 0; 00517 case EDGE_MODE_TAG_CREASE: 00518 return eed->crease ? 1 : 0; 00519 case EDGE_MODE_TAG_BEVEL: 00520 return eed->bweight ? 1 : 0; 00521 } 00522 return 0; 00523 } 00524 00525 00526 int edgetag_shortest_path(Scene *scene, EditMesh *em, EditEdge *source, EditEdge *target) 00527 { 00528 EditEdge *eed; 00529 EditVert *ev; 00530 00531 Heap *heap; 00532 float *cost; 00533 int a, totvert=0, totedge=0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; 00534 00535 00536 /* we need the vert */ 00537 for (ev= em->verts.first, totvert=0; ev; ev= ev->next) { 00538 ev->tmp.l = totvert; 00539 totvert++; 00540 } 00541 00542 for (eed= em->edges.first; eed; eed = eed->next) { 00543 eed->f2 = 0; 00544 if (eed->h) { 00545 eed->f2 |= ME_SEAM_DONE; 00546 } 00547 eed->tmp.l = totedge; 00548 totedge++; 00549 } 00550 00551 /* alloc */ 00552 nedges = MEM_callocN(sizeof(*nedges)*totvert+1, "SeamPathNEdges"); 00553 edges = MEM_mallocN(sizeof(*edges)*totedge*2, "SeamPathEdges"); 00554 prevedge = MEM_mallocN(sizeof(*prevedge)*totedge, "SeamPathPrevious"); 00555 cost = MEM_mallocN(sizeof(*cost)*totedge, "SeamPathCost"); 00556 00557 /* count edges, compute adjacent edges offsets and fill adjacent edges */ 00558 for (eed= em->edges.first; eed; eed = eed->next) { 00559 nedges[eed->v1->tmp.l+1]++; 00560 nedges[eed->v2->tmp.l+1]++; 00561 } 00562 00563 for (a=1; a<totvert; a++) { 00564 int newswap = nedges[a+1]; 00565 nedges[a+1] = nedgeswap + nedges[a]; 00566 nedgeswap = newswap; 00567 } 00568 nedges[0] = nedges[1] = 0; 00569 00570 for (a=0, eed= em->edges.first; eed; a++, eed = eed->next) { 00571 edges[nedges[eed->v1->tmp.l+1]++] = a; 00572 edges[nedges[eed->v2->tmp.l+1]++] = a; 00573 00574 cost[a] = 1e20f; 00575 prevedge[a] = -1; 00576 } 00577 00578 /* regular dijkstra shortest path, but over edges instead of vertices */ 00579 heap = BLI_heap_new(); 00580 BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(source->tmp.l)); 00581 cost[source->tmp.l] = 0.0f; 00582 00583 EM_init_index_arrays(em, 1, 1, 0); 00584 00585 00586 while (!BLI_heap_empty(heap)) { 00587 mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); 00588 eed = EM_get_edge_for_index( mednum ); 00589 00590 if (mednum == target->tmp.l) 00591 break; 00592 00593 if (eed->f2 & ME_SEAM_DONE) 00594 continue; 00595 00596 eed->f2 |= ME_SEAM_DONE; 00597 00598 edgetag_add_adjacent(heap, mednum, eed->v1->tmp.l, nedges, edges, prevedge, cost); 00599 edgetag_add_adjacent(heap, mednum, eed->v2->tmp.l, nedges, edges, prevedge, cost); 00600 } 00601 00602 00603 MEM_freeN(nedges); 00604 MEM_freeN(edges); 00605 MEM_freeN(cost); 00606 BLI_heap_free(heap, NULL); 00607 00608 for (eed= em->edges.first; eed; eed = eed->next) { 00609 eed->f2 &= ~ME_SEAM_DONE; 00610 } 00611 00612 if (mednum != target->tmp.l) { 00613 MEM_freeN(prevedge); 00614 EM_free_index_arrays(); 00615 return 0; 00616 } 00617 00618 /* follow path back to source and mark as seam */ 00619 if (mednum == target->tmp.l) { 00620 short allseams = 1; 00621 00622 mednum = target->tmp.l; 00623 do { 00624 eed = EM_get_edge_for_index( mednum ); 00625 if (!edgetag_context_check(scene, eed)) { 00626 allseams = 0; 00627 break; 00628 } 00629 mednum = prevedge[mednum]; 00630 } while (mednum != source->tmp.l); 00631 00632 mednum = target->tmp.l; 00633 do { 00634 eed = EM_get_edge_for_index( mednum ); 00635 if (allseams) 00636 edgetag_context_set(scene, eed, 0); 00637 else 00638 edgetag_context_set(scene, eed, 1); 00639 mednum = prevedge[mednum]; 00640 } while (mednum != -1); 00641 } 00642 00643 MEM_freeN(prevedge); 00644 EM_free_index_arrays(); 00645 return 1; 00646 } 00647 00648 /* *************************************** */ 00649 #if 0 00650 static void seam_edgehash_insert_face(EdgeHash *ehash, MFace *mf) 00651 { 00652 BLI_edgehash_insert(ehash, mf->v1, mf->v2, NULL); 00653 BLI_edgehash_insert(ehash, mf->v2, mf->v3, NULL); 00654 if (mf->v4) { 00655 BLI_edgehash_insert(ehash, mf->v3, mf->v4, NULL); 00656 BLI_edgehash_insert(ehash, mf->v4, mf->v1, NULL); 00657 } 00658 else 00659 BLI_edgehash_insert(ehash, mf->v3, mf->v1, NULL); 00660 } 00661 00662 void seam_mark_clear_tface(Scene *scene, short mode) 00663 { 00664 Mesh *me; 00665 MFace *mf; 00666 MEdge *med; 00667 int a; 00668 00669 me= get_mesh(OBACT); 00670 if(me==0 || me->totface==0) return; 00671 00672 if (mode == 0) 00673 mode = pupmenu("Seams%t|Mark Border Seam %x1|Clear Seam %x2"); 00674 00675 if (mode != 1 && mode != 2) 00676 return; 00677 00678 if (mode == 2) { 00679 EdgeHash *ehash = BLI_edgehash_new(); 00680 00681 for (a=0, mf=me->mface; a<me->totface; a++, mf++) 00682 if (!(mf->flag & ME_HIDE) && (mf->flag & ME_FACE_SEL)) 00683 seam_edgehash_insert_face(ehash, mf); 00684 00685 for (a=0, med=me->medge; a<me->totedge; a++, med++) 00686 if (BLI_edgehash_haskey(ehash, med->v1, med->v2)) 00687 med->flag &= ~ME_SEAM; 00688 00689 BLI_edgehash_free(ehash, NULL); 00690 } 00691 else { 00692 /* mark edges that are on both selected and deselected faces */ 00693 EdgeHash *ehash1 = BLI_edgehash_new(); 00694 EdgeHash *ehash2 = BLI_edgehash_new(); 00695 00696 for (a=0, mf=me->mface; a<me->totface; a++, mf++) { 00697 if ((mf->flag & ME_HIDE) || !(mf->flag & ME_FACE_SEL)) 00698 seam_edgehash_insert_face(ehash1, mf); 00699 else 00700 seam_edgehash_insert_face(ehash2, mf); 00701 } 00702 00703 for (a=0, med=me->medge; a<me->totedge; a++, med++) 00704 if (BLI_edgehash_haskey(ehash1, med->v1, med->v2) && 00705 BLI_edgehash_haskey(ehash2, med->v1, med->v2)) 00706 med->flag |= ME_SEAM; 00707 00708 BLI_edgehash_free(ehash1, NULL); 00709 BLI_edgehash_free(ehash2, NULL); 00710 } 00711 00712 // XXX if (G.rt == 8) 00713 // unwrap_lscm(1); 00714 00715 me->drawflag |= ME_DRAWSEAMS; 00716 } 00717 #endif 00718 00719 int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], int extend) 00720 { 00721 Mesh *me; 00722 MFace *mface, *msel; 00723 unsigned int a, index; 00724 00725 /* Get the face under the cursor */ 00726 me = get_mesh(ob); 00727 00728 if (!facesel_face_pick(C, me, mval, &index, 1)) 00729 return 0; 00730 00731 msel= (((MFace*)me->mface)+index); 00732 if (msel->flag & ME_HIDE) return 0; 00733 00734 /* clear flags */ 00735 mface = me->mface; 00736 a = me->totface; 00737 if (!extend) { 00738 while (a--) { 00739 mface->flag &= ~ME_FACE_SEL; 00740 mface++; 00741 } 00742 } 00743 00744 me->act_face = (int)index; 00745 00746 if (extend) { 00747 if (msel->flag & ME_FACE_SEL) 00748 msel->flag &= ~ME_FACE_SEL; 00749 else 00750 msel->flag |= ME_FACE_SEL; 00751 } 00752 else msel->flag |= ME_FACE_SEL; 00753 00754 /* image window redraw */ 00755 00756 paintface_flush_flags(ob); 00757 WM_event_add_notifier(C, NC_GEOM|ND_SELECT, ob->data); 00758 ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views 00759 return 1; 00760 } 00761 00762 int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend) 00763 { 00764 Mesh *me; 00765 MFace *mface; 00766 struct ImBuf *ibuf; 00767 unsigned int *rt; 00768 int a, index; 00769 char *selar; 00770 int sx= rect->xmax-rect->xmin+1; 00771 int sy= rect->ymax-rect->ymin+1; 00772 00773 me= get_mesh(vc->obact); 00774 00775 if(me==NULL || me->totface==0 || sx*sy <= 0) 00776 return OPERATOR_CANCELLED; 00777 00778 selar= MEM_callocN(me->totface+1, "selar"); 00779 00780 if (extend == 0 && select) 00781 paintface_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE); 00782 00783 view3d_validate_backbuf(vc); 00784 00785 ibuf = IMB_allocImBuf(sx,sy,32,IB_rect); 00786 rt = ibuf->rect; 00787 glReadPixels(rect->xmin+vc->ar->winrct.xmin, rect->ymin+vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); 00788 if(ENDIAN_ORDER==B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); 00789 00790 a= sx*sy; 00791 while(a--) { 00792 if(*rt) { 00793 index= WM_framebuffer_to_index(*rt); 00794 if(index<=me->totface) selar[index]= 1; 00795 } 00796 rt++; 00797 } 00798 00799 mface= me->mface; 00800 for(a=1; a<=me->totface; a++, mface++) { 00801 if(selar[a]) { 00802 if(mface->flag & ME_HIDE); 00803 else { 00804 if(select) mface->flag |= ME_FACE_SEL; 00805 else mface->flag &= ~ME_FACE_SEL; 00806 } 00807 } 00808 } 00809 00810 IMB_freeImBuf(ibuf); 00811 MEM_freeN(selar); 00812 00813 #ifdef __APPLE__ 00814 glReadBuffer(GL_BACK); 00815 #endif 00816 00817 paintface_flush_flags(vc->obact); 00818 00819 return OPERATOR_FINISHED; 00820 }