diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index f1c756bcce3..187a9ec189f 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -872,7 +872,7 @@ void Mat4MulVec( float mat[][4], int *vec) vec[2]=(int)(x*mat[0][2] + y*mat[1][2] + mat[2][2]*vec[2] + mat[3][2]); } -void Mat4MulVecfl( float mat[][4], float *vec) +void Mat4MulVecfl(float mat[][4], float *vec) { float x,y; diff --git a/source/blender/bmesh/bmesh_operator_api.h b/source/blender/bmesh/bmesh_operator_api.h index 9875dfc9073..2aee9b4813a 100644 --- a/source/blender/bmesh/bmesh_operator_api.h +++ b/source/blender/bmesh/bmesh_operator_api.h @@ -48,6 +48,7 @@ struct GHashIterator; #define BMOP_OPSLOT_INT 1 #define BMOP_OPSLOT_FLT 2 #define BMOP_OPSLOT_PNT 3 +#define BMOP_OPSLOT_MAT 4 #define BMOP_OPSLOT_VEC 7 /*after BMOP_OPSLOT_VEC, everything is @@ -159,6 +160,13 @@ int BMO_CountFlag(struct BMesh *bm, int flag, int type); %hv will do verts, etc. must pass in at least one element type letter. %f[f/e/v] - same as %h. + %v - pointer to a float vector of length 3. + %m[3/4] - matrix, 3/4 refers to the matrix size, 3 or 4. the + corrusponding argument must be a pointer to + a float matrix. + %s - copy a slot from another op, instead of mapping to one + argument, it maps to two, a pointer to an operator and + a slot name. */ /*executes an operator*/ int BMO_CallOpf(BMesh *bm, char *fmt, ...); @@ -196,6 +204,13 @@ void *BMO_Get_Pnt(BMOperator *op, char *slotname); void BMO_Set_Vec(struct BMOperator *op, char *slotname, float *vec); void BMO_Get_Vec(BMOperator *op, char *slotname, float *vec_out); +/*only supports square mats*/ +/*size must be 3 or 4; this api is meant only for transformation matrices. + note that internally the matrix is stored in 4x4 form, and it's safe to + call whichever BMO_Get_Mat* function you want.*/ +void BMO_Set_Mat(struct BMOperator *op, char *slotname, float *mat, int size); +void BMO_Get_Mat4(struct BMOperator *op, char *slotname, float mat[4][4]); +void BMO_Get_Mat3(struct BMOperator *op, char *slotname, float mat[3][3]); /*puts every element of type type (which is a bitmask) with tool flag flag, into a slot.*/ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 5cc2032f78b..54033ae6bb4 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -3,15 +3,35 @@ #include +/*applies a transform to vertices*/ + +BMOpDefine def_translate= { + "translate", + {{BMOP_OPSLOT_VEC, "vec"}, + {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, + {0, /*null-terminating sentinel*/}}, + bmesh_translate_exec, + 0, +}; + + +BMOpDefine def_transform = { + "transform", + {{BMOP_OPSLOT_MAT, "mat"}, + {BMOP_OPSLOT_ELEMENT_BUF, "verts"}, + {0, /*null-terminating sentinel*/}}, + bmesh_transform_exec, + 0, +}; + /*loads a bmesh into an object*/ BMOpDefine def_object_load_bmesh = { "object_load_bmesh", - /*pointer to a mesh struct*/ {{BMOP_OPSLOT_PNT, "scene"}, {BMOP_OPSLOT_PNT, "object"}, {0, /*null-terminating sentinel*/}}, bmesh_to_mesh_exec, - 0 + 0, }; @@ -191,6 +211,8 @@ BMOpDefine *opdefines[] = { &def_extrudeverts_indiv, &def_mesh_to_bmesh, &def_object_load_bmesh, + &def_transform, + &def_translate, }; int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*)); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 8a982333633..812cd5cd9d9 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -1,5 +1,6 @@ #include "MEM_guardedalloc.h" +#include "BLI_arithb.h" #include "BLI_memarena.h" #include "BLI_mempool.h" #include "BLI_blenlib.h" @@ -259,6 +260,45 @@ void BMO_Set_Int(BMOperator *op, char *slotname, int i) slot->data.i = i; } +/*only supports square mats*/ +void BMO_Set_Mat(struct BMOperator *op, char *slotname, float *mat, int size) +{ + BMOpSlot *slot = BMO_GetSlot(op, slotname); + if( !(slot->slottype == BMOP_OPSLOT_MAT) ) + return 0; + + slot->len = 4; + slot->data.p = BLI_memarena_alloc(op->arena, sizeof(float)*4*4); + + if (size == 4) { + memcpy(slot->data.p, mat, sizeof(float)*4*4); + } else if (size == 3) { + Mat4CpyMat3(slot->data.p, mat); + } else { + printf("yeek! invalid size in BMO_Set_Mat!\n"); + + memset(slot->data.p, 0, sizeof(float)*4*4); + return; + } +} + +void BMO_Get_Mat4(struct BMOperator *op, char *slotname, float mat[4][4]) +{ + BMOpSlot *slot = BMO_GetSlot(op, slotname); + if( !(slot->slottype == BMOP_OPSLOT_MAT) ) + return; + + memcpy(mat, slot->data.p, sizeof(float)*4*4); +} + +void BMO_Get_Mat3(struct BMOperator *op, char *slotname, float mat[3][3]) +{ + BMOpSlot *slot = BMO_GetSlot(op, slotname); + if( !(slot->slottype == BMOP_OPSLOT_MAT) ) + return; + + Mat3CpyMat4(mat, slot->data.p); +} void BMO_Set_Pnt(BMOperator *op, char *slotname, void *p) { @@ -1028,6 +1068,33 @@ int BMO_VInitOpf(BMesh *bm, BMOperator *op, char *fmt, va_list vlist) case '=': case '%': break; + case 'm': { + int size, c; + + c = nextc(fmt); + fmt++; + + if (c == '3') size = 3; + else if (c == '4') size = 4; + else goto error; + + BMO_Set_Mat(op, slotname, va_arg(vlist, void*), size); + state = 1; + break; + } + case 'v': { + BMO_Set_Vec(op, slotname, va_arg(vlist, float*)); + state = 1; + break; + } + case 's': { + BMOperator *op2 = va_arg(vlist, void*); + char *slotname2 = va_arg(vlist, char*); + + BMO_CopySlot(op2, op, slotname2, slotname); + state = 1; + break; + } case 'i': case 'd': BMO_Set_Int(op, slotname, va_arg(vlist, int)); diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 22aae12e5e4..a3cbb67b660 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -23,5 +23,7 @@ void makeprim_exec(BMesh *bm, BMOperator *op); void extrude_vert_indiv_exec(BMesh *bm, BMOperator *op); void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op); void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op); +void bmesh_translate_exec(BMesh *bm, BMOperator *op); +void bmesh_transform_exec(BMesh *bm, BMOperator *op); #endif diff --git a/source/blender/bmesh/operators/utils.c b/source/blender/bmesh/operators/utils.c new file mode 100644 index 00000000000..dc18da68477 --- /dev/null +++ b/source/blender/bmesh/operators/utils.c @@ -0,0 +1,63 @@ + +#include "MEM_guardedalloc.h" +#include "BKE_customdata.h" +#include "DNA_listBase.h" +#include "DNA_customdata_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include +#include "BKE_utildefines.h" +#include "BKE_mesh.h" +#include "BKE_global.h" +#include "BKE_DerivedMesh.h" +#include "BKE_cdderivedmesh.h" + +#include "BLI_editVert.h" +#include "mesh_intern.h" +#include "ED_mesh.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_edgehash.h" + +#include "bmesh.h" + +/* + * UTILS.C + * + * utility bmesh operators, e.g. transform, + * translate, rotate, scale, etc. + * +*/ + +void bmesh_transform_exec(BMesh *bm, BMOperator *op) { + BMOIter iter; + BMVert *v; + float mat[4][4]; + + BMO_Get_Mat4(op, "mat", mat); + + BMO_ITER(v, &iter, bm, op, "verts") { + Mat4MulVecfl(mat, v->co); + } +} + +/*this operator calls the transform operator, which + is a little complex, but makes it easier to make + sure the transform op is working, since initially + only this one will be used.*/ +void bmesh_translate_exec(BMesh *bm, BMOperator *op) { + BMOIter iter; + BMVert *v; + float mat[4][4], vec[3]; + + BMO_Get_Vec(op, "offset", vec); + + Mat4One(mat); + VECCOPY(mat[3], vec); + + BMO_CallOpf(bm, "transform mat=%m4 verts=%s", mat, op, "verts"); +} + diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c index 3272cb03631..973ff190845 100644 --- a/source/blender/editors/mesh/bmesh_tools.c +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -466,7 +466,7 @@ short EDBM_Extrude_verts_indiv(BMEditMesh *em, wmOperator *op, short flag, float return 'g'; // g is grab } -short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int eflag, float *nor) +short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int flag, float *nor) { BMesh *bm = em->bm; BMIter iter; @@ -475,24 +475,9 @@ short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int eflag, float *nor) BMVert *vert; BMEdge *edge; BMFace *f; - void *el; ModifierData *md; - int flag; + BMHeader *el; - switch (eflag) { - case SELECT: - flag = BM_SELECT; - break; - default: - flag = BM_SELECT; - break; - } - - for (f=BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);f;f=BMIter_Step(&iter)) { - add_normal_aligned(nor, f->no); - } - Normalize(nor); - BMO_Init_Op(&extop, "extrudefaceregion"); BMO_HeaderFlag_To_Slot(bm, &extop, "edgefacein", flag, BM_VERT|BM_EDGE|BM_FACE); @@ -561,10 +546,19 @@ short EDBM_Extrude_edge(Object *obedit, BMEditMesh *em, int eflag, float *nor) BMO_Exec_Op(bm, &extop); + nor[0] = nor[1] = nor[2] = 0.0f; + BMO_ITER(el, &siter, bm, &extop, "geomout") { BM_Select(bm, el, 1); + + if (el->type == BM_FACE) { + f = (BMFace*)el; + add_normal_aligned(nor, f->no); + }; } + Normalize(nor); + BMO_Finish_Op(bm, &extop); if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab @@ -576,29 +570,6 @@ short EDBM_Extrude_vert(Object *obedit, BMEditMesh *em, short flag, float *nor) BMIter iter; BMEdge *eed; - /*ensure vert flags are consistent for edge selections*/ - eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); - for ( ; eed; eed=BMIter_Step(&iter)) { - if (BM_TestHFlag(eed, flag)) { - BM_SetHFlag(eed->v1, flag); - BM_SetHFlag(eed->v2, flag); - } else { - if (BM_TestHFlag(eed->v1, flag) && BM_TestHFlag(eed->v2, flag)) - BM_SetHFlag(eed, flag); - } - } - - return EDBM_Extrude_edge(obedit, em, flag, nor); - -} - -/* generic extrude */ -short EDBM_Extrude(Object *obedit, BMEditMesh *em, short flag, float *nor) -{ - if(em->selectmode & SCE_SELECT_VERTEX) { - BMIter iter; - BMEdge *eed; - /*ensure vert flags are consistent for edge selections*/ eed = BMIter_New(&iter, em->bm, BM_EDGES_OF_MESH, NULL); for ( ; eed; eed=BMIter_Step(&iter)) { @@ -620,18 +591,13 @@ short EDBM_Extrude(Object *obedit, BMEditMesh *em, short flag, float *nor) } return EDBM_Extrude_edge(obedit, em, flag, nor); - } else - return EDBM_Extrude_edge(obedit, em, flag, nor); - -} +} static int extrude_repeat_mesh(bContext *C, wmOperator *op) { -#if 0 Object *obedit= CTX_data_edit_object(C); - EditMesh *em= EM_GetEditMesh((Mesh *)obedit->data); - + BMEditMesh *em = ((Mesh *)obedit->data)->edit_btmesh; RegionView3D *rv3d = CTX_wm_region_view3d(C); int steps = RNA_int_get(op->ptr,"steps"); @@ -656,19 +622,18 @@ static int extrude_repeat_mesh(bContext *C, wmOperator *op) Mat3MulVecfl(tmat, dvec); for(a=0; abm, "extrudefaceregion edgefacein=%hef", BM_SELECT); + BMO_CallOpf(em->bm, "translate vec=%v verts=%hv", (float*)dvec, BM_SELECT); + //extrudeflag(obedit, em, SELECT, nor); + //translateflag(em, SELECT, dvec); } - recalc_editnormals(em); - - EM_fgon_flags(em); - + EDBM_RecalcNormals(em); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit); // DAG_object_flush_update(scene, obedit, OB_RECALC_DATA); - EM_EndEditMesh(obedit->data, em); -#endif return OPERATOR_FINISHED; } @@ -729,7 +694,9 @@ void EDBM_Extrude_Mesh(Object *obedit, BMEditMesh *em, wmOperator *op) if(nr<1) return; - if(nr==1) transmode= EDBM_Extrude(obedit, em, SELECT, nor); + if(nr==1 && em->selectmode & SCE_SELECT_VERTEX) + transmode= EDBM_Extrude_vert(obedit, em, SELECT, nor); + else if (nr == 1) transmode= EDBM_Extrude_edge(obedit, em, SELECT, nor); else if(nr==4) transmode= EDBM_Extrude_verts_indiv(em, op, SELECT, nor); else if(nr==3) transmode= EDBM_Extrude_edges_indiv(em, SELECT, nor); else transmode= EDBM_Extrude_face_indiv(em, SELECT, nor); @@ -850,3 +817,126 @@ void MESH_OT_select_all_toggle(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } + +/* *************** add-click-mesh (extrude) operator ************** */ + +static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) +{ +#if 0 //BMESH_TODO + ViewContext vc; + EditVert *eve, *v1; + float min[3], max[3]; + int done= 0; + + em_setup_viewcontext(C, &vc); + + INIT_MINMAX(min, max); + + for(v1= vc.em->verts.first;v1; v1=v1->next) { + if(v1->f & SELECT) { + DO_MINMAX(v1->co, min, max); + done= 1; + } + } + + /* call extrude? */ + if(done) { + EditEdge *eed; + float vec[3], cent[3], mat[3][3]; + float nor[3]= {0.0, 0.0, 0.0}; + + /* check for edges that are half selected, use for rotation */ + done= 0; + for(eed= vc.em->edges.first; eed; eed= eed->next) { + if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) { + if(eed->v1->f & SELECT) VecSubf(vec, eed->v1->co, eed->v2->co); + else VecSubf(vec, eed->v2->co, eed->v1->co); + VecAddf(nor, nor, vec); + done= 1; + } + } + if(done) Normalize(nor); + + /* center */ + VecAddf(cent, min, max); + VecMulf(cent, 0.5f); + VECCOPY(min, cent); + + Mat4MulVecfl(vc.obedit->obmat, min); // view space + view3d_get_view_aligned_coordinate(&vc, min, event->mval); + Mat4Invert(vc.obedit->imat, vc.obedit->obmat); + Mat4MulVecfl(vc.obedit->imat, min); // back in object space + + VecSubf(min, min, cent); + + /* calculate rotation */ + Mat3One(mat); + if(done) { + float dot; + + VECCOPY(vec, min); + Normalize(vec); + dot= INPR(vec, nor); + + if( fabs(dot)<0.999) { + float cross[3], si, q1[4]; + + Crossf(cross, nor, vec); + Normalize(cross); + dot= 0.5f*saacos(dot); + si= (float)sin(dot); + q1[0]= (float)cos(dot); + q1[1]= cross[0]*si; + q1[2]= cross[1]*si; + q1[3]= cross[2]*si; + + QuatToMat3(q1, mat); + } + } + + extrudeflag(vc.obedit, vc.em, SELECT, nor); + rotateflag(vc.em, SELECT, cent, mat); + translateflag(vc.em, SELECT, min); + + recalc_editnormals(vc.em); + } + else { + float mat[3][3],imat[3][3]; + float *curs= give_cursor(vc.scene, vc.v3d); + + VECCOPY(min, curs); + view3d_get_view_aligned_coordinate(&vc, min, event->mval); + + eve= addvertlist(vc.em, 0, NULL); + + Mat3CpyMat4(mat, vc.obedit->obmat); + Mat3Inv(imat, mat); + + VECCOPY(eve->co, min); + Mat3MulVecfl(imat, eve->co); + VecSubf(eve->co, eve->co, vc.obedit->obmat[3]); + + eve->f= SELECT; + } + + //retopo_do_all(); + WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit); + DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA); + + return OPERATOR_FINISHED; +#endif +} + +void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Duplicate or Extrude at 3D Cursor"; + ot->idname= "MESH_OT_dupli_extrude_cursor"; + + /* api callbacks */ + ot->invoke= dupli_extrude_cursor; + ot->poll= ED_operator_editmesh; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index 0bb4970b825..318a217bcd3 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -119,129 +119,6 @@ static short icoface[20][3] = { {10,9,11} }; -/* *************** add-click-mesh (extrude) operator ************** */ - -static int dupli_extrude_cursor(bContext *C, wmOperator *op, wmEvent *event) -{ -#if 0 //BMESH_TODO - ViewContext vc; - EditVert *eve, *v1; - float min[3], max[3]; - int done= 0; - - em_setup_viewcontext(C, &vc); - - INIT_MINMAX(min, max); - - for(v1= vc.em->verts.first;v1; v1=v1->next) { - if(v1->f & SELECT) { - DO_MINMAX(v1->co, min, max); - done= 1; - } - } - - /* call extrude? */ - if(done) { - EditEdge *eed; - float vec[3], cent[3], mat[3][3]; - float nor[3]= {0.0, 0.0, 0.0}; - - /* check for edges that are half selected, use for rotation */ - done= 0; - for(eed= vc.em->edges.first; eed; eed= eed->next) { - if( (eed->v1->f & SELECT)+(eed->v2->f & SELECT) == SELECT ) { - if(eed->v1->f & SELECT) VecSubf(vec, eed->v1->co, eed->v2->co); - else VecSubf(vec, eed->v2->co, eed->v1->co); - VecAddf(nor, nor, vec); - done= 1; - } - } - if(done) Normalize(nor); - - /* center */ - VecAddf(cent, min, max); - VecMulf(cent, 0.5f); - VECCOPY(min, cent); - - Mat4MulVecfl(vc.obedit->obmat, min); // view space - view3d_get_view_aligned_coordinate(&vc, min, event->mval); - Mat4Invert(vc.obedit->imat, vc.obedit->obmat); - Mat4MulVecfl(vc.obedit->imat, min); // back in object space - - VecSubf(min, min, cent); - - /* calculate rotation */ - Mat3One(mat); - if(done) { - float dot; - - VECCOPY(vec, min); - Normalize(vec); - dot= INPR(vec, nor); - - if( fabs(dot)<0.999) { - float cross[3], si, q1[4]; - - Crossf(cross, nor, vec); - Normalize(cross); - dot= 0.5f*saacos(dot); - si= (float)sin(dot); - q1[0]= (float)cos(dot); - q1[1]= cross[0]*si; - q1[2]= cross[1]*si; - q1[3]= cross[2]*si; - - QuatToMat3(q1, mat); - } - } - - extrudeflag(vc.obedit, vc.em, SELECT, nor); - rotateflag(vc.em, SELECT, cent, mat); - translateflag(vc.em, SELECT, min); - - recalc_editnormals(vc.em); - } - else { - float mat[3][3],imat[3][3]; - float *curs= give_cursor(vc.scene, vc.v3d); - - VECCOPY(min, curs); - view3d_get_view_aligned_coordinate(&vc, min, event->mval); - - eve= addvertlist(vc.em, 0, NULL); - - Mat3CpyMat4(mat, vc.obedit->obmat); - Mat3Inv(imat, mat); - - VECCOPY(eve->co, min); - Mat3MulVecfl(imat, eve->co); - VecSubf(eve->co, eve->co, vc.obedit->obmat[3]); - - eve->f= SELECT; - } - - //retopo_do_all(); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, vc.obedit); - DAG_object_flush_update(vc.scene, vc.obedit, OB_RECALC_DATA); - - return OPERATOR_FINISHED; -#endif -} - -void MESH_OT_dupli_extrude_cursor(wmOperatorType *ot) -{ - /* identifiers */ - ot->name= "Duplicate or Extrude at 3D Cursor"; - ot->idname= "MESH_OT_dupli_extrude_cursor"; - - /* api callbacks */ - ot->invoke= dupli_extrude_cursor; - ot->poll= ED_operator_editmesh; - - /* flags */ - ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; -} - /* ********************** */ diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index e61deb1d554..dc00f64628f 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -265,7 +265,7 @@ void ED_keymap_mesh(wmWindowManager *wm) WM_keymap_add_item(keymap, "MESH_OT_tris_convert_to_quads", JKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "MESH_OT_split", FOURKEY, KM_PRESS, KM_CTRL, 0); - WM_keymap_add_item(keymap, "MESH_OT_extrude_repeat", FOURKEY, KM_PRESS, KM_ALT, 0); + WM_keymap_add_item(keymap, "MESH_OT_extrude_repeat", FOURKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_edge_rotate", FIVEKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "MESH_OT_loop_to_region",SIXKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index ba4d3089fdf..d79fe98b563 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -478,6 +478,7 @@ void recalcData(TransInfo *t) DAG_object_flush_update(scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */ + BMEdit_RecalcTesselation(em); EDBM_RecalcNormals(em); } }