4982ce3571c3b492cff1b392c33c7f6440f32c09
[blender.git] / source / blender / editors / mesh / editmesh_utils.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2004 by Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joseph Eagar
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/mesh/editmesh_utils.c
29  *  \ingroup edmesh
30  */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_mesh_types.h"
35 #include "DNA_object_types.h"
36
37 #include "BLI_math.h"
38 #include "BLI_alloca.h"
39
40 #include "BKE_DerivedMesh.h"
41 #include "BKE_context.h"
42 #include "BKE_depsgraph.h"
43 #include "BKE_key.h"
44 #include "BKE_mesh.h"
45 #include "BKE_mesh_mapping.h"
46 #include "BKE_report.h"
47 #include "BKE_editmesh.h"
48 #include "BKE_editmesh_bvh.h"
49
50 #include "BKE_object.h"  /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "ED_mesh.h"
56 #include "ED_screen.h"
57 #include "ED_util.h"
58 #include "ED_view3d.h"
59
60 #include "mesh_intern.h"  /* own include */
61
62 /* mesh backup implementation. This would greatly benefit from some sort of binary diffing
63  * just as the undo stack would. So leaving this as an interface for further work */
64
65 BMBackup EDBM_redo_state_store(BMEditMesh *em)
66 {
67         BMBackup backup;
68         backup.bmcopy = BM_mesh_copy(em->bm);
69         return backup;
70 }
71
72 void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess)
73 {
74         BMesh *tmpbm;
75         if (!em || !backup.bmcopy)
76                 return;
77
78         BM_mesh_data_free(em->bm);
79         tmpbm = BM_mesh_copy(backup.bmcopy);
80         *em->bm = *tmpbm;
81         MEM_freeN(tmpbm);
82         tmpbm = NULL;
83
84         if (recalctess)
85                 BKE_editmesh_tessface_calc(em);
86 }
87
88 void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
89 {
90         if (em && backup->bmcopy) {
91                 BM_mesh_data_free(em->bm);
92                 *em->bm = *backup->bmcopy;
93         }
94         else if (backup->bmcopy) {
95                 BM_mesh_data_free(backup->bmcopy);
96         }
97
98         if (backup->bmcopy)
99                 MEM_freeN(backup->bmcopy);
100         backup->bmcopy = NULL;
101
102         if (recalctess && em)
103                 BKE_editmesh_tessface_calc(em);
104 }
105
106 /* hack to workaround multiple operators being called within the same event loop without an update
107  * see: [#31811] */
108 void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em)
109 {
110         if ((((ID *)em->ob->data)->flag & LIB_ID_RECALC) ||
111             (em->ob->recalc & OB_RECALC_DATA))
112         {
113                 em->ob->recalc |= OB_RECALC_DATA;  /* since we may not have done selection flushing */
114                 BKE_object_handle_update(scene, em->ob);
115         }
116 }
117
118 void EDBM_mesh_normals_update(BMEditMesh *em)
119 {
120         BM_mesh_normals_update(em->bm);
121 }
122
123 void EDBM_mesh_clear(BMEditMesh *em)
124 {
125         /* clear bmesh */
126         BM_mesh_clear(em->bm);
127         
128         /* free derived meshes */
129         if (em->derivedCage) {
130                 em->derivedCage->needsFree = 1;
131                 em->derivedCage->release(em->derivedCage);
132         }
133         if (em->derivedFinal && em->derivedFinal != em->derivedCage) {
134                 em->derivedFinal->needsFree = 1;
135                 em->derivedFinal->release(em->derivedFinal);
136         }
137         
138         em->derivedCage = em->derivedFinal = NULL;
139         
140         /* free tessellation data */
141         em->tottri = 0;
142         if (em->looptris) {
143                 MEM_freeN(em->looptris);
144                 em->looptris = NULL;
145         }
146 }
147
148 void EDBM_stats_update(BMEditMesh *em)
149 {
150         const char iter_types[3] = {BM_VERTS_OF_MESH,
151                                     BM_EDGES_OF_MESH,
152                                     BM_FACES_OF_MESH};
153
154         BMIter iter;
155         BMElem *ele;
156         int *tots[3];
157         int i;
158
159         tots[0] = &em->bm->totvertsel;
160         tots[1] = &em->bm->totedgesel;
161         tots[2] = &em->bm->totfacesel;
162         
163         em->bm->totvertsel = em->bm->totedgesel = em->bm->totfacesel = 0;
164
165         for (i = 0; i < 3; i++) {
166                 ele = BM_iter_new(&iter, em->bm, iter_types[i], NULL);
167                 for ( ; ele; ele = BM_iter_step(&iter)) {
168                         if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) {
169                                 (*tots[i])++;
170                         }
171                 }
172         }
173 }
174
175 DerivedMesh *EDBM_mesh_deform_dm_get(BMEditMesh *em)
176 {
177         return ((em->derivedFinal != NULL) &&
178                 (em->derivedFinal->type == DM_TYPE_EDITBMESH) &&
179                 (em->derivedFinal->deformedOnly != false)) ? em->derivedFinal : NULL;
180 }
181
182 bool EDBM_op_init(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const char *fmt, ...)
183 {
184         BMesh *bm = em->bm;
185         va_list list;
186
187         va_start(list, fmt);
188
189         if (!BMO_op_vinitf(bm, bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
190                 BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
191                 va_end(list);
192                 return false;
193         }
194         
195         if (!em->emcopy)
196                 em->emcopy = BKE_editmesh_copy(em);
197         em->emcopyusers++;
198
199         va_end(list);
200
201         return true;
202 }
203
204
205 /* returns 0 on error, 1 on success.  executes and finishes a bmesh operator */
206 bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool do_report)
207 {
208         const char *errmsg;
209         
210         BMO_op_finish(em->bm, bmop);
211
212         if (BMO_error_get(em->bm, &errmsg, NULL)) {
213                 BMEditMesh *emcopy = em->emcopy;
214
215                 if (do_report) {
216                         BKE_report(op->reports, RPT_ERROR, errmsg);
217                 }
218
219                 EDBM_mesh_free(em);
220                 *em = *emcopy;
221
222                 MEM_freeN(emcopy);
223                 em->emcopyusers = 0;
224                 em->emcopy = NULL;
225
226                 /* when copying, tessellation isn't to for faster copying,
227                  * but means we need to re-tessellate here */
228                 if (em->looptris == NULL) {
229                         BKE_editmesh_tessface_calc(em);
230                 }
231
232                 return false;
233         }
234         else {
235                 em->emcopyusers--;
236                 if (em->emcopyusers < 0) {
237                         printf("warning: em->emcopyusers was less then zero.\n");
238                 }
239
240                 if (em->emcopyusers <= 0) {
241                         BKE_editmesh_free(em->emcopy);
242                         MEM_freeN(em->emcopy);
243                         em->emcopy = NULL;
244                 }
245
246                 return true;
247         }
248 }
249
250 bool EDBM_op_callf(BMEditMesh *em, wmOperator *op, const char *fmt, ...)
251 {
252         BMesh *bm = em->bm;
253         BMOperator bmop;
254         va_list list;
255
256         va_start(list, fmt);
257
258         if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
259                 BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
260                 va_end(list);
261                 return false;
262         }
263
264         if (!em->emcopy)
265                 em->emcopy = BKE_editmesh_copy(em);
266         em->emcopyusers++;
267
268         BMO_op_exec(bm, &bmop);
269
270         va_end(list);
271         return EDBM_op_finish(em, &bmop, op, true);
272 }
273
274 bool EDBM_op_call_and_selectf(BMEditMesh *em, wmOperator *op,
275                               const char *select_slot_out, const bool select_extend,
276                               const char *fmt, ...)
277 {
278         BMOpSlot *slot_select_out;
279         BMesh *bm = em->bm;
280         BMOperator bmop;
281         va_list list;
282         char hflag;
283
284         va_start(list, fmt);
285
286         if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
287                 BKE_reportf(op->reports, RPT_ERROR, "Parse error in %s", __func__);
288                 va_end(list);
289                 return false;
290         }
291
292         if (!em->emcopy)
293                 em->emcopy = BKE_editmesh_copy(em);
294         em->emcopyusers++;
295
296         BMO_op_exec(bm, &bmop);
297
298         slot_select_out = BMO_slot_get(bmop.slots_out, select_slot_out);
299         hflag = slot_select_out->slot_subtype.elem & BM_ALL_NOLOOP;
300         BLI_assert(hflag != 0);
301
302         if (select_extend == false) {
303                 BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
304         }
305
306         BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, select_slot_out, hflag, BM_ELEM_SELECT, true);
307
308         va_end(list);
309         return EDBM_op_finish(em, &bmop, op, true);
310 }
311
312 bool EDBM_op_call_silentf(BMEditMesh *em, const char *fmt, ...)
313 {
314         BMesh *bm = em->bm;
315         BMOperator bmop;
316         va_list list;
317
318         va_start(list, fmt);
319
320         if (!BMO_op_vinitf(bm, &bmop, BMO_FLAG_DEFAULTS, fmt, list)) {
321                 va_end(list);
322                 return false;
323         }
324
325         if (!em->emcopy)
326                 em->emcopy = BKE_editmesh_copy(em);
327         em->emcopyusers++;
328
329         BMO_op_exec(bm, &bmop);
330
331         va_end(list);
332         return EDBM_op_finish(em, &bmop, NULL, false);
333 }
334
335 void EDBM_selectmode_to_scene(bContext *C)
336 {
337         Scene *scene = CTX_data_scene(C);
338         Object *obedit = CTX_data_edit_object(C);
339         BMEditMesh *em = BKE_editmesh_from_object(obedit);
340
341         if (!em)
342                 return;
343
344         scene->toolsettings->selectmode = em->selectmode;
345
346         /* Request redraw of header buttons (to show new select mode) */
347         WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, scene);
348 }
349
350 void EDBM_mesh_make(ToolSettings *ts, Object *ob)
351 {
352         Mesh *me = ob->data;
353         BMesh *bm;
354
355         if (UNLIKELY(!me->mpoly && me->totface)) {
356                 BKE_mesh_convert_mfaces_to_mpolys(me);
357         }
358
359         bm = BKE_mesh_to_bmesh(me, ob);
360
361         if (me->edit_btmesh) {
362                 /* this happens when switching shape keys */
363                 EDBM_mesh_free(me->edit_btmesh);
364                 MEM_freeN(me->edit_btmesh);
365         }
366
367         /* currently executing operators re-tessellates, so we can avoid doing here
368          * but at some point it may need to be added back. */
369 #if 0
370         me->edit_btmesh = BKE_editmesh_create(bm, true);
371 #else
372         me->edit_btmesh = BKE_editmesh_create(bm, false);
373 #endif
374
375         me->edit_btmesh->selectmode = me->edit_btmesh->bm->selectmode = ts->selectmode;
376         me->edit_btmesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
377         me->edit_btmesh->ob = ob;
378
379         /* we need to flush selection because the mode may have changed from when last in editmode */
380         EDBM_selectmode_flush(me->edit_btmesh);
381 }
382
383 void EDBM_mesh_load(Object *ob)
384 {
385         Mesh *me = ob->data;
386         BMesh *bm = me->edit_btmesh->bm;
387
388         BM_mesh_bm_to_me(bm, me, false);
389
390 #ifdef USE_TESSFACE_DEFAULT
391         BKE_mesh_tessface_calc(me);
392 #endif
393
394         /* free derived mesh. usually this would happen through depsgraph but there
395          * are exceptions like file save that will not cause this, and we want to
396          * avoid ending up with an invalid derived mesh then */
397         BKE_object_free_derived_caches(ob);
398 }
399
400 /**
401  * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free
402  */
403 void EDBM_mesh_free(BMEditMesh *em)
404 {
405         /* These tables aren't used yet, so it's not strictly necessary
406          * to 'end' them (with 'e' param) but if someone tries to start
407          * using them, having these in place will save a lot of pain */
408         mesh_octree_table(NULL, NULL, NULL, 'e');
409         mesh_mirrtopo_table(NULL, 'e');
410
411         BKE_editmesh_free(em);
412 }
413
414 void EDBM_selectmode_flush_ex(BMEditMesh *em, const short selectmode)
415 {
416         BM_mesh_select_mode_flush_ex(em->bm, selectmode);
417 }
418
419 void EDBM_selectmode_flush(BMEditMesh *em)
420 {
421         EDBM_selectmode_flush_ex(em, em->selectmode);
422 }
423
424 void EDBM_deselect_flush(BMEditMesh *em)
425 {
426         /* function below doesnt use. just do this to keep the values in sync */
427         em->bm->selectmode = em->selectmode;
428         BM_mesh_deselect_flush(em->bm);
429 }
430
431
432 void EDBM_select_flush(BMEditMesh *em)
433 {
434         /* function below doesnt use. just do this to keep the values in sync */
435         em->bm->selectmode = em->selectmode;
436         BM_mesh_select_flush(em->bm);
437 }
438
439 void EDBM_select_more(BMEditMesh *em)
440 {
441         BMOperator bmop;
442         int use_faces = em->selectmode == SCE_SELECT_FACE;
443
444         BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS,
445                      "region_extend geom=%hvef use_constrict=%b use_faces=%b",
446                      BM_ELEM_SELECT, false, use_faces);
447         BMO_op_exec(em->bm, &bmop);
448         /* don't flush selection in edge/vertex mode  */
449         BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
450         BMO_op_finish(em->bm, &bmop);
451
452         EDBM_selectmode_flush(em);
453 }
454
455 void EDBM_select_less(BMEditMesh *em)
456 {
457         BMOperator bmop;
458         int use_faces = em->selectmode == SCE_SELECT_FACE;
459
460         BMO_op_initf(em->bm, &bmop, BMO_FLAG_DEFAULTS,
461                      "region_extend geom=%hvef use_constrict=%b use_faces=%b",
462                      BM_ELEM_SELECT, true, use_faces);
463         BMO_op_exec(em->bm, &bmop);
464         /* don't flush selection in edge/vertex mode  */
465         BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, use_faces ? true : false);
466         BMO_op_finish(em->bm, &bmop);
467
468         EDBM_selectmode_flush(em);
469 }
470
471 void EDBM_flag_disable_all(BMEditMesh *em, const char hflag)
472 {
473         BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, false);
474 }
475
476 void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
477 {
478         BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true);
479 }
480
481 /**************-------------- Undo ------------*****************/
482
483 /* for callbacks */
484
485 static void *getEditMesh(bContext *C)
486 {
487         Object *obedit = CTX_data_edit_object(C);
488         if (obedit && obedit->type == OB_MESH) {
489                 Mesh *me = obedit->data;
490                 return me->edit_btmesh;
491         }
492         return NULL;
493 }
494
495 typedef struct UndoMesh {
496         Mesh me;
497         int selectmode;
498
499         /** \note
500          * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]),
501          * but editing shape keys, going into object mode, removing or changing their order,
502          * then go back into editmode and undo will give issues - where the old index will be out of sync
503          * with the new object index.
504          *
505          * There are a few ways this could be made to work but for now its a known limitation with mixing
506          * object and editmode operations - Campbell */
507         int shapenr;
508 } UndoMesh;
509
510 /* undo simply makes copies of a bmesh */
511 static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
512 {
513         BMEditMesh *em = emv;
514         Mesh *obme = obdata;
515         
516         UndoMesh *um = MEM_callocN(sizeof(UndoMesh), "undo Mesh");
517         
518         /* make sure shape keys work */
519         um->me.key = obme->key ? BKE_key_copy_nolib(obme->key) : NULL;
520
521         /* BM_mesh_validate(em->bm); */ /* for troubleshooting */
522
523         BM_mesh_bm_to_me(em->bm, &um->me, false);
524
525         um->selectmode = em->selectmode;
526         um->shapenr = em->bm->shapenr;
527
528         return um;
529 }
530
531 static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *UNUSED(obdata))
532 {
533         BMEditMesh *em = em_v, *em_tmp;
534         Object *ob = em->ob;
535         UndoMesh *um = umv;
536         BMesh *bm;
537
538         const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&um->me);
539
540         ob->shapenr = em->bm->shapenr = um->shapenr;
541
542         EDBM_mesh_free(em);
543
544         bm = BM_mesh_create(&allocsize);
545
546         BM_mesh_bm_from_me(bm, &um->me, true, false, ob->shapenr);
547
548         em_tmp = BKE_editmesh_create(bm, true);
549         *em = *em_tmp;
550         
551         em->selectmode = um->selectmode;
552         bm->selectmode = um->selectmode;
553         em->ob = ob;
554
555         MEM_freeN(em_tmp);
556 }
557
558 static void free_undo(void *me_v)
559 {
560         Mesh *me = me_v;
561         if (me->key) {
562                 BKE_key_free(me->key);
563                 MEM_freeN(me->key);
564         }
565
566         BKE_mesh_free(me, false);
567         MEM_freeN(me);
568 }
569
570 /* and this is all the undo system needs to know */
571 void undo_push_mesh(bContext *C, const char *name)
572 {
573         /* em->ob gets out of date and crashes on mesh undo,
574          * this is an easy way to ensure its OK
575          * though we could investigate the matter further. */
576         Object *obedit = CTX_data_edit_object(C);
577         BMEditMesh *em = BKE_editmesh_from_object(obedit);
578         em->ob = obedit;
579
580         undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
581 }
582
583 /**
584  * Return a new UVVertMap from the editmesh
585  */
586 UvVertMap *BM_uv_vert_map_create(BMesh *bm, bool use_select, const float limit[2])
587 {
588         BMVert *ev;
589         BMFace *efa;
590         BMLoop *l;
591         BMIter iter, liter;
592         /* vars from original func */
593         UvVertMap *vmap;
594         UvMapVert *buf;
595         /* MTexPoly *tf; */ /* UNUSED */
596         MLoopUV *luv;
597         unsigned int a;
598         int totverts, i, totuv;
599         const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
600
601         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
602         
603         totverts = bm->totvert;
604         totuv = 0;
605
606         /* generate UvMapVert array */
607         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
608                 if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
609                         totuv += efa->len;
610                 }
611         }
612
613         if (totuv == 0) {
614                 return NULL;
615         }
616         vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
617         if (!vmap) {
618                 return NULL;
619         }
620
621         vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totverts, "UvMapVert_pt");
622         buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * totuv, "UvMapVert");
623
624         if (!vmap->vert || !vmap->buf) {
625                 BKE_mesh_uv_vert_map_free(vmap);
626                 return NULL;
627         }
628         
629         a = 0;
630         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
631                 if ((use_select == false) || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
632                         i = 0;
633                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
634                                 buf->tfindex = i;
635                                 buf->f = a;
636                                 buf->separate = 0;
637                                 
638                                 buf->next = vmap->vert[BM_elem_index_get(l->v)];
639                                 vmap->vert[BM_elem_index_get(l->v)] = buf;
640                                 
641                                 buf++;
642                                 i++;
643                         }
644                 }
645
646                 a++;
647         }
648         
649         /* sort individual uvs for each vert */
650         a = 0;
651         BM_ITER_MESH (ev, &iter, bm, BM_VERTS_OF_MESH) {
652                 UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
653                 UvMapVert *iterv, *v, *lastv, *next;
654                 float *uv, *uv2, uvdiff[2];
655
656                 while (vlist) {
657                         v = vlist;
658                         vlist = vlist->next;
659                         v->next = newvlist;
660                         newvlist = v;
661
662                         efa = BM_face_at_index(bm, v->f);
663                         /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
664                         
665                         l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->tfindex);
666                         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
667                         uv = luv->uv;
668                         
669                         lastv = NULL;
670                         iterv = vlist;
671
672                         while (iterv) {
673                                 next = iterv->next;
674                                 efa = BM_face_at_index(bm, iterv->f);
675                                 /* tf = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
676                                 
677                                 l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->tfindex);
678                                 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
679                                 uv2 = luv->uv;
680                                 
681                                 sub_v2_v2v2(uvdiff, uv2, uv);
682
683                                 if (fabsf(uvdiff[0]) < limit[0] && fabsf(uvdiff[1]) < limit[1]) {
684                                         if (lastv) lastv->next = next;
685                                         else vlist = next;
686                                         iterv->next = newvlist;
687                                         newvlist = iterv;
688                                 }
689                                 else {
690                                         lastv = iterv;
691                                 }
692
693                                 iterv = next;
694                         }
695
696                         newvlist->separate = 1;
697                 }
698
699                 vmap->vert[a] = newvlist;
700                 a++;
701         }
702
703         return vmap;
704 }
705
706
707 UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, unsigned int v)
708 {
709         return vmap->vert[v];
710 }
711
712 /* from editmesh_lib.c in trunk */
713
714
715 /* A specialized vert map used by stitch operator */
716 UvElementMap *BM_uv_element_map_create(BMesh *bm, const bool selected, const bool do_islands)
717 {
718         BMVert *ev;
719         BMFace *efa;
720         BMLoop *l;
721         BMIter iter, liter;
722         /* vars from original func */
723         UvElementMap *element_map;
724         UvElement *buf;
725         UvElement *islandbuf;
726         /* island number for faces */
727         int *island_number;
728
729         MLoopUV *luv;
730         int totverts, i, totuv, j, nislands = 0, islandbufsize = 0;
731
732         unsigned int *map;
733         BMFace **stack;
734         int stacksize = 0;
735
736         const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
737
738         BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
739
740         totverts = bm->totvert;
741         totuv = 0;
742
743         island_number = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_number_face");
744         if (!island_number) {
745                 return NULL;
746         }
747
748         /* generate UvElement array */
749         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
750                 if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
751                         totuv += efa->len;
752                 }
753         }
754
755         if (totuv == 0) {
756                 MEM_freeN(island_number);
757                 return NULL;
758         }
759         element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
760         if (!element_map) {
761                 MEM_freeN(island_number);
762                 return NULL;
763         }
764         element_map->totalUVs = totuv;
765         element_map->vert = (UvElement **)MEM_callocN(sizeof(*element_map->vert) * totverts, "UvElementVerts");
766         buf = element_map->buf = (UvElement *)MEM_callocN(sizeof(*element_map->buf) * totuv, "UvElement");
767
768         if (!element_map->vert || !element_map->buf) {
769                 BM_uv_element_map_free(element_map);
770                 MEM_freeN(island_number);
771                 return NULL;
772         }
773
774         j = 0;
775         BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
776                 island_number[j++] = INVALID_ISLAND;
777                 if (!selected || BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
778                         BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
779                                 buf->l = l;
780                                 buf->separate = 0;
781                                 buf->island = INVALID_ISLAND;
782                                 buf->tfindex = i;
783
784                                 buf->next = element_map->vert[BM_elem_index_get(l->v)];
785                                 element_map->vert[BM_elem_index_get(l->v)] = buf;
786
787                                 buf++;
788                         }
789                 }
790         }
791
792         /* sort individual uvs for each vert */
793         i = 0;
794         BM_ITER_MESH (ev, &iter, bm, BM_VERTS_OF_MESH) {
795                 UvElement *newvlist = NULL, *vlist = element_map->vert[i];
796                 UvElement *iterv, *v, *lastv, *next;
797                 float *uv, *uv2, uvdiff[2];
798
799                 while (vlist) {
800                         v = vlist;
801                         vlist = vlist->next;
802                         v->next = newvlist;
803                         newvlist = v;
804
805                         l = v->l;
806                         luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
807                         uv = luv->uv;
808
809                         lastv = NULL;
810                         iterv = vlist;
811
812                         while (iterv) {
813                                 next = iterv->next;
814
815                                 l = iterv->l;
816                                 luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
817                                 uv2 = luv->uv;
818
819                                 sub_v2_v2v2(uvdiff, uv2, uv);
820
821                                 if (fabsf(uvdiff[0]) < STD_UV_CONNECT_LIMIT && fabsf(uvdiff[1]) < STD_UV_CONNECT_LIMIT) {
822                                         if (lastv) lastv->next = next;
823                                         else vlist = next;
824                                         iterv->next = newvlist;
825                                         newvlist = iterv;
826                                 }
827                                 else {
828                                         lastv = iterv;
829                                 }
830
831                                 iterv = next;
832                         }
833
834                         newvlist->separate = 1;
835                 }
836
837                 element_map->vert[i] = newvlist;
838                 i++;
839         }
840
841         if (do_islands) {
842                 /* map holds the map from current vmap->buf to the new, sorted map */
843                 map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
844                 stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
845                 islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
846
847                 /* at this point, every UvElement in vert points to a UvElement sharing the same vertex. Now we should sort uv's in islands. */
848                 for (i = 0; i < totuv; i++) {
849                         if (element_map->buf[i].island == INVALID_ISLAND) {
850                                 element_map->buf[i].island = nislands;
851                                 stack[0] = element_map->buf[i].l->f;
852                                 island_number[BM_elem_index_get(stack[0])] = nislands;
853                                 stacksize = 1;
854
855                                 while (stacksize > 0) {
856                                         efa = stack[--stacksize];
857
858                                         BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
859                                                 UvElement *element, *initelement = element_map->vert[BM_elem_index_get(l->v)];
860
861                                                 for (element = initelement; element; element = element->next) {
862                                                         if (element->separate)
863                                                                 initelement = element;
864
865                                                         if (element->l->f == efa) {
866                                                                 /* found the uv corresponding to our face and vertex. Now fill it to the buffer */
867                                                                 element->island = nislands;
868                                                                 map[element - element_map->buf] = islandbufsize;
869                                                                 islandbuf[islandbufsize].l = element->l;
870                                                                 islandbuf[islandbufsize].separate = element->separate;
871                                                                 islandbuf[islandbufsize].tfindex = element->tfindex;
872                                                                 islandbuf[islandbufsize].island =  nislands;
873                                                                 islandbufsize++;
874
875                                                                 for (element = initelement; element; element = element->next) {
876                                                                         if (element->separate && element != initelement)
877                                                                                 break;
878
879                                                                         if (island_number[BM_elem_index_get(element->l->f)] == INVALID_ISLAND) {
880                                                                                 stack[stacksize++] = element->l->f;
881                                                                                 island_number[BM_elem_index_get(element->l->f)] = nislands;
882                                                                         }
883                                                                 }
884                                                                 break;
885                                                         }
886                                                 }
887                                         }
888                                 }
889
890                                 nislands++;
891                         }
892                 }
893
894                 /* remap */
895                 for (i = 0; i < bm->totvert; i++) {
896                         /* important since we may do selection only. Some of these may be NULL */
897                         if (element_map->vert[i])
898                                 element_map->vert[i] = &islandbuf[map[element_map->vert[i] - element_map->buf]];
899                 }
900
901                 element_map->islandIndices = MEM_callocN(sizeof(*element_map->islandIndices) * nislands, "UvElementMap_island_indices");
902                 if (!element_map->islandIndices) {
903                         MEM_freeN(islandbuf);
904                         MEM_freeN(stack);
905                         MEM_freeN(map);
906                         BM_uv_element_map_free(element_map);
907                         MEM_freeN(island_number);
908                 }
909
910                 j = 0;
911                 for (i = 0; i < totuv; i++) {
912                         UvElement *element = element_map->buf[i].next;
913                         if (element == NULL)
914                                 islandbuf[map[i]].next = NULL;
915                         else
916                                 islandbuf[map[i]].next = &islandbuf[map[element - element_map->buf]];
917
918                         if (islandbuf[i].island != j) {
919                                 j++;
920                                 element_map->islandIndices[j] = i;
921                         }
922                 }
923
924                 MEM_freeN(element_map->buf);
925
926                 element_map->buf = islandbuf;
927                 element_map->totalIslands = nislands;
928                 MEM_freeN(stack);
929                 MEM_freeN(map);
930         }
931         MEM_freeN(island_number);
932
933         return element_map;
934 }
935
936 void BM_uv_vert_map_free(UvVertMap *vmap)
937 {
938         if (vmap) {
939                 if (vmap->vert) MEM_freeN(vmap->vert);
940                 if (vmap->buf) MEM_freeN(vmap->buf);
941                 MEM_freeN(vmap);
942         }
943 }
944
945 void BM_uv_element_map_free(UvElementMap *element_map)
946 {
947         if (element_map) {
948                 if (element_map->vert) MEM_freeN(element_map->vert);
949                 if (element_map->buf) MEM_freeN(element_map->buf);
950                 if (element_map->islandIndices) MEM_freeN(element_map->islandIndices);
951                 MEM_freeN(element_map);
952         }
953 }
954
955 UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
956 {
957         UvElement *element;
958
959         element = map->vert[BM_elem_index_get(l->v)];
960
961         for (; element; element = element->next)
962                 if (element->l->f == efa)
963                         return element;
964
965         return NULL;
966 }
967
968 /* last_sel, use em->act_face otherwise get the last selected face in the editselections
969  * at the moment, last_sel is mainly useful for making sure the space image dosnt flicker */
970 MTexPoly *EDBM_mtexpoly_active_get(BMEditMesh *em, BMFace **r_act_efa, const bool sloppy, const bool selected)
971 {
972         BMFace *efa = NULL;
973         
974         if (!EDBM_mtexpoly_check(em))
975                 return NULL;
976         
977         efa = BM_mesh_active_face_get(em->bm, sloppy, selected);
978
979         if (efa) {
980                 if (r_act_efa) *r_act_efa = efa;
981                 return CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
982         }
983
984         if (r_act_efa) *r_act_efa = NULL;
985         return NULL;
986 }
987
988 /* can we edit UV's for this mesh?*/
989 bool EDBM_mtexpoly_check(BMEditMesh *em)
990 {
991         /* some of these checks could be a touch overkill */
992         return em && em->bm->totface && CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY) &&
993                CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
994 }
995
996 bool EDBM_vert_color_check(BMEditMesh *em)
997 {
998         /* some of these checks could be a touch overkill */
999         return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPCOL);
1000 }
1001
1002 static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
1003 {
1004         intptr_t eve_i = index_lookup[index];
1005         return (eve_i == -1) ? NULL : (BMVert *)eve_i;
1006 }
1007
1008 /**
1009  * [note: I've decided to use ideasman's code for non-editmode stuff, but since
1010  *  it has a big "not for editmode!" disclaimer, I'm going to keep what I have here
1011  *  - joeedh]
1012  *
1013  * x-mirror editing api.  usage:
1014  *
1015  *  EDBM_verts_mirror_cache_begin(em);
1016  *  ...
1017  *  ...
1018  *  BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
1019  *     mirrorv = EDBM_verts_mirror_get(em, v);
1020  *  }
1021  *  ...
1022  *  ...
1023  *  EDBM_verts_mirror_cache_end(em);
1024  *
1025  * \param use_self  Allow a vertex to reference its self.
1026  * \param use_select  Only cache selected verts.
1027  *
1028  * \note why do we only allow x axis mirror editing?
1029  */
1030
1031 /* BM_SEARCH_MAXDIST is too big, copied from 2.6x MOC_THRESH, should become a
1032  * preference */
1033 #define BM_SEARCH_MAXDIST_MIRR 0.00002f
1034 #define BM_CD_LAYER_ID "__mirror_index"
1035 /**
1036  * \param em  Editmesh.
1037  * \param use_self  Allow a vertex to point to its self (middle verts).
1038  * \param use_select  Restrict to selected verts.
1039  * \param use_topology  Use topology mirror.
1040  * \param maxdist  Distance for close point test.
1041  * \param r_index  Optional array to write into, as an alternative to a customdata layer (length of total verts).
1042  */
1043 void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em, const int axis, const bool use_self, const bool use_select,
1044                                       /* extra args */
1045                                       const bool use_topology, float maxdist, int *r_index)
1046 {
1047         Mesh *me = (Mesh *)em->ob->data;
1048         BMesh *bm = em->bm;
1049         BMIter iter;
1050         BMVert *v;
1051         int cd_vmirr_offset;
1052         int i;
1053
1054         /* one or the other is used depending if topo is enabled */
1055         struct BMBVHTree *tree = NULL;
1056         MirrTopoStore_t mesh_topo_store = {NULL, -1, -1, -1};
1057
1058         BM_mesh_elem_table_ensure(bm, BM_VERT);
1059
1060         if (r_index == NULL) {
1061                 const char *layer_id = BM_CD_LAYER_ID;
1062                 em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id);
1063                 if (em->mirror_cdlayer == -1) {
1064                         BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, layer_id);
1065                         em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, layer_id);
1066                 }
1067
1068                 cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT,
1069                                                           em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT));
1070
1071                 bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY;
1072         }
1073
1074         BM_mesh_elem_index_ensure(bm, BM_VERT);
1075
1076         if (use_topology) {
1077                 ED_mesh_mirrtopo_init(me, -1, &mesh_topo_store, true);
1078         }
1079         else {
1080                 tree = BKE_bmbvh_new_from_editmesh(em, 0, NULL, false);
1081         }
1082
1083 #define VERT_INTPTR(_v, _i) r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset);
1084
1085         BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
1086                 BLI_assert(BM_elem_index_get(v) == i);
1087
1088                 /* temporary for testing, check for selection */
1089                 if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) {
1090                         /* do nothing */
1091                 }
1092                 else {
1093                         BMVert *v_mirr;
1094                         int *idx = VERT_INTPTR(v, i);
1095
1096                         if (use_topology) {
1097                                 v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
1098                         }
1099                         else {
1100                                 float co[3];
1101                                 copy_v3_v3(co, v->co);
1102                                 co[axis] *= -1.0f;
1103                                 v_mirr = BKE_bmbvh_find_vert_closest(tree, co, maxdist);
1104                         }
1105
1106                         if (v_mirr && (use_self || (v_mirr != v))) {
1107                                 const int i_mirr = BM_elem_index_get(v_mirr);
1108                                 *idx = i_mirr;
1109                                 idx = VERT_INTPTR(v_mirr, i_mirr);
1110                                 *idx = i;
1111                         }
1112                         else {
1113                                 *idx = -1;
1114                         }
1115                 }
1116
1117         }
1118
1119 #undef VERT_INTPTR
1120
1121         if (use_topology) {
1122                 ED_mesh_mirrtopo_free(&mesh_topo_store);
1123         }
1124         else {
1125                 BKE_bmbvh_free(tree);
1126         }
1127 }
1128
1129 void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const int axis,
1130                                    const bool use_self, const bool use_select,
1131                                    const bool use_topology)
1132 {
1133         EDBM_verts_mirror_cache_begin_ex(em, axis,
1134                                          use_self, use_select,
1135                                          /* extra args */
1136                                          use_topology, BM_SEARCH_MAXDIST_MIRR, NULL);
1137 }
1138
1139 BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v)
1140 {
1141         int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
1142
1143         BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
1144
1145         if (mirr && *mirr >= 0 && *mirr < em->bm->totvert) {
1146                 if (!em->bm->vtable) {
1147                         printf("err: should only be called between "
1148                                "EDBM_verts_mirror_cache_begin and EDBM_verts_mirror_cache_end");
1149                         return NULL;
1150                 }
1151
1152                 return em->bm->vtable[*mirr];
1153         }
1154
1155         return NULL;
1156 }
1157
1158 BMEdge *EDBM_verts_mirror_get_edge(BMEditMesh *em, BMEdge *e)
1159 {
1160         BMVert *v1_mirr = EDBM_verts_mirror_get(em, e->v1);
1161         if (v1_mirr) {
1162                 BMVert *v2_mirr = EDBM_verts_mirror_get(em, e->v2);
1163                 if (v2_mirr) {
1164                         return BM_edge_exists(v1_mirr, v2_mirr);
1165                 }
1166         }
1167
1168         return NULL;
1169 }
1170
1171 BMFace *EDBM_verts_mirror_get_face(BMEditMesh *em, BMFace *f)
1172 {
1173         BMFace *f_mirr = NULL;
1174         BMVert **v_mirr_arr = BLI_array_alloca(v_mirr_arr, f->len);
1175
1176         BMLoop *l_iter, *l_first;
1177         unsigned int i = 0;
1178
1179         l_iter = l_first = BM_FACE_FIRST_LOOP(f);
1180         do {
1181                 if ((v_mirr_arr[i++] = EDBM_verts_mirror_get(em, l_iter->v)) == NULL) {
1182                         return NULL;
1183                 }
1184         } while ((l_iter = l_iter->next) != l_first);
1185
1186         BM_face_exists(v_mirr_arr, f->len, &f_mirr);
1187         return f_mirr;
1188 }
1189
1190 void EDBM_verts_mirror_cache_clear(BMEditMesh *em, BMVert *v)
1191 {
1192         int *mirr = CustomData_bmesh_get_layer_n(&em->bm->vdata, v->head.data, em->mirror_cdlayer);
1193
1194         BLI_assert(em->mirror_cdlayer != -1); /* invalid use */
1195
1196         if (mirr) {
1197                 *mirr = -1;
1198         }
1199 }
1200
1201 void EDBM_verts_mirror_cache_end(BMEditMesh *em)
1202 {
1203         em->mirror_cdlayer = -1;
1204 }
1205
1206 void EDBM_verts_mirror_apply(BMEditMesh *em, const int sel_from, const int sel_to)
1207 {
1208         BMIter iter;
1209         BMVert *v;
1210
1211         BLI_assert((em->bm->vtable != NULL) && ((em->bm->elem_table_dirty & BM_VERT) == 0));
1212
1213         BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
1214                 if (BM_elem_flag_test(v, BM_ELEM_SELECT) == sel_from) {
1215                         BMVert *mirr = EDBM_verts_mirror_get(em, v);
1216                         if (mirr) {
1217                                 if (BM_elem_flag_test(mirr, BM_ELEM_SELECT) == sel_to) {
1218                                         copy_v3_v3(mirr->co, v->co);
1219                                         mirr->co[0] *= -1.0f;
1220                                 }
1221                         }
1222                 }
1223         }
1224 }
1225
1226
1227 /* swap is 0 or 1, if 1 it hides not selected */
1228 void EDBM_mesh_hide(BMEditMesh *em, bool swap)
1229 {
1230         BMIter iter;
1231         BMElem *ele;
1232         int itermode;
1233         char hflag_swap = swap ? BM_ELEM_SELECT : 0;
1234
1235         if (em == NULL) return;
1236
1237         if (em->selectmode & SCE_SELECT_VERTEX)
1238                 itermode = BM_VERTS_OF_MESH;
1239         else if (em->selectmode & SCE_SELECT_EDGE)
1240                 itermode = BM_EDGES_OF_MESH;
1241         else
1242                 itermode = BM_FACES_OF_MESH;
1243
1244         BM_ITER_MESH (ele, &iter, em->bm, itermode) {
1245                 if (BM_elem_flag_test(ele, BM_ELEM_SELECT) ^ hflag_swap)
1246                         BM_elem_hide_set(em->bm, ele, true);
1247         }
1248
1249         EDBM_selectmode_flush(em);
1250
1251         /* original hide flushing comment (OUTDATED):
1252          * hide happens on least dominant select mode, and flushes up, not down! (helps preventing errors in subsurf) */
1253         /* - vertex hidden, always means edge is hidden too
1254          * - edge hidden, always means face is hidden too
1255          * - face hidden, only set face hide
1256          * - then only flush back down what's absolute hidden
1257          */
1258 }
1259
1260
1261 void EDBM_mesh_reveal(BMEditMesh *em)
1262 {
1263         const char iter_types[3] = {BM_VERTS_OF_MESH,
1264                                     BM_EDGES_OF_MESH,
1265                                     BM_FACES_OF_MESH};
1266
1267         int sels[3] = {(em->selectmode & SCE_SELECT_VERTEX),
1268                        (em->selectmode & SCE_SELECT_EDGE),
1269                        (em->selectmode & SCE_SELECT_FACE), };
1270         int i;
1271
1272         /* Use tag flag to remember what was hidden before all is revealed.
1273          * BM_ELEM_HIDDEN --> BM_ELEM_TAG */
1274 #pragma omp parallel for schedule(dynamic) if (em->bm->totvert + em->bm->totedge + em->bm->totface >= BM_OMP_LIMIT)
1275         for (i = 0; i < 3; i++) {
1276                 BMIter iter;
1277                 BMElem *ele;
1278
1279                 BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
1280                         BM_elem_flag_set(ele, BM_ELEM_TAG, BM_elem_flag_test(ele, BM_ELEM_HIDDEN));
1281                 }
1282         }
1283
1284         /* Reveal everything */
1285         EDBM_flag_disable_all(em, BM_ELEM_HIDDEN);
1286
1287         /* Select relevant just-revealed elements */
1288         for (i = 0; i < 3; i++) {
1289                 BMIter iter;
1290                 BMElem *ele;
1291
1292                 if (!sels[i]) {
1293                         continue;
1294                 }
1295
1296                 BM_ITER_MESH (ele, &iter, em->bm, iter_types[i]) {
1297                         if (BM_elem_flag_test(ele, BM_ELEM_TAG)) {
1298                                 BM_elem_select_set(em->bm, ele, true);
1299                         }
1300                 }
1301         }
1302
1303         EDBM_selectmode_flush(em);
1304
1305         /* hidden faces can have invalid normals */
1306         EDBM_mesh_normals_update(em);
1307 }
1308
1309 /* so many tools call these that we better make it a generic function.
1310  */
1311 void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive)
1312 {
1313         Object *ob = em->ob;
1314         /* order of calling isn't important */
1315         DAG_id_tag_update(ob->data, OB_RECALC_DATA);
1316         WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
1317
1318         if (do_tessface) {
1319                 BKE_editmesh_tessface_calc(em);
1320         }
1321
1322         if (is_destructive) {
1323                 /* TODO. we may be able to remove this now! - Campbell */
1324                 // BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP);
1325         }
1326         else {
1327                 /* in debug mode double check we didn't need to recalculate */
1328                 BLI_assert(BM_mesh_elem_table_check(em->bm) == true);
1329         }
1330 }
1331
1332 /* poll call for mesh operators requiring a view3d context */
1333 int EDBM_view3d_poll(bContext *C)
1334 {
1335         if (ED_operator_editmesh(C) && ED_operator_view3d_active(C))
1336                 return 1;
1337
1338         return 0;
1339 }
1340
1341
1342
1343 /* -------------------------------------------------------------------- */
1344 /* BMBVH functions */
1345 // XXX
1346 #if 0 //BMESH_TODO: not implemented yet
1347 int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d)
1348 {
1349
1350 }
1351 #endif
1352
1353 static BMFace *edge_ray_cast(struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e)
1354 {
1355         BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL);
1356
1357         if (f && BM_edge_in_face(e, f))
1358                 return NULL;
1359
1360         return f;
1361 }
1362
1363 static void scale_point(float c1[3], const float p[3], const float s)
1364 {
1365         sub_v3_v3(c1, p);
1366         mul_v3_fl(c1, s);
1367         add_v3_v3(c1, p);
1368 }
1369
1370 bool BMBVH_EdgeVisible(struct BMBVHTree *tree, BMEdge *e, ARegion *ar, View3D *v3d, Object *obedit)
1371 {
1372         BMFace *f;
1373         float co1[3], co2[3], co3[3], dir1[3], dir2[3], dir3[3];
1374         float origin[3], invmat[4][4];
1375         float epsilon = 0.01f;
1376         float end[3];
1377         const float mval_f[2] = {ar->winx / 2.0f,
1378                                  ar->winy / 2.0f};
1379
1380         ED_view3d_win_to_segment(ar, v3d, mval_f, origin, end, false);
1381
1382         invert_m4_m4(invmat, obedit->obmat);
1383         mul_m4_v3(invmat, origin);
1384
1385         copy_v3_v3(co1, e->v1->co);
1386         mid_v3_v3v3(co2, e->v1->co, e->v2->co);
1387         copy_v3_v3(co3, e->v2->co);
1388
1389         scale_point(co1, co2, 0.99);
1390         scale_point(co3, co2, 0.99);
1391
1392         /* ok, idea is to generate rays going from the camera origin to the
1393          * three points on the edge (v1, mid, v2)*/
1394         sub_v3_v3v3(dir1, origin, co1);
1395         sub_v3_v3v3(dir2, origin, co2);
1396         sub_v3_v3v3(dir3, origin, co3);
1397
1398         normalize_v3(dir1);
1399         normalize_v3(dir2);
1400         normalize_v3(dir3);
1401
1402         mul_v3_fl(dir1, epsilon);
1403         mul_v3_fl(dir2, epsilon);
1404         mul_v3_fl(dir3, epsilon);
1405
1406         /* offset coordinates slightly along view vectors, to avoid
1407          * hitting the faces that own the edge.*/
1408         add_v3_v3v3(co1, co1, dir1);
1409         add_v3_v3v3(co2, co2, dir2);
1410         add_v3_v3v3(co3, co3, dir3);
1411
1412         normalize_v3(dir1);
1413         normalize_v3(dir2);
1414         normalize_v3(dir3);
1415
1416         /* do three samplings: left, middle, right */
1417         f = edge_ray_cast(tree, co1, dir1, NULL, e);
1418         if (f && !edge_ray_cast(tree, co2, dir2, NULL, e))
1419                 return true;
1420         else if (f && !edge_ray_cast(tree, co3, dir3, NULL, e))
1421                 return true;
1422         else if (!f)
1423                 return true;
1424
1425         return false;
1426 }