finished bmeshafying merge, though probably needs further testing and debugging....
authorJoseph Eagar <joeedh@gmail.com>
Mon, 31 Aug 2009 23:07:05 +0000 (23:07 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Mon, 31 Aug 2009 23:07:05 +0000 (23:07 +0000)
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/intern/bmesh_operators_private.h
source/blender/bmesh/operators/removedoubles.c
source/blender/editors/mesh/bmesh_tools.c
source/blender/editors/mesh/editmesh_tools.c

index d1a20c6a3c87c3e4ddb7fd8bf3a47515966991e0..401cfba2fbd71ed178fb45d1d78cde598a819657 100644 (file)
@@ -406,6 +406,8 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me)
                totloop += iter->len;
        }
        iter->free(iter);
+       
+       tmp.totloop = totloop;
 
        CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
        CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
index b8e8e86ffaa0e160e6079fa890540b62ffd53588..35d69fbe9cde673bde6b94ef63e56c09b3a9a4d5 100644 (file)
@@ -237,6 +237,35 @@ BMOpDefine def_collapse = {
 };
 
 
+/*
+  Facedata point Merge
+
+  Merge uv/vcols at a specific vertex.
+*/
+BMOpDefine def_pointmerge_facedata = {
+       "pointmerge_facedata",
+       {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+        {BMOP_OPSLOT_ELEMENT_BUF, "snapv"}, /*snap vertex*/
+        {0, /*null-terminating sentinel*/}},
+       bmesh_pointmerge_facedata_exec,
+       0,
+};
+
+/*
+  Average Vertices Facevert Data
+
+  Merge uv/vcols associated with the input vertices at
+  the bounding box center. (I know, it's not averaging but
+  the vert_snap_to_bb_center is just too long).
+*/
+BMOpDefine def_vert_average_facedata = {
+       "vert_average_facedata",
+       {{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
+        {0, /*null-terminating sentinel*/}},
+       bmesh_vert_average_facedata_exec,
+       0,
+};
+
 /*
   Point Merge
 
@@ -704,6 +733,8 @@ BMOpDefine *opdefines[] = {
        &def_similarfaces,
        &def_similaredges,
        &def_similarverts,
+       &def_pointmerge_facedata,
+       &def_vert_average_facedata,
 };
 
 int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));
index f8e0685fa15f9b1539503500b942e1bf8676c2de..f99a2322bd8469a53d8f8aaf554c4977974febce 100644 (file)
@@ -49,4 +49,7 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op);
 void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op);
 void bmesh_similaredges_exec(BMesh *bm, BMOperator *op);
 void bmesh_similarverts_exec(BMesh *bm, BMOperator *op);
+void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op);
+void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op);
+
 #endif
index 12f652ce9649b50280dcc6cf393cb18c19274313..24d57b6b1fdad98fe38545e6a76ab2e5cb9df5ef 100644 (file)
@@ -213,17 +213,120 @@ static int vergaverco(const void *e1, const void *e2)
 
 #define EDGE_MARK      1
 
+void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
+{
+       BMOIter siter;
+       BMIter iter;
+       BMVert *v, *snapv;
+       BMLoop *l, *firstl = NULL;
+       float fac;
+       int i, tot;
+
+       snapv = BMO_IterNew(&siter, bm, op, "snapv", BM_VERT);  
+       tot = BM_Vert_FaceCount(snapv);
+
+       if (!tot)
+               return;
+
+       fac = 1.0f / tot;
+       BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, snapv) {
+               if (!firstl) {
+                       firstl = l;
+               }
+               
+               for (i=0; i<bm->ldata.totlayer; i++) {
+                       if (CustomData_layer_has_math(&bm->ldata, i)) {
+                               int type = bm->ldata.layers[i].type;
+                               void *e1, *e2;
+
+                               e1 = CustomData_bmesh_get_layer_n(&bm->ldata, firstl->head.data, i); 
+                               e2 = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+                               
+                               CustomData_data_multiply(type, e2, fac);
+
+                               if (l != firstl)
+                                       CustomData_data_add(type, e1, e2);
+                       }
+               }
+       }
+
+       BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+               BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+                       if (l == firstl) 
+                               continue;
+
+                       CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, firstl->head.data, &l->head.data);
+               }
+       }
+}
+
+void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op)
+{
+       BMOIter siter;
+       BMIter iter;
+       BMVert *v;
+       BMLoop *l, *firstl = NULL;
+       CDBlockBytes min, max;
+       void *block;
+       int i, type;
+
+       for (i=0; i<bm->ldata.totlayer; i++) {
+               if (!CustomData_layer_has_math(&bm->ldata, i))
+                       continue;
+               
+               type = bm->ldata.layers[i].type;
+               CustomData_data_initminmax(type, &min, &max);
+
+               BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+                       BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+                               block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+                               CustomData_data_dominmax(type, block, &min, &max);      
+                       }
+               }
+
+               CustomData_data_multiply(type, &min, 0.5f);
+               CustomData_data_multiply(type, &max, 0.5f);
+               CustomData_data_add(type, &min, &max);
+
+               BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+                       BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
+                               block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
+                               CustomData_data_copy_value(type, &min, block);
+                       }
+               }
+       }
+}
+
 void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op)
 {
+       BMOperator weldop;
+       BMOIter siter;
+       BMVert *v, *snapv = NULL;
+       float vec[3];
+       
+       BMO_Get_Vec(op, "mergeco", vec);
+
+       //BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
+       BMO_Init_Op(&weldop, "weldverts");
+       
+       BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
+               if (!snapv) {
+                       snapv = v;
+                       VECCOPY(snapv->co, vec);
+               } else {
+                       BMO_Insert_MapPointer(bm, &weldop, "targetmap", v, snapv);
+               }               
+       }
+
+       BMO_Exec_Op(bm, &weldop);
+       BMO_Finish_Op(bm, &weldop);
 }
 
 void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
 {
        BMOperator weldop;
        BMWalker walker;
-       BMOIter siter;
-       BMIter iter, liter, liter2;
-       BMVert *v;
+       BMIter iter;
        BMEdge *e, **edges = NULL;
        V_DECLARE(edges);
        float min[3], max[3];
@@ -276,11 +379,9 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
 /*uv collapse function*/
 void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
 {
-       BMIter iter, liter, liter2;
+       BMIter iter, liter;
        BMFace *f;
        BMLoop *l, *l2;
-       BMEdge *e;
-       BMVert *v;
        BMWalker walker;
        void **blocks = NULL;
        V_DECLARE(blocks);
index 4f8c55e3119fbfa7bbdf44beacdcf8a38234ef07..59ff6b389ba08ee7f440cd7a1faa13f2fe7ced8c 100644 (file)
@@ -1632,7 +1632,6 @@ static int edge_rotate_selected(bContext *C, wmOperator *op)
        Object *obedit= CTX_data_edit_object(C);
        BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
        BMOperator bmop;
-       BMOIter siter;
        BMEdge *eed;
        BMIter iter;
        int ccw = RNA_int_get(op->ptr, "direction") == 1; // direction == 2 when clockwise and ==1 for counter CW.
@@ -2423,3 +2422,179 @@ void MESH_OT_colors_mirror(wmOperatorType *ot)
        /* props */
        RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
 }
+
+
+static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *wmop)
+{
+       BMVert *mergevert;
+       BMEditSelection *ese;
+
+       /* do sanity check in mergemenu in edit.c ?*/
+       if(first == 0){
+               ese = em->bm->selected.last;
+               mergevert= (BMVert*)ese->data;
+       }
+       else{
+               ese = em->bm->selected.first;
+               mergevert = (BMVert*)ese->data;
+       }
+
+       if (!BM_TestHFlag(mergevert, BM_SELECT))
+               return OPERATOR_CANCELLED;
+       
+       if (uvmerge) {
+               if (!EDBM_CallOpf(em, wmop, "pointmerge_facedata verts=%hv snapv=%e", BM_SELECT, mergevert))
+                       return OPERATOR_CANCELLED;
+       }
+
+       if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, mergevert->co))
+               return OPERATOR_CANCELLED;
+
+       return OPERATOR_FINISHED;
+}
+
+static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d, 
+                        int target, int uvmerge, wmOperator *wmop)
+{
+       BMIter iter;
+       BMVert *v;
+       float *co, cent[3] = {0.0f, 0.0f, 0.0f}, fac;
+       int i;
+
+       if (target) {
+               co = give_cursor(scene, v3d);
+       } else {
+               i = 0;
+               BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
+                       if (!BM_TestHFlag(v, BM_SELECT))
+                               continue;
+                       VECADD(cent, cent, v->co);
+                       i++;
+               }
+               
+               if (!i)
+                       return OPERATOR_CANCELLED;
+
+               fac = 1.0f / (float)i;
+               VECMUL(cent, fac);
+               co = cent;
+       }
+
+       if (!co)
+               return OPERATOR_CANCELLED;
+       
+       if (uvmerge) {
+               if (!EDBM_CallOpf(em, wmop, "vert_average_facedata verts=%hv", BM_SELECT))
+                       return OPERATOR_CANCELLED;
+       }
+
+       if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, co))
+               return OPERATOR_CANCELLED;
+
+       return OPERATOR_FINISHED;
+}
+
+static int merge_exec(bContext *C, wmOperator *op)
+{
+       Scene *scene= CTX_data_scene(C);
+       View3D *v3d = CTX_wm_view3d(C);
+       Object *obedit= CTX_data_edit_object(C);
+       BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
+       int status= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
+
+       switch(RNA_enum_get(op->ptr, "type")) {
+               case 3:
+                       status = merge_target(em, scene, v3d, 0, uvs, op);
+                       break;
+               case 4:
+                       status = merge_target(em, scene, v3d, 1, uvs, op);
+                       break;
+               case 1:
+                       status = merge_firstlast(em, 0, uvs, op);
+                       break;
+               case 6:
+                       status = merge_firstlast(em, 1, uvs, op);
+                       break;
+               case 5:
+                       status = 1;
+                       if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
+                               status = 0;
+                       break;
+       }
+
+       if(!status)
+               return OPERATOR_CANCELLED;
+
+       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
+       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
+
+       return OPERATOR_FINISHED;
+}
+
+static EnumPropertyItem merge_type_items[]= {
+       {6, "FIRST", 0, "At First", ""},
+       {1, "LAST", 0, "At Last", ""},
+       {3, "CENTER", 0, "At Center", ""},
+       {4, "CURSOR", 0, "At Cursor", ""},
+       {5, "COLLAPSE", 0, "Collapse", ""},
+       {0, NULL, 0, NULL, NULL}};
+
+static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
+{      
+       Object *obedit;
+       EnumPropertyItem *item= NULL;
+       int totitem= 0;
+       
+       if(!C) /* needed for docs */
+               return merge_type_items;
+       
+       obedit= CTX_data_edit_object(C);
+       if(obedit && obedit->type == OB_MESH) {
+               BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
+
+               if(em->selectmode & SCE_SELECT_VERTEX) {
+                       if(em->bm->selected.first && em->bm->selected.last &&
+                               ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT) {
+                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
+                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+                       }
+                       else if(em->bm->selected.first && ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT)
+                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
+                       else if(em->bm->selected.last && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT)
+                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
+               }
+
+               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
+               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
+               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
+               RNA_enum_item_end(&item, &totitem);
+
+               *free= 1;
+
+               return item;
+       }
+       
+       return NULL;
+}
+
+void MESH_OT_merge(wmOperatorType *ot)
+{
+       PropertyRNA *prop;
+
+       /* identifiers */
+       ot->name= "Merge";
+       ot->idname= "MESH_OT_merge";
+
+       /* api callbacks */
+       ot->exec= merge_exec;
+       ot->invoke= WM_menu_invoke;
+       ot->poll= ED_operator_editmesh;
+
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+       /* properties */
+       prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
+       RNA_def_enum_funcs(prop, merge_type_itemf);
+       RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge.");
+}
index 10e85166d05c19a7314e30531a0c03fc717cc093..0729d139fb65e81408840fca6cc8c3e3e4907b5d 100644 (file)
@@ -5417,164 +5417,6 @@ int collapseEdges(EditMesh *em)
        return mergecount;
 }
 
