svn merge ^/trunk/blender -r41226:41227 .
[blender.git] / source / blender / editors / uvedit / uvedit_unwrap_ops.c
index 29a9ae8..84eb418 100644 (file)
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
+#include "BLI_utildefines.h"
 #include "BLI_math.h"
 #include "BLI_edgehash.h"
 #include "BLI_editVert.h"
 #include "BLI_uvproject.h"
 #include "BLI_utildefines.h"
+#include "BLI_rand.h"
 
 #include "BKE_context.h"
 #include "BKE_customdata.h"
 #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"
 
@@ -73,9 +83,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;
@@ -83,15 +93,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;
        }
 
@@ -121,70 +131,71 @@ 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 int uvedit_have_selection(Scene *scene, EditMesh *em, short implicit)
+static int uvedit_have_selection(Scene *scene, BMEditMesh *em, short implicit)
 {
-       EditFace *efa;
-       MTFace *tf;
-
+       BMFace *efa;
+       BMLoop *l;
+       BMIter iter, liter;
+       MLoopUV *luv;
+       
        /* verify if we have any selected uv's before unwrapping,
           so we can cancel the operator early */
-       for(efa= em->faces.first; efa; efa= efa->next) {
+       BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
                if(scene->toolsettings->uv_flag & UV_SYNC_SELECTION) {
-                       if(efa->h)
+                       if(BM_TestHFlag(efa, BM_HIDDEN))
                                continue;
                }
-               else if((efa->h) || ((efa->f & SELECT)==0))
+               else if(BM_TestHFlag(efa, BM_HIDDEN) || !BM_TestHFlag(efa, BM_SELECT))
                        continue;
-
-               tf= (MTFace *)CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
-
-               if(!tf)
-                       return 1; /* default selected if doesn't exists */
+       
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
+                       if (!luv)
+                               return 1;
+                       
+                       if (uvedit_uv_selected(em, scene, l))
+                               break;
+               }
                
-               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)) )
-               ) {
+               if (implicit && !l)
                        continue;
-               }
-
+               
                return 1;
        }
 
        return 0;
 }
 
-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 = BM_get_actFace(em->bm, 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);
                
@@ -194,71 +205,112 @@ 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) {
+               BM_SetIndex(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;
-               
-               if((efa->h) || (sel && (efa->f & SELECT)==0))
-                       continue;
+               int lsel;
 
-               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)) )
-               ) {
+               if((BM_TestHFlag(efa, BM_HIDDEN)) || (sel && BM_TestHFlag(efa, BM_SELECT)==0))
                        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!*/
+               BLI_begin_edgefill();
+               
+               firstv = lastv = NULL;
+               BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
+                       int i;
+                       
+                       v = BLI_addfillvert(l->v->co);
+                       
+                       /*add small random offset*/
+                       for (i=0; i<3; i++) {
+                               v->co[i] += (BLI_drand()-0.5f)*FLT_EPSILON*50;
+                       }
+                       
+                       v->tmp.p = l;
+
+                       if (lastv) {
+                               BLI_addfilledge(lastv, v);
+                       }
+
+                       lastv = v;
+                       if (!firstv) 
+                               firstv = v;
+               }
+
+               BLI_addfilledge(firstv, v);
+               
+               /*mode 2 enables faster handling of tri/quads*/
+               BLI_edgefill(2);
+               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)BM_GetIndex(ls[0]->v);
+                       vkeys[1] = (ParamKey)BM_GetIndex(ls[1]->v);
+                       vkeys[2] = (ParamKey)BM_GetIndex(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);
                }
-               else
-                       nverts = 3;
 
-               param_face_add(handle, key, nverts, 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)BM_GetIndex(eed->v1);
+                               vkeys[1] = (ParamKey)BM_GetIndex(eed->v2);
                                param_edge_set_seam(handle, vkeys);
                        }
                }
