merge with/from trunk at r35190
[blender.git] / source / blender / editors / uvedit / uvedit_unwrap_ops.c
index 7e686f818f70dac883c94ac08e25c9905f50f050..57264e2cd5c30716e342108883bbd87f095f7014 100644 (file)
 #include "BKE_depsgraph.h"
 #include "BKE_image.h"
 #include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
+
+#include "BLI_math.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_array.h"
+#include "BLI_uvproject.h"
 
 #include "PIL_time.h"
 
@@ -70,9 +78,9 @@
 
 static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
 {
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
-       EditFace *efa;
-       MTFace *tf;
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+       BMFace *efa;
+       BMIter iter;
        Image *ima;
        bScreen *sc;
        ScrArea *sa;
@@ -80,15 +88,15 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
        SpaceImage *sima;
 
        if(ED_uvedit_test(obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return 1;
        }
 
-       if(em && em->faces.first)
-               EM_add_data_layer(em, &em->fdata, CD_MTFACE, NULL);
-       
+       if(em && em->bm->totface && !CustomData_has_layer(&em->bm->pdata, CD_MTEXPOLY)) {
+               BM_add_data_layer(em->bm, &em->bm->pdata, CD_MTEXPOLY);
+               BM_add_data_layer(em->bm, &em->bm->ldata, CD_MLOOPUV);
+       }
+
        if(!ED_uvedit_test(obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return 0;
        }
 
@@ -118,34 +126,36 @@ static int ED_uvedit_ensure_uvs(bContext *C, Scene *scene, Object *obedit)
                ED_uvedit_assign_image(scene, obedit, ima, NULL);
        
        /* select new UV's */
-       for(efa=em->faces.first; efa; efa=efa->next) {
-               tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-               uvedit_face_select(scene, efa, tf);
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+               uvedit_face_select(scene, em, efa);
        }
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return 1;
 }
 
 /****************** Parametrizer Conversion ***************/
 
-static ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short implicit, short fill, short sel, short correct_aspect)
+static ParamHandle *construct_param_handle(Scene *scene, BMEditMesh *em, 
+                                   short implicit, short fill, short sel, 
+                                   short correct_aspect)
 {
        ParamHandle *handle;
-       EditFace *efa;
-       EditEdge *eed;
-       EditVert *ev;
-       MTFace *tf;
+       BMFace *efa;
+       BMLoop *l;
+       BMEdge *eed;
+       BMVert *ev;
+       BMIter iter, liter;
+       MTexPoly *tf;
        int a;
        
        handle = param_construct_begin();
 
        if(correct_aspect) {
-               efa = EM_get_actFace(em, 1);
+               efa = EDBM_get_actFace(em, 1);
 
                if(efa) {
+                       MTexPoly *tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
                        float aspx, aspy;
-                       tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
 
                        ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
                
@@ -155,71 +165,103 @@ static ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short imp
        }
        
        /* we need the vert indices */
-       for(ev= em->verts.first, a=0; ev; ev= ev->next, a++)
-               ev->tmp.l = a;
+       a = 0;
+       BM_ITER(ev, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+               BMINDEX_SET(ev, a);
+               a++;
+       }
        
-       for(efa= em->faces.first; efa; efa= efa->next) {
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+               EditVert *v, *lastv, *firstv;
+               EditFace *sefa;
                ParamKey key, vkeys[4];
                ParamBool pin[4], select[4];
+               BMLoop *ls[3];
+               MLoopUV *luvs[3];
                float *co[4];
                float *uv[4];
-               int nverts;
+               int lsel;
                
-               if((efa->h) || (sel && (efa->f & SELECT)==0)) 
+               if((BM_TestHFlag(efa, BM_HIDDEN)) || (sel && BM_TestHFlag(efa, BM_SELECT)==0)) 
                        continue;
 
-               tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-               
-               if(implicit &&
-                       !(      uvedit_uv_selected(scene, efa, tf, 0) ||
-                               uvedit_uv_selected(scene, efa, tf, 1) ||
-                               uvedit_uv_selected(scene, efa, tf, 2) ||
-                               (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) )
-               ) {
-                       continue;
+               tf= (MTexPoly *)CustomData_em_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+               lsel = 0;
+
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       if (uvedit_uv_selected(em, scene, l)) {
+                               lsel = 1;
+                               break;
+                       }
                }
 
+               if (implicit && !lsel)
+                       continue;
+
                key = (ParamKey)efa;
-               vkeys[0] = (ParamKey)efa->v1->tmp.l;
-               vkeys[1] = (ParamKey)efa->v2->tmp.l;
-               vkeys[2] = (ParamKey)efa->v3->tmp.l;
-
-               co[0] = efa->v1->co;
-               co[1] = efa->v2->co;
-               co[2] = efa->v3->co;
-
-               uv[0] = tf->uv[0];
-               uv[1] = tf->uv[1];
-               uv[2] = tf->uv[2];
-
-               pin[0] = ((tf->unwrap & TF_PIN1) != 0);
-               pin[1] = ((tf->unwrap & TF_PIN2) != 0);
-               pin[2] = ((tf->unwrap & TF_PIN3) != 0);
-
-               select[0] = ((uvedit_uv_selected(scene, efa, tf, 0)) != 0);
-               select[1] = ((uvedit_uv_selected(scene, efa, tf, 1)) != 0);
-               select[2] = ((uvedit_uv_selected(scene, efa, tf, 2)) != 0);
-
-               if(efa->v4) {
-                       vkeys[3] = (ParamKey)efa->v4->tmp.l;
-                       co[3] = efa->v4->co;
-                       uv[3] = tf->uv[3];
-                       pin[3] = ((tf->unwrap & TF_PIN4) != 0);
-                       select[3] = (uvedit_uv_selected(scene, efa, tf, 3) != 0);
-                       nverts = 4;
+
+               /*scanfill time!*/
+               firstv = lastv = NULL;
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       v = BLI_addfillvert(l->v->co);
+                       
+                       v->tmp.p = l;
+
+                       if (lastv) {
+                               BLI_addfilledge(lastv, v);
+                       }
+
+                       lastv = v;
+                       if (!firstv) 
+                               firstv = v;
                }
-               else
-                       nverts = 3;
 
-               param_face_add(handle, key, nverts, vkeys, co, uv, pin, select);
+               BLI_addfilledge(firstv, v);
+               
+               /*mode 2 enables shortest-diagonal for quads*/
+               BLI_edgefill(0);
+               for (sefa = fillfacebase.first; sefa; sefa=sefa->next) {
+                       ls[0] = sefa->v1->tmp.p;
+                       ls[1] = sefa->v2->tmp.p;
+                       ls[2] = sefa->v3->tmp.p;
+                       
+                       luvs[0] = CustomData_bmesh_get(&em->bm->ldata, ls[0]->head.data, CD_MLOOPUV);
+                       luvs[1] = CustomData_bmesh_get(&em->bm->ldata, ls[1]->head.data, CD_MLOOPUV);
+                       luvs[2] = CustomData_bmesh_get(&em->bm->ldata, ls[2]->head.data, CD_MLOOPUV);
+
+                       vkeys[0] = (ParamKey)BMINDEX_GET(ls[0]->v);
+                       vkeys[1] = (ParamKey)BMINDEX_GET(ls[1]->v);
+                       vkeys[2] = (ParamKey)BMINDEX_GET(ls[2]->v);
+
+                       co[0] = ls[0]->v->co;
+                       co[1] = ls[1]->v->co;
+                       co[2] = ls[2]->v->co;
+
+                       uv[0] = luvs[0]->uv;
+                       uv[1] = luvs[1]->uv;
+                       uv[2] = luvs[2]->uv;
+
+                       pin[0] = (luvs[0]->flag & MLOOPUV_PINNED) != 0;
+                       pin[1] = (luvs[1]->flag & MLOOPUV_PINNED) != 0;
+                       pin[2] = (luvs[2]->flag & MLOOPUV_PINNED) != 0;
+
+                       select[0] = uvedit_uv_selected(em, scene, ls[0]) != 0;
+                       select[1] = uvedit_uv_selected(em, scene, ls[1]) != 0;
+                       select[2] = uvedit_uv_selected(em, scene, ls[2]) != 0;
+
+                       if (!p_face_exists(handle,vkeys,0,1,2))
+                                       param_face_add(handle, key, 3, vkeys, co, uv, pin, select);
+               }
+
+               BLI_end_edgefill();
        }
 
        if(!implicit) {
-               for(eed= em->edges.first; eed; eed= eed->next) {
-                       if(eed->seam) {
+               BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
+                       if(BM_TestHFlag(eed, BM_SEAM)) {
                                ParamKey vkeys[2];
-                               vkeys[0] = (ParamKey)eed->v1->tmp.l;
-                               vkeys[1] = (ParamKey)eed->v2->tmp.l;
+                               vkeys[0] = (ParamKey)BMINDEX_GET(eed->v1);
+                               vkeys[1] = (ParamKey)BMINDEX_GET(eed->v2);
                                param_edge_set_seam(handle, vkeys);
                        }
                }
@@ -235,7 +277,7 @@ static ParamHandle *construct_param_handle(Scene *scene, EditMesh *em, short imp
 typedef struct MinStretch {
        Scene *scene;
        Object *obedit;
-       EditMesh *em;
+       BMEditMesh *em;
        ParamHandle *handle;
        float blend;
        double lasttime;
@@ -247,7 +289,7 @@ static void minimize_stretch_init(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        MinStretch *ms;
        int fill_holes= RNA_boolean_get(op->ptr, "fill_holes");
 
@@ -430,7 +472,7 @@ static int pack_islands_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        ParamHandle *handle;
 
        handle = construct_param_handle(scene, em, 1, 0, 1, 1);
@@ -441,7 +483,6 @@ static int pack_islands_exec(bContext *C, wmOperator *UNUSED(op))
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }
 
@@ -463,7 +504,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        ParamHandle *handle;
 
        handle= construct_param_handle(scene, em, 1, 0, 1, 1);
@@ -474,7 +515,6 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }
 
@@ -496,19 +536,17 @@ static ParamHandle *liveHandle = NULL;
 
 void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
 {
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        short abf = scene->toolsettings->unwrapper == 0;
        short fillholes = scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
 
        if(!ED_uvedit_test(obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return;
        }
 
-       liveHandle = construct_param_handle(scene, em, 0, fillholes, 1, 1);
+       liveHandle = construct_param_handle(scene, em, 0, fillholes, 0, 1);
 
        param_lscm_begin(liveHandle, PARAM_TRUE, abf);
-       BKE_mesh_end_editmesh(obedit->data, em);
 }
 
 void ED_uvedit_live_unwrap_re_solve(void)
@@ -539,9 +577,12 @@ void ED_uvedit_live_unwrap_end(short cancel)
 #define POLAR_ZX       0
 #define POLAR_ZY       1
 
-static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Object *ob, EditMesh *em)
+static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, 
+                                   Object *ob, BMEditMesh *em)
 {
-       EditFace *efa;
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
        float min[3], max[3], *cursx;
        int around= (v3d)? v3d->around: V3D_CENTER;
 
@@ -551,13 +592,12 @@ static void uv_map_transform_center(Scene *scene, View3D *v3d, float *result, Ob
                case V3D_CENTER: /* bounding box center */
                        min[0]= min[1]= min[2]= 1e20f;
                        max[0]= max[1]= max[2]= -1e20f; 
-
-                       for(efa= em->faces.first; efa; efa= efa->next) {
-                               if(efa->f & SELECT) {
-                                       DO_MINMAX(efa->v1->co, min, max);
-                                       DO_MINMAX(efa->v2->co, min, max);
-                                       DO_MINMAX(efa->v3->co, min, max);
-                                       if(efa->v4) DO_MINMAX(efa->v4->co, min, max);
+                       
+                       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL)  {
+                               if(BM_TestHFlag(efa, BM_SELECT)) {
+                                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                                               DO_MINMAX(l->v->co, min, max);
+                                       }
                                }
                        }
                        mid_v3_v3v3(result, min, max);
@@ -631,7 +671,7 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float
        /* context checks are messy here, making it work in both 3d view and uv editor */
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        View3D *v3d= CTX_wm_view3d(C);
        RegionView3D *rv3d= CTX_wm_region_view3d(C);
        /* common operator properties */
@@ -658,7 +698,6 @@ static void uv_map_transform(bContext *C, wmOperator *op, float center[3], float
        else 
                uv_map_rotation_matrix(rotmat, rv3d, obedit, upangledeg, sideangledeg, radius);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
 }
 
 static void uv_transform_properties(wmOperatorType *ot, int radius)
@@ -681,14 +720,17 @@ static void uv_transform_properties(wmOperatorType *ot, int radius)
                RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "Radius of the sphere or cylinder.", 0.0001f, 100.0f);
 }
 
-static void correct_uv_aspect(EditMesh *em)
+static void correct_uv_aspect(BMEditMesh *em)
 {
-       EditFace *efa= EM_get_actFace(em, 1);
-       MTFace *tf;
+       BMFace *efa= EDBM_get_actFace(em, 1);
+       BMLoop *l;
+       BMIter iter, liter;
+       MTexPoly *tf;
+       MLoopUV *luv;
        float scale, aspx= 1.0f, aspy=1.0f;
        
        if(efa) {
-               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+               tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
                ED_image_uv_aspect(tf->tpage, &aspx, &aspy);
        }
        
@@ -698,30 +740,28 @@ static void correct_uv_aspect(EditMesh *em)
        if(aspx > aspy) {
                scale= aspy/aspx;
 
-               for(efa= em->faces.first; efa; efa= efa->next) {
-                       if(efa->f & SELECT) {
-                               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
-                               tf->uv[0][0]= ((tf->uv[0][0]-0.5)*scale)+0.5;
-                               tf->uv[1][0]= ((tf->uv[1][0]-0.5)*scale)+0.5;
-                               tf->uv[2][0]= ((tf->uv[2][0]-0.5)*scale)+0.5;
-                               if(efa->v4)
-                                       tf->uv[3][0]= ((tf->uv[3][0]-0.5)*scale)+0.5;
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
+                       
+                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                               luv->uv[0] = ((luv->uv[0]-0.5)*scale)+0.5;
                        }
                }
        }
        else {
                scale= aspx/aspy;
 
-               for(efa= em->faces.first; efa; efa= efa->next) {
-                       if(efa->f & SELECT) {
-                               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
-                               tf->uv[0][1]= ((tf->uv[0][1]-0.5)*scale)+0.5;
-                               tf->uv[1][1]= ((tf->uv[1][1]-0.5)*scale)+0.5;
-                               tf->uv[2][1]= ((tf->uv[2][1]-0.5)*scale)+0.5;
-                               if(efa->v4)
-                                       tf->uv[3][1]= ((tf->uv[3][1]-0.5)*scale)+0.5;
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
+                       
+                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                               luv->uv[1] = ((luv->uv[1]-0.5)*scale)+0.5;
                        }
                }
        }
@@ -736,10 +776,12 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot)
        RNA_def_boolean(ot->srna, "scale_to_bounds", 0, "Scale to Bounds", "Scale UV coordinates to bounds after unwrapping.");
 }
 
-static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
+static void uv_map_clip_correct(BMEditMesh *em, wmOperator *op)
 {
-       EditFace *efa;
-       MTFace *tf;
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
+       MLoopUV *luv;
        float dx, dy, min[2], max[2];
        int b, nverts;
        int correct_aspect= RNA_boolean_get(op->ptr, "correct_aspect");
@@ -753,16 +795,13 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
        if(scale_to_bounds) {
                INIT_MINMAX2(min, max);
                
-               for(efa= em->faces.first; efa; efa= efa->next) {
-                       if(efa->f & SELECT) {
-                               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
 
-                               DO_MINMAX2(tf->uv[0], min, max);
-                               DO_MINMAX2(tf->uv[1], min, max);
-                               DO_MINMAX2(tf->uv[2], min, max);
-
-                               if(efa->v4)
-                                       DO_MINMAX2(tf->uv[3], min, max);
+                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                               DO_MINMAX2(luv->uv, min, max);
                        }
                }
                
@@ -775,31 +814,28 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
                if(dy > 0.0f)
                        dy= 1.0f/dy;
 
-               for(efa= em->faces.first; efa; efa= efa->next) {
-                       if(efa->f & SELECT) {
-                               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
-                               nverts= (efa->v4)? 4: 3;
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
 
-                               for(b=0; b<nverts; b++) {
-                                       tf->uv[b][0]= (tf->uv[b][0]-min[0])*dx;
-                                       tf->uv[b][1]= (tf->uv[b][1]-min[1])*dy;
-                               }
+                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                               
+                               luv->uv[0] = (luv->uv[0]-min[0])*dx;
+                               luv->uv[1] = (luv->uv[1]-min[1])*dy;
                        }
                }
        }
        else if(clip_to_bounds) {
                /* clipping and wrapping */
-               for(efa= em->faces.first; efa; efa= efa->next) {
-                       if(efa->f & SELECT) {
-                               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-                       
-                               nverts= (efa->v4)? 4: 3;
-
-                               for(b=0; b<nverts; b++) {
-                                       CLAMP(tf->uv[b][0], 0.0, 1.0);
-                                       CLAMP(tf->uv[b][1], 0.0, 1.0);
-                               }
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
+
+                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                               CLAMP(luv->uv[0], 0.0, 1.0);
+                               CLAMP(luv->uv[1], 0.0, 1.0);
                        }
                }
        }
@@ -811,7 +847,7 @@ static int unwrap_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        ParamHandle *handle;
        int method = RNA_enum_get(op->ptr, "method");
        int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
@@ -819,7 +855,6 @@ static int unwrap_exec(bContext *C, wmOperator *op)
        
        /* add uvs if they don't exist yet */
        if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
@@ -841,7 +876,6 @@ static int unwrap_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }
 
@@ -873,17 +907,18 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
        Camera *camera= NULL;
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
-       ARegion *ar= CTX_wm_region(C);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+       ARegion *ar = CTX_wm_region(C);
        View3D *v3d= CTX_wm_view3d(C);
-       RegionView3D *rv3d= ar->regiondata;
-       EditFace *efa;
-       MTFace *tf;
+       RegionView3D *rv3d= CTX_wm_region_view3d(C);
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
+       MLoopUV *luv;
        float rotmat[4][4];
 
        /* add uvs if they don't exist yet */
        if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
@@ -893,17 +928,15 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
        }
 
        if(RNA_boolean_get(op->ptr, "orthographic")) {
-               uv_map_rotation_matrix(rotmat, ar->regiondata, obedit, 90.0f, 0.0f, 1.0f);
+               uv_map_rotation_matrix(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f);
                
-               for(efa= em->faces.first; efa; efa= efa->next) {
-                       if(efa->f & SELECT) {
-                               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
-                               project_from_view_ortho(tf->uv[0], efa->v1->co, rotmat);
-                               project_from_view_ortho(tf->uv[1], efa->v2->co, rotmat);
-                               project_from_view_ortho(tf->uv[2], efa->v3->co, rotmat);
-                               if(efa->v4)
-                                       project_from_view_ortho(tf->uv[3], efa->v4->co, rotmat);
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
+
+                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                               project_from_view_ortho(luv->uv, l->v->co, rotmat);
                        }
                }
        }
@@ -911,15 +944,13 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
                struct UvCameraInfo *uci= project_camera_info(v3d->camera, obedit->obmat, scene->r.xsch, scene->r.ysch);
                
                if(uci) {
-                       for(efa= em->faces.first; efa; efa= efa->next) {
-                               if(efa->f & SELECT) {
-                                       tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
-                                       project_from_camera(tf->uv[0], efa->v1->co, uci);
-                                       project_from_camera(tf->uv[1], efa->v2->co, uci);
-                                       project_from_camera(tf->uv[2], efa->v3->co, uci);
-                                       if(efa->v4)
-                                               project_from_camera(tf->uv[3], efa->v4->co, uci);
+                       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                               if (!BM_TestHFlag(efa, BM_SELECT))
+                                       continue;
+
+                               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                                       luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                                       project_from_camera(luv->uv, l->v->co, uci);
                                }
                        }
                        
@@ -929,15 +960,13 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
        else {
                copy_m4_m4(rotmat, obedit->obmat);
 
-               for(efa= em->faces.first; efa; efa= efa->next) {
-                       if(efa->f & SELECT) {
-                               tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
 
-                               project_from_view(tf->uv[0], efa->v1->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
-                               project_from_view(tf->uv[1], efa->v2->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
-                               project_from_view(tf->uv[2], efa->v3->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
-                               if(efa->v4)
-                                       project_from_view(tf->uv[3], efa->v4->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
+                       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                               project_from_view(luv->uv, l->v->co, rv3d->persmat, rotmat, ar->winx, ar->winy);
                        }
                }
        }
@@ -947,7 +976,6 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }
 
@@ -983,38 +1011,75 @@ static int reset_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
-       EditFace *efa;
-       MTFace *tf;
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
+       MTexPoly *tf;
+       MLoopUV *luv;
+       BLI_array_declare(uvs);
+       float **uvs = NULL;
+       int i;
 
        /* add uvs if they don't exist yet */
        if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
-       for(efa= em->faces.first; efa; efa= efa->next) {
-               if(efa->f & SELECT) {
-                       tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+               if (!BM_TestHFlag(efa, BM_SELECT))
+                       continue;
+               
+               BLI_array_empty(uvs);
+               i = 0;
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                       BLI_array_growone(uvs);
 
-                       tf->uv[0][0]= 0.0f;
-                       tf->uv[0][1]= 0.0f;
-                       
-                       tf->uv[1][0]= 1.0f;
-                       tf->uv[1][1]= 0.0f;
+                       uvs[i++] = luv->uv;
+               }
+
+               if (i == 3) {
+                       uvs[0][0] = 0.0;
+                       uvs[0][1] = 0.0;
                        
-                       tf->uv[2][0]= 1.0f;
-                       tf->uv[2][1]= 1.0f;
+                       uvs[1][0] = 1.0;
+                       uvs[1][1] = 0.0;
+
+                       uvs[2][0] = 1.0;
+                       uvs[2][1] = 1.0;
+               } else if (i == 4) {
+                       uvs[0][0] = 0.0;
+                       uvs[0][1] = 0.0;
                        
-                       tf->uv[3][0]= 0.0f;
-                       tf->uv[3][1]= 1.0f;
+                       uvs[1][0] = 1.0;
+                       uvs[1][1] = 0.0;
+
+                       uvs[2][0] = 1.0;
+                       uvs[2][1] = 1.0;
+
+                       uvs[3][0] = 0.0;
+                       uvs[3][1] = 1.0;
+                 /*make sure we ignore 2-sided faces*/
+               } else if (i > 2) {
+                       float fac = 0.0f, dfac = 1.0f / (float)efa->len;
+
+                       dfac *= M_PI*2;
+
+                       for (i=0; i<efa->len; i++) {
+                               uvs[i][0] = sin(fac);
+                               uvs[i][1] = cos(fac);
+
+                               fac += dfac;
+                       }
                }
        }
 
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
+       
+       BLI_array_free(uvs);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }
 
@@ -1046,55 +1111,71 @@ static void uv_sphere_project(float target[2], float source[3], float center[3],
                target[0] -= 1.0f;  
 }
 
-static void uv_map_mirror(EditFace *efa, MTFace *tf)
+static void uv_map_mirror(BMEditMesh *em, BMFace *efa, MTexPoly *tf)
 {
+       BMLoop *l;
+       BMIter liter;
+       MLoopUV *luv;
+       BLI_array_declare(uvs);
+       float **uvs = NULL;
        float dx;
-       int nverts, i, mi;
+       int i, mi;
 
-       nverts= (efa->v4)? 4: 3;
+       i = 0;
+       BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+               luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+               BLI_array_growone(uvs);
+
+               uvs[i] = luv->uv;
+               i++;
+       }
 
        mi = 0;
-       for(i=1; i<nverts; i++)
-               if(tf->uv[i][0] > tf->uv[mi][0])
+       for(i=1; i<efa->len; i++)
+               if(uvs[i][0] > uvs[mi][0])
                        mi = i;
 
-       for(i=0; i<nverts; i++) {
+       for(i=0; i<efa->len; i++) {
                if(i != mi) {
-                       dx = tf->uv[mi][0] - tf->uv[i][0];
-                       if(dx > 0.5) tf->uv[i][0] += 1.0;
+                       dx = uvs[mi][0] - uvs[i][0];
+                       if(dx > 0.5) uvs[i][0] += 1.0;
                } 
        } 
+
+       BLI_array_free(uvs);
 }
 
 static int sphere_project_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
-       EditFace *efa;
-       MTFace *tf;
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
+       MTexPoly *tf;
+       MLoopUV *luv;
        float center[3], rotmat[4][4];
 
        /* add uvs if they don't exist yet */
        if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
        uv_map_transform(C, op, center, rotmat);
 
-       for(efa= em->faces.first; efa; efa= efa->next) {
-               if(efa->f & SELECT) {
-                       tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+               if (!BM_TestHFlag(efa, BM_SELECT))
+                       continue;
 
-                       uv_sphere_project(tf->uv[0], efa->v1->co, center, rotmat);
-                       uv_sphere_project(tf->uv[1], efa->v2->co, center, rotmat);
-                       uv_sphere_project(tf->uv[2], efa->v3->co, center, rotmat);
-                       if(efa->v4)
-                               uv_sphere_project(tf->uv[3], efa->v4->co, center, rotmat);
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
-                       uv_map_mirror(efa, tf);
+                       uv_sphere_project(luv->uv, l->v->co, center, rotmat);
                }
+
+               tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+               uv_map_mirror(em, efa, tf);
        }
 
        uv_map_clip_correct(em, op);
@@ -1102,7 +1183,6 @@ static int sphere_project_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }
 
@@ -1142,31 +1222,33 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
-       EditFace *efa;
-       MTFace *tf;
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
+       MTexPoly *tf;
+       MLoopUV *luv;
        float center[3], rotmat[4][4];
 
        /* add uvs if they don't exist yet */
        if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
        uv_map_transform(C, op, center, rotmat);
 
-       for(efa= em->faces.first; efa; efa= efa->next) {
-               if(efa->f & SELECT) {
-                       tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
-                       uv_cylinder_project(tf->uv[0], efa->v1->co, center, rotmat);
-                       uv_cylinder_project(tf->uv[1], efa->v2->co, center, rotmat);
-                       uv_cylinder_project(tf->uv[2], efa->v3->co, center, rotmat);
-                       if(efa->v4)
-                               uv_cylinder_project(tf->uv[3], efa->v4->co, center, rotmat);
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+               tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+               if (!BM_TestHFlag(efa, BM_SELECT))
+                       continue;
+               
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
 
-                       uv_map_mirror(efa, tf);
+                       uv_cylinder_project(luv->uv, l->v->co, center, rotmat);
                }
+
+               uv_map_mirror(em, efa, tf);
        }
 
        uv_map_clip_correct(em, op);
@@ -1174,7 +1256,6 @@ static int cylinder_project_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }
 
@@ -1200,15 +1281,17 @@ static int cube_project_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *obedit= CTX_data_edit_object(C);
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
-       EditFace *efa;
-       MTFace *tf;
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
+       MTexPoly *tf;
+       MLoopUV *luv;
        float no[3], cube_size, *loc, dx, dy;
        int cox, coy;
 
        /* add uvs if they don't exist yet */
        if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
@@ -1218,41 +1301,38 @@ static int cube_project_exec(bContext *C, wmOperator *op)
        /* choose x,y,z axis for projection depending on the largest normal
         * component, but clusters all together around the center of map. */
 
-       for(efa= em->faces.first; efa; efa= efa->next) {
-               if(efa->f & SELECT) {
-                       tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-                       normal_tri_v3( no,efa->v1->co, efa->v2->co, efa->v3->co);
-                       
-                       no[0]= fabs(no[0]);
-                       no[1]= fabs(no[1]);
-                       no[2]= fabs(no[2]);
-                       
-                       cox=0; coy= 1;
-                       if(no[2]>=no[0] && no[2]>=no[1]);
-                       else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
-                       else { cox= 1; coy= 2; }
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+               int first=1;
+
+               tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
+               if (!BM_TestHFlag(efa, BM_SELECT))
+                       continue;
+               
+               VECCOPY(no, efa->no);
+
+               no[0]= fabs(no[0]);
+               no[1]= fabs(no[1]);
+               no[2]= fabs(no[2]);
+               
+               cox=0; coy= 1;
+               if(no[2]>=no[0] && no[2]>=no[1]);
+               else if(no[1]>=no[0] && no[1]>=no[2]) coy= 2;
+               else { cox= 1; coy= 2; }
+
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+
+                       luv->uv[0] = 0.5+0.5*cube_size*(loc[cox] + l->v->co[cox]);
+                       luv->uv[1] = 0.5+0.5*cube_size*(loc[coy] + l->v->co[coy]);
                        
-                       tf->uv[0][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v1->co[cox]);
-                       tf->uv[0][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v1->co[coy]);
-                       dx = floor(tf->uv[0][0]);
-                       dy = floor(tf->uv[0][1]);
-                       tf->uv[0][0] -= dx;
-                       tf->uv[0][1] -= dy;
-                       tf->uv[1][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v2->co[cox]);
-                       tf->uv[1][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v2->co[coy]);
-                       tf->uv[1][0] -= dx;
-                       tf->uv[1][1] -= dy;
-                       tf->uv[2][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v3->co[cox]);
-                       tf->uv[2][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v3->co[coy]);
-                       tf->uv[2][0] -= dx;
-                       tf->uv[2][1] -= dy;
-
-                       if(efa->v4) {
-                               tf->uv[3][0]= 0.5+0.5*cube_size*(loc[cox] + efa->v4->co[cox]);
-                               tf->uv[3][1]= 0.5+0.5*cube_size*(loc[coy] + efa->v4->co[coy]);
-                               tf->uv[3][0] -= dx;
-                               tf->uv[3][1] -= dy;
+                       if (first) {
+                               dx = floor(luv->uv[0]);
+                               dy = floor(luv->uv[1]);
+                               first = 0;
                        }
+
+                       luv->uv[0] -= dx;
+                       luv->uv[1] -= dy;
                }
        }
 
@@ -1261,7 +1341,6 @@ static int cube_project_exec(bContext *C, wmOperator *op)
        DAG_id_tag_update(obedit->data, 0);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
-       BKE_mesh_end_editmesh(obedit->data, em);
        return OPERATOR_FINISHED;
 }