-int merge_firstlast(EditMesh *em, int first, int uvmerge)
-{
-       EditVert *eve,*mergevert;
-       EditSelection *ese;
-
-       /* do sanity check in mergemenu in edit.c ?*/
-       if(first == 0){
-               ese = em->selected.last;
-               mergevert= (EditVert*)ese->data;
-       }
-       else{
-               ese = em->selected.first;
-               mergevert = (EditVert*)ese->data;
-       }
-
-       if(mergevert->f&SELECT){
-               for (eve=em->verts.first; eve; eve=eve->next){
-                       if (eve->f&SELECT)
-                       VECCOPY(eve->co,mergevert->co);
-               }
-       }
-
-       if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
-
-               for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
-               for(eve=em->verts.first; eve; eve=eve->next){
-                       if(eve->f&SELECT) eve->f1 = 1;
-               }
-               collapseuvs(em, mergevert);
-       }
-
-       return removedoublesflag(em, 1, 0, MERGELIMIT);
-}
-
-int merge_target(EditMesh *em, int target, int uvmerge)
-{
-       EditVert *eve;
-
-       // XXX not working
-       if(target) snap_sel_to_curs();
-       else snap_to_center();
-
-       if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
-               for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
-               for(eve=em->verts.first; eve; eve=eve->next){
-                               if(eve->f&SELECT) eve->f1 = 1;
-               }
-               collapseuvs(em, NULL);
-       }
-
-       return removedoublesflag(em, 1, 0, MERGELIMIT);
-}
-#undef MERGELIMIT
-
-static int merge_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);
-       int count= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
-
-       switch(RNA_enum_get(op->ptr, "type")) {
-               case 3:
-                       count = merge_target(em, 0, uvs);
-                       break;
-               case 4:
-                       count = merge_target(em, 1, uvs);
-                       break;
-               case 1:
-                       count = merge_firstlast(em, 0, uvs);
-                       break;
-               case 6:
-                       count = merge_firstlast(em, 1, uvs);
-                       break;
-               case 2:
-                       count = collapseEdges(em);
-                       break;
-       }
-
-       if(!count)
-               return OPERATOR_CANCELLED;
-
-       BKE_mesh_end_editmesh(obedit->data, em);
-
-       DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
-       WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
-
-       return OPERATOR_FINISHED;
-}
-
-static EnumPropertyItem merge_type_items[]= {
-       {6, "FIRST", 0, "At First", ""},
-       {1, "LAST", 0, "At Last", ""},
-       {3, "CENTER", 0, "At Center", ""},
-       {4, "CURSOR", 0, "At Cursor", ""},
-       {5, "COLLAPSE", 0, "Collapse", ""},
-       {0, NULL, 0, NULL, NULL}};
-
-static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
-{      
-       Object *obedit;
-       EnumPropertyItem *item= NULL;
-       int totitem= 0;
-       
-       if(!C) /* needed for docs */
-               return merge_type_items;
-       
-       obedit= CTX_data_edit_object(C);
-       if(obedit && obedit->type == OB_MESH) {
-               EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
-
-               if(em->selectmode & SCE_SELECT_VERTEX) {
-                       if(em->selected.first && em->selected.last &&
-                               ((EditSelection*)em->selected.first)->type == EDITVERT && ((EditSelection*)em->selected.last)->type == EDITVERT) {
-                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
-                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
-                       }
-                       else if(em->selected.first && ((EditSelection*)em->selected.first)->type == EDITVERT)
-                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
-                       else if(em->selected.last && ((EditSelection*)em->selected.last)->type == EDITVERT)
-                               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
-               }
-
-               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
-               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
-               RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
-               RNA_enum_item_end(&item, &totitem);
-
-               *free= 1;
-
-               return item;
-       }
-       
-       return NULL;
-}
-
-void MESH_OT_merge(wmOperatorType *ot)
-{
-       PropertyRNA *prop;
-
-       /* identifiers */
-       ot->name= "Merge";
-       ot->idname= "MESH_OT_merge";
-
-       /* api callbacks */
-       ot->exec= merge_exec;
-       ot->invoke= WM_menu_invoke;
-       ot->poll= ED_operator_editmesh;
-
-       /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
-       /* properties */
-       prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
-       RNA_def_enum_funcs(prop, merge_type_itemf);
-       RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge.");
-}
-
 /************************ Vertex Path Operator *************************/
 
 typedef struct PathNode {