@@ -274,7 +326,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;
@@ -286,13 +338,12 @@ static int 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");
        short implicit= 1;
 
        if(!uvedit_have_selection(scene, em, implicit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return 0;
        }
 
@@ -332,7 +383,7 @@ static void minimize_stretch_iteration(bContext *C, wmOperator *op, int interact
                param_flush(ms->handle);
 
                if(sa) {
-                       sprintf(str, "Minimize Stretch. Blend %.2f", ms->blend);
+                       sprintf(str, "Minimize Stretch. Blend %.2f.", ms->blend);
                        ED_area_headerprint(sa, str);
                }
 
@@ -473,12 +524,9 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
        ot->poll= ED_operator_uvedit;
 
        /* properties */
-       RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes",
-                       "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
-       RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend",
-                            "Blend factor between stretch minimized and original", 0.0f, 1.0f);
-       RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations",
-                   "Number of iterations to run, 0 is unlimited when run interactively", 0, 100);
+       RNA_def_boolean(ot->srna, "fill_holes", 1, "Fill Holes", "Virtual fill holes in mesh before unwrapping, to better avoid overlaps and preserve symmetry");
+       RNA_def_float_factor(ot->srna, "blend", 0.0f, 0.0f, 1.0f, "Blend", "Blend factor between stretch minimized and original", 0.0f, 1.0f);
+       RNA_def_int(ot->srna, "iterations", 0, 0, INT_MAX, "Iterations", "Number of iterations to run, 0 is unlimited when run interactively", 0, 100);
 }
 
 /* ******************** Pack Islands operator **************** */
@@ -487,12 +535,11 @@ static int pack_islands_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;
        short implicit= 1;
 
        if(!uvedit_have_selection(scene, em, implicit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
@@ -511,7 +558,6 @@ static int pack_islands_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;
 }
 
@@ -527,8 +573,7 @@ void UV_OT_pack_islands(wmOperatorType *ot)
        ot->poll= ED_operator_uvedit;
 
        /* properties */
-       RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin",
-                            "Space between islands", 0.0f, 1.0f);
+       RNA_def_float_factor(ot->srna, "margin", 0.0f, 0.0f, 1.0f, "Margin", "Space between islands", 0.0f, 1.0f);
 }
 
 /* ******************** Average Islands Scale operator **************** */
@@ -537,12 +582,11 @@ 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;
        short implicit= 1;
 
        if(!uvedit_have_selection(scene, em, implicit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
                return OPERATOR_CANCELLED;
        }
 
@@ -554,7 +598,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;
 }
 
@@ -576,19 +619,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, 0, 1);
 
        param_lscm_begin(liveHandle, PARAM_TRUE, abf);
-       BKE_mesh_end_editmesh(obedit->data, em);
 }
 
 void ED_uvedit_live_unwrap_re_solve(void)
@@ -619,9 +660,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;
 
@@ -631,13 +675,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);
@@ -712,7 +755,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 */
@@ -739,7 +782,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)
@@ -765,14 +807,17 @@ static void uv_transform_properties(wmOperatorType *ot, int 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= BM_get_actFace(em->bm, 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);
        }
        
@@ -782,30 +827,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.5f)*scale)+0.5f;
-                               tf->uv[1][0]= ((tf->uv[1][0]-0.5f)*scale)+0.5f;
-                               tf->uv[2][0]= ((tf->uv[2][0]-0.5f)*scale)+0.5f;
-                               if(efa->v4)
-                                       tf->uv[3][0]= ((tf->uv[3][0]-0.5f)*scale)+0.5f;
+               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) || BM_TestHFlag(efa, BM_HIDDEN))
+                               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.5f)*scale)+0.5f;
-                               tf->uv[1][1]= ((tf->uv[1][1]-0.5f)*scale)+0.5f;
-                               tf->uv[2][1]= ((tf->uv[2][1]-0.5f)*scale)+0.5f;
-                               if(efa->v4)
-                                       tf->uv[3][1]= ((tf->uv[3][1]-0.5f)*scale)+0.5f;
+               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)||BM_TestHFlag(efa, BM_HIDDEN))
+                               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;
                        }
                }
        }
@@ -823,12 +866,13 @@ static void uv_map_clip_correct_properties(wmOperatorType *ot)
                        "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");
        int clip_to_bounds= RNA_boolean_get(op->ptr, "clip_to_bounds");
        int scale_to_bounds= RNA_boolean_get(op->ptr, "scale_to_bounds");
@@ -840,16 +884,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);
-
-                               DO_MINMAX2(tf->uv[0], min, max);
-                               DO_MINMAX2(tf->uv[1], min, max);
-                               DO_MINMAX2(tf->uv[2], min, max);
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
 
-                               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);
                        }
                }
                
