remove mesh and object arguments from bmesh operators, these are stored within the...
[blender-staging.git] / source / blender / editors / mesh / bmeshutils.c
1  /* $Id: bmeshutils.c
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2004 by Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): Joseph Eagar
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include <string.h>
31 #include <math.h>
32 #include <float.h>
33
34 #include "MEM_guardedalloc.h"
35 #include "PIL_time.h"
36
37 #include "BLO_sys_types.h" // for intptr_t support
38
39 #include "DNA_mesh_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_modifier_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_view3d_types.h"
47 #include "DNA_key_types.h"
48
49 #include "RNA_types.h"
50 #include "RNA_define.h"
51 #include "RNA_access.h"
52
53 #include "BLI_utildefines.h"
54 #include "BLI_blenlib.h"
55 #include "BLI_math.h"
56 #include "BLI_editVert.h"
57 #include "BLI_rand.h"
58 #include "BLI_ghash.h"
59 #include "BLI_linklist.h"
60 #include "BLI_heap.h"
61 #include "BLI_array.h"
62
63 #include "BKE_context.h"
64 #include "BKE_customdata.h"
65 #include "BKE_depsgraph.h"
66 #include "BKE_global.h"
67 #include "BKE_library.h"
68 #include "BKE_key.h"
69 #include "BKE_mesh.h"
70 #include "BKE_object.h"
71 #include "BKE_bmesh.h"
72 #include "BKE_report.h"
73 #include "BKE_tessmesh.h"
74
75 #include "bmesh.h"
76
77 #include "BIF_gl.h"
78 #include "BIF_glutil.h"
79
80 #include "WM_api.h"
81 #include "WM_types.h"
82
83 #include "ED_mesh.h"
84 #include "ED_view3d.h"
85 #include "ED_util.h"
86 #include "ED_screen.h"
87
88 #include "UI_interface.h"
89
90 #include "editbmesh_bvh.h"
91 #include "mesh_intern.h"
92
93 void EDBM_RecalcNormals(BMEditMesh *em)
94 {
95         BM_Compute_Normals(em->bm);
96 }
97
98 void EDBM_stats_update(BMEditMesh *em)
99 {
100         BMIter iter;
101         BMHeader *ele;
102         int types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH};
103         int *tots[3];
104         int i;
105
106         tots[0] = &em->bm->totvertsel;
107         tots[1] = &em->bm->totedgesel;
108         tots[2] = &em->bm->totfacesel;
109         
110         em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
111
112         for (i=0; i<3; i++) {
113                 ele = BMIter_New(&iter, em->bm, types[i], NULL);
114                 for ( ; ele; ele=BMIter_Step(&iter)) {
115                         if (BM_TestHFlag(ele, BM_SELECT)) {
116                                 *tots[i]++;
117                         }
118                 }
119         }
120 }
121
122 int EDBM_InitOpf(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
123 {
124         BMesh *bm = em->bm;
125         va_list list;
126
127         va_start(list, fmt);
128
129         if (!BMO_VInitOpf(bm, bmop, fmt, list)) {
130                 BKE_report(op->reports, RPT_ERROR,
131                            "Parse error in EDBM_CallOpf");
132                 va_end(list);
133                 return 0;
134         }
135         
136         if (!em->emcopy)
137                 em->emcopy = BMEdit_Copy(em);
138         em->emcopyusers++;
139
140         va_end(list);
141
142         return 1;
143 }
144
145
146 /*returns 0 on error, 1 on success.  executes and finishes a bmesh operator*/
147 int EDBM_FinishOp(BMEditMesh *em, BMOperator *bmop, wmOperator *op, int report) {
148         const char *errmsg;
149         
150         BMO_Finish_Op(em->bm, bmop);
151
152         if (BMO_GetError(em->bm, &errmsg, NULL)) {
153                 BMEditMesh *emcopy = em->emcopy;
154
155                 if (report) BKE_report(op->reports, RPT_ERROR, errmsg);
156
157                 BMEdit_Free(em);
158                 *em = *emcopy;
159
160                 MEM_freeN(emcopy);
161                 em->emcopyusers = 0;
162                 em->emcopy = NULL;
163                 return 0;
164         } else {
165                 em->emcopyusers--;
166                 if (em->emcopyusers < 0) {
167                         printf("warning: em->emcopyusers was less then zero.\n");
168                 }
169
170                 if (em->emcopyusers <= 0) {
171                         BMEdit_Free(em->emcopy);
172                         MEM_freeN(em->emcopy);
173                         em->emcopy = NULL;
174                 }
175         }
176
177         return 1;
178 }
179
180 int EDBM_CallOpf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
181 {
182         BMesh *bm = em->bm;
183         BMOperator bmop;
184         va_list list;
185
186         va_start(list, fmt);
187
188         if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
189                 BKE_report(op->reports, RPT_ERROR,
190                            "Parse error in EDBM_CallOpf");
191                 va_end(list);
192                 return 0;
193         }
194
195         if (!em->emcopy)
196                 em->emcopy = BMEdit_Copy(em);
197         em->emcopyusers++;
198
199         BMO_Exec_Op(bm, &bmop);
200
201         va_end(list);
202         return EDBM_FinishOp(em, &bmop, op, 1);
203 }
204
205 int EDBM_CallAndSelectOpf(BMEditMesh *em, wmOperator *op, const char *selectslot, const char *fmt, ...)
206 {
207         BMesh *bm = em->bm;
208         BMOperator bmop;
209         va_list list;
210
211         va_start(list, fmt);
212
213         if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
214                 BKE_report(op->reports, RPT_ERROR,
215                            "Parse error in EDBM_CallOpf");
216                 va_end(list);
217                 return 0;
218         }
219
220         if (!em->emcopy)
221                 em->emcopy = BMEdit_Copy(em);
222         em->emcopyusers++;
223
224         BMO_Exec_Op(bm, &bmop);
225         BMO_HeaderFlag_Buffer(em->bm, &bmop, selectslot, BM_SELECT, BM_ALL);
226
227         va_end(list);
228         return EDBM_FinishOp(em, &bmop, op, 1);
229 }
230
231 int EDBM_CallOpfSilent(BMEditMesh *em, const char *fmt, ...)
232 {
233         BMesh *bm = em->bm;
234         BMOperator bmop;
235         va_list list;
236
237         va_start(list, fmt);
238
239         if (!BMO_VInitOpf(bm, &bmop, fmt, list)) {
240                 va_end(list);
241                 return 0;
242         }
243
244         if (!em->emcopy)
245                 em->emcopy = BMEdit_Copy(em);
246         em->emcopyusers++;
247
248         BMO_Exec_Op(bm, &bmop);
249
250         va_end(list);
251         return EDBM_FinishOp(em, &bmop, NULL, 0);
252 }
253
254 void EDBM_selectmode_to_scene(Scene *scene, Object *obedit)
255 {
256         BMEditMesh *em = ((Mesh*)obedit->data)->edit_btmesh;
257
258         if (!em)
259                 return;
260
261         scene->toolsettings->selectmode = em->selectmode;
262 }
263
264 void EDBM_MakeEditBMesh(ToolSettings *ts, Scene *UNUSED(scene), Object *ob)
265 {
266         Mesh *me = ob->data;
267         BMesh *bm;
268
269         if (!me->mpoly && me->totface) {
270                 printf("yeek!! bmesh conversion issue! may lose lots of geometry!\n");
271                 
272                 /*BMESH_TODO need to write smarter code here*/
273                 bm = BKE_mesh_to_bmesh(ob);
274         } else {
275                 bm = BKE_mesh_to_bmesh(ob);
276         }
277
278         me->edit_btmesh = BMEdit_Create(bm);
279         me->edit_btmesh->selectmode = ts->selectmode;
280         me->edit_btmesh->me = me;
281         me->edit_btmesh->ob = ob;
282 }
283
284 void EDBM_LoadEditBMesh(Scene *scene, Object *ob)
285 {
286         Mesh *me = ob->data;
287         BMesh *bm = me->edit_btmesh->bm;
288
289         BMO_CallOpf(bm, "object_load_bmesh scene=%p", scene);
290 }
291
292 void EDBM_FreeEditBMesh(BMEditMesh *tm)
293 {
294         BMEdit_Free(tm);
295 }
296
297 void EDBM_init_index_arrays(BMEditMesh *tm, int forvert, int foredge, int forface)
298 {
299         EDBM_free_index_arrays(tm);
300
301         if (forvert) {
302                 BMIter iter;
303                 BMVert *ele;
304                 int i=0;
305                 
306                 tm->vert_index = MEM_mallocN(sizeof(void**)*tm->bm->totvert, "tm->vert_index");
307
308                 ele = BMIter_New(&iter, tm->bm, BM_VERTS_OF_MESH, NULL);
309                 for ( ; ele; ele=BMIter_Step(&iter)) {
310                         tm->vert_index[i++] = ele;
311                 }
312         }
313
314         if (foredge) {
315                 BMIter iter;
316                 BMEdge *ele;
317                 int i=0;
318                 
319                 tm->edge_index = MEM_mallocN(sizeof(void**)*tm->bm->totedge, "tm->edge_index");
320
321                 ele = BMIter_New(&iter, tm->bm, BM_EDGES_OF_MESH, NULL);
322                 for ( ; ele; ele=BMIter_Step(&iter)) {
323                         tm->edge_index[i++] = ele;
324                 }
325         }
326
327         if (forface) {
328                 BMIter iter;
329                 BMFace *ele;
330                 int i=0;
331                 
332                 tm->face_index = MEM_mallocN(sizeof(void**)*tm->bm->totface, "tm->face_index");
333
334                 ele = BMIter_New(&iter, tm->bm, BM_FACES_OF_MESH, NULL);
335                 for ( ; ele; ele=BMIter_Step(&iter)) {
336                         tm->face_index[i++] = ele;
337                 }
338         }
339 }
340
341 void EDBM_free_index_arrays(BMEditMesh *tm)
342 {
343         if (tm->vert_index) {
344                 MEM_freeN(tm->vert_index);
345                 tm->vert_index = NULL;
346         }
347
348         if (tm->edge_index) {
349                 MEM_freeN(tm->edge_index);
350                 tm->edge_index = NULL;
351         }
352
353         if (tm->face_index) {
354                 MEM_freeN(tm->face_index);
355                 tm->face_index = NULL;
356         }
357 }
358
359 BMVert *EDBM_get_vert_for_index(BMEditMesh *tm, int index)
360 {
361         return tm->vert_index && index < tm->bm->totvert ?tm->vert_index[index]:NULL;
362 }
363
364 BMEdge *EDBM_get_edge_for_index(BMEditMesh *tm, int index)
365 {
366         return tm->edge_index && index < tm->bm->totedge ?tm->edge_index[index]:NULL;
367 }
368
369 BMFace *EDBM_get_face_for_index(BMEditMesh *tm, int index)
370 {
371         return (tm->face_index && index<tm->bm->totface && index>=0) ? tm->face_index[index] : NULL;
372 }
373
374 /* this replaces the active flag used in uv/face mode */
375 void EDBM_set_actFace(BMEditMesh *em, BMFace *efa)
376 {
377         em->bm->act_face = efa;
378 }
379
380 BMFace *EDBM_get_actFace(BMEditMesh *em, int sloppy)
381 {
382         if (em->bm->act_face) {
383                 return em->bm->act_face;
384         } else if (sloppy) {
385                 BMFace *efa= NULL;
386                 BMEditSelection *ese;
387                 
388                 ese = em->bm->selected.last;
389                 for (; ese; ese=ese->prev){
390                         if(ese->type == BM_FACE) {
391                                 efa = (BMFace *)ese->data;
392                                 
393                                 if (BM_TestHFlag(efa, BM_HIDDEN)) efa= NULL;
394                                 else break;
395                         }
396                 }
397                 if (efa==NULL) {
398                         BMIter iter;
399                         efa = BMIter_New(&iter, em->bm, BM_FACES_OF_MESH, NULL);
400                         for ( ; efa; efa=BMIter_Step(&iter)) {
401                                 if (BM_TestHFlag(efa, BM_SELECT))
402                                         break;
403                         }
404                 }
405                 return efa; /* can still be null */
406         }
407         return NULL;
408
409 }
410
411 void EDBM_select_flush(BMEditMesh *em, int selectmode)
412 {
413         em->bm->selectmode = selectmode;
414         BM_SelectMode_Flush(em->bm);
415         em->bm->selectmode = em->selectmode;
416 }
417
418 /*BMESH_TODO*/
419 void EDBM_deselect_flush(BMEditMesh *UNUSED(em))
420 {
421 }
422
423
424 void EDBM_selectmode_flush(BMEditMesh *em)
425 {
426         em->bm->selectmode = em->selectmode;
427         BM_SelectMode_Flush(em->bm);
428 }
429
430 /*EDBM_select_[more/less] are api functions, I think the uv editor
431   uses them? though the select more/less ops themselves do not.*/
432 static void EDBM_select_more(BMEditMesh *em)
433 {
434         BMOperator bmop;
435         int usefaces = em->selectmode > SCE_SELECT_EDGE;
436
437         BMO_InitOpf(em->bm, &bmop, 
438                     "regionextend geom=%hvef constrict=%d usefaces=%d",
439                     BM_SELECT, 0, usefaces);
440         BMO_Exec_Op(em->bm, &bmop);
441         BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
442         BMO_Finish_Op(em->bm, &bmop);
443
444         EDBM_selectmode_flush(em);
445 }
446
447 static void EDBM_select_less(BMEditMesh *em)
448 {
449         BMOperator bmop;
450         int usefaces = em->selectmode > SCE_SELECT_EDGE;
451
452         BMO_InitOpf(em->bm, &bmop, 
453                     "regionextend geom=%hvef constrict=%d usefaces=%d",
454                     BM_SELECT, 0, usefaces);
455         BMO_Exec_Op(em->bm, &bmop);
456         BMO_HeaderFlag_Buffer(em->bm, &bmop, "geomout", BM_SELECT, BM_ALL);
457         BMO_Finish_Op(em->bm, &bmop);
458
459         EDBM_selectmode_flush(em);
460 }
461
462 int EDBM_get_actSelection(BMEditMesh *em, BMEditSelection *ese)
463 {
464         BMEditSelection *ese_last = em->bm->selected.last;
465         BMFace *efa = EDBM_get_actFace(em, 0);
466
467         ese->next = ese->prev = NULL;
468         
469         if (ese_last) {
470                 if (ese_last->type == BM_FACE) { /* if there is an active face, use it over the last selected face */
471                         if (efa) {
472                                 ese->data = (void *)efa;
473                         } else {
474                                 ese->data = ese_last->data;
475                         }
476                         ese->type = BM_FACE;
477                 } else {
478                         ese->data = ese_last->data;
479                         ese->type = ese_last->type;
480                 }
481         } else if (efa) { /* no */
482                 ese->data = (void *)efa;
483                 ese->type = BM_FACE;
484         } else {
485                 ese->data = NULL;
486                 return 0;
487         }
488         return 1;
489 }
490
491 void EDBM_clear_flag_all(BMEditMesh *em, int flag)
492 {
493         BMIter iter;
494         BMHeader *ele;
495         int i, type;
496
497         if (flag & BM_SELECT)
498                 BM_clear_selection_history(em->bm);
499
500         for (i=0; i<3; i++) {
501                 switch (i) {
502                         case 0:
503                                 type = BM_VERTS_OF_MESH;
504                                 break;
505                         case 1:
506                                 type = BM_EDGES_OF_MESH;
507                                 break;
508                         case 2:
509                                 type = BM_FACES_OF_MESH;
510                                 break;
511                 }
512                 
513                 BM_ITER(ele, &iter, em->bm, type, NULL) {
514                         if (flag & BM_SELECT) BM_Select(em->bm, ele, 0);
515                         BM_ClearHFlag(ele, flag);
516                 }
517         }
518 }
519
520 void EDBM_set_flag_all(BMEditMesh *em, int flag)
521 {
522         BMIter iter;
523         BMHeader *ele;
524         int i, type;
525
526         for (i=0; i<3; i++) {
527                 switch (i) {
528                         case 0:
529                                 type = BM_VERTS_OF_MESH;
530                                 break;
531                         case 1:
532                                 type = BM_EDGES_OF_MESH;
533                                 break;
534                         case 2:
535                                 type = BM_FACES_OF_MESH;
536                                 break;
537                 }
538                 
539                 ele = BMIter_New(&iter, em->bm, type, NULL);
540                 for ( ; ele; ele=BMIter_Step(&iter)) {
541                         if (flag & BM_SELECT) BM_Select(em->bm, ele, 1);
542                         BM_SetHFlag(ele, flag);
543                 }
544         }
545 }
546
547 /**************-------------- Undo ------------*****************/
548
549 /* for callbacks */
550
551 static void *getEditMesh(bContext *C)
552 {
553         Object *obedit= CTX_data_edit_object(C);
554         if(obedit && obedit->type==OB_MESH) {
555                 Mesh *me= obedit->data;
556                 return me->edit_btmesh;
557         }
558         return NULL;
559 }
560
561 typedef struct undomesh {
562         Mesh me;
563         int selectmode;
564         char obname[64];
565 } undomesh;
566
567 /*undo simply makes copies of a bmesh*/
568 static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
569 {
570         BMEditMesh *em = emv;
571         Mesh *obme = obdata;
572         
573         undomesh *me = MEM_callocN(sizeof(undomesh), "undo Mesh");
574         strcpy(me->obname, em->bm->ob->id.name+2);
575         
576         /*make sure shape keys work*/
577         me->me.key = obme->key ? copy_key_nolib(obme->key) : NULL;
578
579         /*we recalc the tesselation here, to avoid seeding calls to
580           BMEdit_RecalcTesselation throughout the code.*/
581         BMEdit_RecalcTesselation(em);
582
583         BMO_CallOpf(em->bm, "bmesh_to_mesh notesselation=%i", 1);
584         me->selectmode = em->selectmode;
585
586         return me;
587 }
588
589 static void undoMesh_to_editbtMesh(void *umv, void *emv, void *UNUSED(obdata))
590 {
591         BMEditMesh *em = emv, *em2;
592         Object *ob;
593         undomesh *me = umv;
594         BMesh *bm;
595         int allocsize[4] = {512, 512, 2048, 512};
596         
597         ob = (Object*)find_id("OB", me->obname);
598         ob->shapenr = em->bm->shapenr;
599
600         BMEdit_Free(em);
601
602         bm = BM_Make_Mesh(ob, allocsize);
603         BMO_CallOpf(bm, "mesh_to_bmesh set_shapekey=%i", 0);
604
605         em2 = BMEdit_Create(bm);
606         *em = *em2;
607         
608         em->selectmode = me->selectmode;
609
610         MEM_freeN(em2);
611 }
612
613
614 static void free_undo(void *umv)
615 {
616         if (((Mesh*)umv)->key)
617         {
618                 free_key(((Mesh*)umv)->key);
619                 MEM_freeN(((Mesh*)umv)->key);
620         }
621         
622         free_mesh(umv, 0);
623         MEM_freeN(umv);
624 }
625
626 /* and this is all the undo system needs to know */
627 void undo_push_mesh(bContext *C, const char *name)
628 {
629         undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
630 }
631
632 /*write comment here*/
633 UvVertMap *EDBM_make_uv_vert_map(BMEditMesh *em, int selected, int do_face_idx_array, float *limit)
634 {
635         BMVert *ev;
636         BMFace *efa;
637         BMLoop *l;
638         BMIter iter, liter;
639         /* vars from original func */
640         UvVertMap *vmap;
641         UvMapVert *buf;
642         /* MTexPoly *tf; */ /* UNUSED */
643         MLoopUV *luv;
644         unsigned int a;
645         int totverts, i, totuv;
646         
647         if (do_face_idx_array)
648                 EDBM_init_index_arrays(em, 0, 0, 1);
649         
650         /* we need the vert */
651         totverts=0;
652         BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
653                 BM_SetIndex(ev, totverts);
654                 totverts++;
655         }
656         
657         totuv = 0;
658
659         /* generate UvMapVert array */
660         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
661                 if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT)))
662                         totuv += efa->len;
663         }
664
665         if(totuv==0) {
666                 if (do_face_idx_array)
667                         EDBM_free_index_arrays(em);
668                 return NULL;
669         }
670         vmap= (UvVertMap*)MEM_callocN(sizeof(*vmap), "UvVertMap");
671         if (!vmap) {
672                 if (do_face_idx_array)
673                         EDBM_free_index_arrays(em);
674                 return NULL;
675         }
676
677         vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totverts, "UvMapVert*");
678         buf= vmap->buf= (UvMapVert*)MEM_callocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
679
680         if (!vmap->vert || !vmap->buf) {
681                 free_uv_vert_map(vmap);
682                 if (do_face_idx_array)
683                         EDBM_free_index_arrays(em);
684                 return NULL;
685         }
686         
687         a = 0;
688         BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
689                 if(!selected || ((!BM_TestHFlag(efa, BM_HIDDEN)) && BM_TestHFlag(efa, BM_SELECT))) {
690                         i = 0;
691                         BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
692                                 buf->tfindex= i;
693                                 buf->f= a;
694                                 buf->separate = 0;
695                                 
696                                 buf->next= vmap->vert[BM_GetIndex(l->v)];
697                                 vmap->vert[BM_GetIndex(l->v)]= buf;
698                                 
699                                 buf++;
700                                 i++;
701                         }
702                 }
703
704                 a++;
705         }
706         
707         /* sort individual uvs for each vert */
708         a = 0;
709         BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
710                 UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
711                 UvMapVert *iterv, *v, *lastv, *next;
712                 float *uv, *uv2, uvdiff[2];
713
714                 while(vlist) {
715                         v= vlist;
716                         vlist= vlist->next;
717                         v->next= newvlist;
718                         newvlist= v;
719
720                         efa = EDBM_get_face_for_index(em, v->f);
721                         /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
722                         
723                         l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
724                         luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
725                         uv = luv->uv; 
726                         
727                         lastv= NULL;
728                         iterv= vlist;
729
730                         while(iterv) {
731                                 next= iterv->next;
732                                 efa = EDBM_get_face_for_index(em, iterv->f);
733                                 /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
734                                 
735                                 l = BMIter_AtIndex(em->bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
736                                 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
737                                 uv2 = luv->uv; 
738                                 
739                                 sub_v2_v2v2(uvdiff, uv2, uv);
740
741                                 if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) {
742                                         if(lastv) lastv->next= next;
743                                         else vlist= next;
744                                         iterv->next= newvlist;
745                                         newvlist= iterv;
746                                 }
747                                 else
748                                         lastv=iterv;
749
750                                 iterv= next;
751                         }
752
753                         newvlist->separate = 1;
754                 }
755
756                 vmap->vert[a]= newvlist;
757                 a++;
758         }
759         
760         if (do_face_idx_array)
761                 EDBM_free_index_arrays(em);
762         
763         return vmap;
764 }
765
766
767 UvMapVert *EDBM_get_uv_map_vert(UvVertMap *vmap, unsigned int v)
768 {
769         return vmap->vert[v];
770 }
771
772 void EDBM_free_uv_vert_map(UvVertMap *vmap)
773 {
774         if (vmap) {
775                 if (vmap->vert) MEM_freeN(vmap->vert);
776                 if (vmap->buf) MEM_freeN(vmap->buf);
777                 MEM_freeN(vmap);
778         }
779 }
780
781
782 /* last_sel, use em->act_face otherwise get the last selected face in the editselections
783  * at the moment, last_sel is mainly useful for gaking sure the space image dosnt flicker */
784 MTexPoly *EDBM_get_active_mtexpoly(BMEditMesh *em, BMFace **act_efa, int sloppy)
785 {
786         BMFace *efa = NULL;
787         
788         if(!EDBM_texFaceCheck(em))
789                 return NULL;
790         
791         efa = EDBM_get_actFace(em, sloppy);
792         
793         if (efa) {
794                 if (act_efa) *act_efa = efa; 
795                 return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
796         }
797
798         if (act_efa) *act_efa= NULL;
799         return NULL;
800 }
801
802 /* can we edit UV's for this mesh?*/
803 int EDBM_texFaceCheck(BMEditMesh *em)
804 {
805         /* some of these checks could be a touch overkill */
806         return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) &&
807                    CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
808 }
809
810 int EDBM_vertColorCheck(BMEditMesh *em)
811 {
812         /* some of these checks could be a touch overkill */
813         return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
814 }
815
816
817 void EDBM_CacheMirrorVerts(BMEditMesh *em)
818 {
819         BMBVHTree *tree = BMBVH_NewBVH(em, 0, NULL, NULL);
820         BMIter iter;
821         BMVert *v;
822         float invmat[4][4];
823         int li, i;
824
825         if (!em->vert_index) {
826                 EDBM_init_index_arrays(em, 1, 0, 0);
827                 em->mirr_free_arrays = 1;
828         }
829
830         if (!CustomData_get_layer_named(&em->bm->vdata, CD_PROP_INT, (char*)"__mirror_index")) {
831                 BM_add_data_layer_named(em->bm, &em->bm->vdata, CD_PROP_INT, (char*)"__mirror_index");
832         }
833
834         li = CustomData_get_named_layer_index(&em->bm->vdata, CD_PROP_INT, "__mirror_index");
835         em->bm->vdata.layers[li].flag |= CD_FLAG_TEMPORARY;
836
837         /*multiply verts by object matrix, temporarily*/
838
839         i = 0;
840         BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
841                 BM_SetIndex(v, i);
842                 i++;
843
844                 if (em->ob) 
845                         mul_m4_v3(em->ob->obmat, v->co);
846         }
847
848         BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
849                 BMVert *mirr;
850                 int *idx = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, li);
851                 float co[3] = {-v->co[0], v->co[1], v->co[2]};
852
853                 //temporary for testing, check for selection
854                 if (!BM_TestHFlag(v, BM_SELECT))
855                         continue;
856                 
857                 mirr = BMBVH_FindClosestVertTopo(tree, co, BM_SEARCH_MAXDIST, v);
858                 if (mirr && mirr != v) {
859                         *idx = BM_GetIndex(mirr);
860                         idx = CustomData_bmesh_get_layer_n(&em->bm->vdata,mirr->head.data, li);
861                         *idx = BM_GetIndex(v);
862                 } else *idx = -1;
863         }
864
865         /*unmultiply by object matrix*/
866         if (em->ob) {
867                 i = 0;
868                 invert_m4_m4(invmat, em->ob->obmat);
869                 BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
870                         BM_SetIndex(v, i);
871                         i++;
872
873                         mul_m4_v3(invmat, v->co);
874                 }
875
876                 BMBVH_FreeBVH(tree);
877         }
878 }
879
880 BMVert *EDBM_GetMirrorVert(BMEditMesh *em, BMVert *v)
881 {
882         int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
883         
884         if (mirr && *mirr >=0 && *mirr < em->bm->totvert) {
885                 if (!em->vert_index) {
886                         printf("err: should only be called between "
887                                 "EDBM_CacheMirrorVerts and EDBM_EndMirrorCache");
888                         return NULL;
889                 }
890
891                 return em->vert_index[*mirr];
892         }
893
894         return NULL;
895 }
896
897 void EDBM_EndMirrorCache(BMEditMesh *em)
898 {
899         if (em->mirr_free_arrays) {
900                 MEM_freeN(em->vert_index);
901                 em->vert_index = NULL;
902         }
903 }