@@ -862,31 +903,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;
+               BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(efa, BM_SELECT))
+                               continue;
 
-                               for(b=0; b<nverts; b++) {
-                                       CLAMP(tf->uv[b][0], 0.0f, 1.0f);
-                                       CLAMP(tf->uv[b][1], 0.0f, 1.0f);
-                               }
+                       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.0f, 1.0f);
+                               CLAMP(luv->uv[1], 0.0f, 1.0f);
                        }
                }
        }
@@ -897,7 +935,7 @@ static void uv_map_clip_correct(EditMesh *em, wmOperator *op)
 /* assumes UV layer is checked, doesn't run update funcs */
 void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
 {
-       EditMesh *em= BKE_mesh_get_editmesh((Mesh*)obedit->data);
+       BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
        ParamHandle *handle;
 
        const short fill_holes= scene->toolsettings->uvcalc_flag & UVCALC_FILLHOLES;
@@ -915,26 +953,21 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
        param_flush(handle);
 
        param_delete(handle);
-
-       BKE_mesh_end_editmesh(obedit->data, em);
 }
 
 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;
        int method = RNA_enum_get(op->ptr, "method");
        int fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
        int correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
        short implicit= 0;
 
        if(!uvedit_have_selection(scene, em, implicit)) {
-               BKE_mesh_end_editmesh(obedit->data, em);
-               return 0;
+               return OPERATOR_CANCELLED;
        }
-
-       BKE_mesh_end_editmesh(obedit->data, em);
        
        /* add uvs if they don't exist yet */
        if(!ED_uvedit_ensure_uvs(C, scene, obedit)) {
@@ -991,17 +1024,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;
        }
 
@@ -1011,17 +1045,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);
                        }
                }
        }
@@ -1029,15 +1061,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);
                                }
                        }
                        
@@ -1047,15 +1077,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);
                        }
                }
        }
@@ -1065,7 +1093,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;
 }
 
@@ -1101,38 +1128,74 @@ 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;
+       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;
 }
 
@@ -1164,55 +1227,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 *UNUSED(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.5f) tf->uv[i][0] += 1.0f;
+                       dx = uvs[mi][0] - uvs[i][0];
+                       if(dx > 0.5f) uvs[i][0] += 1.0f;
                } 
        } 
+
+       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);
@@ -1220,7 +1299,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;
 }
 
@@ -1260,31 +1338,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);
@@ -1292,7 +1372,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;
 }
 
@@ -1318,15 +1397,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;
        }
 
@@ -1336,41 +1417,40 @@ 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; }
+               
+               dx = dy = 0;
+               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.5f+0.5f*cube_size*(loc[cox] + l->v->co[cox]);
+                       luv->uv[1] = 0.5f+0.5f*cube_size*(loc[coy] + l->v->co[coy]);
                        
-                       tf->uv[0][0]= 0.5f+0.5f*cube_size*(loc[cox] + efa->v1->co[cox]);
-                       tf->uv[0][1]= 0.5f+0.5f*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.5f+0.5f*cube_size*(loc[cox] + efa->v2->co[cox]);
-                       tf->uv[1][1]= 0.5f+0.5f*cube_size*(loc[coy] + efa->v2->co[coy]);
-                       tf->uv[1][0] -= dx;
-                       tf->uv[1][1] -= dy;
-                       tf->uv[2][0]= 0.5f+0.5f*cube_size*(loc[cox] + efa->v3->co[cox]);
-                       tf->uv[2][1]= 0.5f+0.5f*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.5f+0.5f*cube_size*(loc[cox] + efa->v4->co[cox]);
-                               tf->uv[3][1]= 0.5f+0.5f*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;
                }
        }
 
@@ -1379,7 +1459,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;
 }
 
@@ -1395,7 +1474,6 @@ void UV_OT_cube_project(wmOperatorType *ot)
        ot->poll= ED_operator_uvmap;
 
        /* properties */
-       RNA_def_float(ot->srna, "cube_size", 1.0f, 0.0f, FLT_MAX, "Cube Size",
-                     "Size of the cube to project on", 0.001f, 100.0f);
+       RNA_def_float(ot->srna, "cube_size", 1.0f, 0.0f, FLT_MAX, "Cube Size", "Size of the cube to project on", 0.001f, 100.0f);
        uv_map_clip_correct_properties(ot);
 }