merge with trunk at r31523
[blender.git] / source / blender / editors / space_view3d / view3d_snap.c
index a4e893a61813e056fafdd5d69d7c834caed29338..48e38c6c419aa54d0ef3537c25225525ae83b203 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * $Id$
+ * $Id: view3d_snap.c 18967 2009-02-14 13:07:09Z ton $
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
 
 #include "MEM_guardedalloc.h"
 
+#include "DNA_action_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_curve_types.h"
+#include "DNA_group_types.h"
+#include "DNA_ipo_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_view3d_types.h"
 #include "DNA_object_types.h"
 
 #include "BLI_blenlib.h"
 #include "BKE_lattice.h"
 #include "BKE_main.h"
 #include "BKE_object.h"
+#include "BKE_tessmesh.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "RNA_access.h"
+#include "RNA_define.h"
 
+#include "UI_interface.h"
 
+#include "ED_anim_api.h"
 #include "ED_armature.h"
 #include "ED_mesh.h"
 #include "ED_screen.h"
+#include "ED_view3d.h"
 #include "ED_curve.h" /* for ED_curve_editnurbs */
 
 #include "view3d_intern.h"
@@ -88,10 +103,10 @@ static void special_transvert_update(Scene *scene, Object *obedit)
        if(obedit) {
                
                DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
-               
+
                if(obedit->type==OB_MESH) {
                        Mesh *me= obedit->data;
-                       recalc_editnormals(me->edit_mesh);      // does face centers too
+                       BM_Compute_Normals(me->edit_btmesh->bm);        // does face centers too
                }
                else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
                        Curve *cu= obedit->data;
@@ -118,7 +133,7 @@ static void special_transvert_update(Scene *scene, Object *obedit)
                                                float diffvec[3];
                                                
                                                sub_v3_v3v3(diffvec, tv->loc, tv->oldloc);
-                                               add_v3_v3(ebo->tail, diffvec);
+                                               add_v3_v3v3(ebo->tail, ebo->tail, diffvec);
                                                
                                                a++;
                                                if (a<tottrans) tv++;
@@ -160,7 +175,8 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
        BPoint *bp;
        TransVert *tv=NULL;
        MetaElem *ml;
-       EditVert *eve;
+       BMVert *eve;
+       BMIter iter;
        EditBone        *ebo;
        float total, center[3], centroid[3];
        int a;
@@ -172,45 +188,62 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
        
        if(obedit->type==OB_MESH) {
                Mesh *me= obedit->data;
-               EditMesh *em= me->edit_mesh;
+               BMEditMesh *em= me->edit_btmesh;
+               BMesh *bm = em->bm;
                int proptrans= 0;
                
                // transform now requires awareness for select mode, so we tag the f1 flags in verts
                tottrans= 0;
-               if(em->selectmode & SCE_SELECT_VERTEX) {
-                       for(eve= em->verts.first; eve; eve= eve->next) {
-                               if(eve->h==0 && (eve->f & SELECT)) {
-                                       eve->f1= SELECT;
+               if(em->bm->selectmode & SCE_SELECT_VERTEX) {
+                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+                               if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) {
+                                       BMINDEX_SET(eve, 1);
                                        tottrans++;
                                }
-                               else eve->f1= 0;
+                               else BMINDEX_SET(eve, 0);
                        }
                }
-               else if(em->selectmode & SCE_SELECT_EDGE) {
-                       EditEdge *eed;
-                       for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
-                       for(eed= em->edges.first; eed; eed= eed->next) {
-                               if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
+               else if(em->bm->selectmode & SCE_SELECT_EDGE) {
+                       BMEdge *eed;
+
+                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+                               BMINDEX_SET(eve, 0);
+
+                       BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
+                               if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT))
+                                       BMINDEX_SET(eed->v1, 1), BMINDEX_SET(eed->v2, 1);
                        }
-                       for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+
+                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+                               if(BMINDEX_GET(eve)) tottrans++;
                }
                else {
-                       EditFace *efa;
-                       for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
-                       for(efa= em->faces.first; efa; efa= efa->next) {
-                               if(efa->h==0 && (efa->f & SELECT)) {
-                                       efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
-                                       if(efa->v4) efa->v4->f1= SELECT;
+                       BMFace *efa;
+
+                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+                               BMINDEX_SET(eve, 0);
+
+                       BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
+                               if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) {
+                                       BMIter liter;
+                                       BMLoop *l;
+                                       
+                                       BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
+                                               BMINDEX_SET(l->v, 1);
+                                       }
                                }
                        }
-                       for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
+
+                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
+                               if(BMINDEX_GET(eve)) tottrans++;
                }
                
                /* proportional edit exception... */
                if((mode & 1) && tottrans) {
-                       for(eve= em->verts.first; eve; eve= eve->next) {
-                               if(eve->h==0) {
-                                       eve->f1 |= 2;
+                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+                               if(BMINDEX_GET(eve)) tottrans++;
+                               if(!BM_TestHFlag(eve, BM_HIDDEN)) {
+                                       BMINDEX_SET(eve, BMINDEX_GET(eve)|2);
                                        proptrans++;
                                }
                        }
@@ -221,13 +254,13 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
                if(tottrans) {
                        tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
 
-                       for(eve= em->verts.first; eve; eve= eve->next) {
-                               if(eve->f1) {
+                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+                               if(BMINDEX_GET(eve)) {
                                        VECCOPY(tv->oldloc, eve->co);
                                        tv->loc= eve->co;
                                        if(eve->no[0]!=0.0 || eve->no[1]!=0.0 ||eve->no[2]!=0.0)
                                                tv->nor= eve->no; // note this is a hackish signal (ton)
-                                       tv->flag= eve->f1 & SELECT;
+                                       tv->flag= BMINDEX_GET(eve) & SELECT;
                                        tv++;
                                }
                        }
@@ -287,7 +320,7 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
                ListBase *nurbs= ED_curve_editnurbs(cu);
 
                for(nu= nurbs->first; nu; nu= nu->next) {
-                       if(nu->type == CU_BEZIER)
+                       if((nu->type & 7)==CU_BEZIER)
                                totmalloc += 3*nu->pntsu;
                        else
                                totmalloc += nu->pntsu*nu->pntsv;
@@ -296,7 +329,7 @@ static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
 
                nu= nurbs->first;
                while(nu) {
-                       if(nu->type == CU_BEZIER) {
+                       if((nu->type & 7)==CU_BEZIER) {
                                a= nu->pntsu;
                                bezt= nu->bezt;
                                while(a--) {
@@ -439,11 +472,11 @@ static int snap_sel_to_grid(bContext *C, wmOperator *op)
                        
                        VECCOPY(vec, tv->loc);
                        mul_m3_v3(bmat, vec);
-                       add_v3_v3(vec, obedit->obmat[3]);
+                       add_v3_v3v3(vec, vec, obedit->obmat[3]);
                        vec[0]= gridf*floor(.5+ vec[0]/gridf);
                        vec[1]= gridf*floor(.5+ vec[1]/gridf);
                        vec[2]= gridf*floor(.5+ vec[2]/gridf);
-                       sub_v3_v3(vec, obedit->obmat[3]);
+                       sub_v3_v3v3(vec, vec, obedit->obmat[3]);
                        
                        mul_m3_v3(imat, vec);
                        VECCOPY(tv->loc, vec);
@@ -490,7 +523,7 @@ static int snap_sel_to_grid(bContext *C, wmOperator *op)
                                
                                /* auto-keyframing */
 // XXX                         autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
-                               DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                               DAG_id_flush_update(ob->data, OB_RECALC_DATA);
                        }
                        else {
                                ob->recalc |= OB_RECALC_OB;
@@ -532,7 +565,6 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
        
        /* identifiers */
        ot->name= "Snap Selection to Grid";
-       ot->description= "Snap selected item(s) to nearest grid node";
        ot->idname= "VIEW3D_OT_snap_selected_to_grid";
        
        /* api callbacks */
@@ -617,7 +649,7 @@ static int snap_sel_to_curs(bContext *C, wmOperator *op)
                                
                                /* auto-keyframing */
 // XXX                         autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
-                               DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+                               DAG_id_flush_update(ob->data, OB_RECALC_DATA);
                        }
                        else {
                                ob->recalc |= OB_RECALC_OB;
@@ -658,7 +690,6 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
        
        /* identifiers */
        ot->name= "Snap Selection to Cursor";
-       ot->description= "Snap selected item(s) to cursor";
        ot->idname= "VIEW3D_OT_snap_selected_to_cursor";
        
        /* api callbacks */
@@ -695,7 +726,6 @@ void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
        
        /* identifiers */
        ot->name= "Snap Cursor to Grid";
-       ot->description= "Snap cursor to nearest grid node";
        ot->idname= "VIEW3D_OT_snap_cursor_to_grid";
        
        /* api callbacks */
@@ -736,8 +766,8 @@ static int snap_curs_to_sel(bContext *C, wmOperator *op)
                for(a=0; a<tottrans; a++, tv++) {
                        VECCOPY(vec, tv->loc);
                        mul_m3_v3(bmat, vec);
-                       add_v3_v3(vec, obedit->obmat[3]);
-                       add_v3_v3(centroid, vec);
+                       add_v3_v3v3(vec, vec, obedit->obmat[3]);
+                       add_v3_v3v3(centroid, centroid, vec);
                        DO_MINMAX(vec, min, max);
                }
                
@@ -764,7 +794,7 @@ static int snap_curs_to_sel(bContext *C, wmOperator *op)
                                        if(pchan->bone->flag & BONE_SELECTED) {
                                                VECCOPY(vec, pchan->pose_head);
                                                mul_m4_v3(ob->obmat, vec);
-                                               add_v3_v3(centroid, vec);
+                                               add_v3_v3v3(centroid, centroid, vec);
                                                DO_MINMAX(vec, min, max);
                                                count++;
                                        }
@@ -772,9 +802,9 @@ static int snap_curs_to_sel(bContext *C, wmOperator *op)
                        }
                }
                else {
-                       CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
+                       CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
                                VECCOPY(vec, ob->obmat[3]);
-                               add_v3_v3(centroid, vec);
+                               add_v3_v3v3(centroid, centroid, vec);
                                DO_MINMAX(vec, min, max);
                                count++;
                        }
@@ -802,7 +832,6 @@ void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
        
        /* identifiers */
        ot->name= "Snap Cursor to Selected";
-       ot->description= "Snap cursor to center of selected item(s)"; 
        ot->idname= "VIEW3D_OT_snap_cursor_to_selected";
        
        /* api callbacks */
@@ -829,10 +858,10 @@ static int snap_curs_to_active(bContext *C, wmOperator *op)
                if (obedit->type == OB_MESH) {
                        /* check active */
                        Mesh *me= obedit->data;
-                       EditSelection ese;
+                       BMEditSelection ese;
                        
-                       if (EM_get_actSelection(me->edit_mesh, &ese)) {
-                               EM_editselection_center(curs, &ese);
+                       if (EDBM_get_actSelection(me->edit_btmesh, &ese)) {
+                               EDBM_editselection_center(me->edit_btmesh, curs, &ese);
                        }
                        
                        mul_m4_v3(obedit->obmat, curs);
@@ -853,7 +882,6 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
        
        /* identifiers */
        ot->name= "Snap Cursor to Active";
-       ot->description= "Snap cursor to active item";
        ot->idname= "VIEW3D_OT_snap_cursor_to_active";
        
        /* api callbacks */
@@ -864,24 +892,221 @@ void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
-/* **************************************************** */
-/*New Code - Snap Cursor to Center -*/
-static int snap_curs_to_center(bContext *C, wmOperator *op)
+/* ************************************** */
+
+static int snap_selected_to_center(bContext *C, wmOperator *op)
 {
+       extern float originmat[3][3];   /* XXX object.c */
+       Object *obedit= CTX_data_edit_object(C);
        Scene *scene= CTX_data_scene(C);
        View3D *v3d= CTX_wm_view3d(C);
-       float *curs;
-       curs= give_cursor(scene, v3d);
+       TransVert *tv;
+       float snaploc[3], imat[3][3], bmat[3][3], vec[3], min[3], max[3], centroid[3];
+       int count, a;
+
+       /*calculate the snaplocation (centerpoint) */
+       count= 0;
+       INIT_MINMAX(min, max);
+       centroid[0]= centroid[1]= centroid[2]= 0.0f;
+       snaploc[0]= snaploc[1]= snaploc[2]= 0.0f;
 
-       curs[0]= 0.0;
-       curs[1]= 0.0;
-       curs[2]= 0.0;
+       if(obedit) {
+               tottrans= 0;
+               
+               if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
+                       make_trans_verts(obedit, bmat[0], bmat[1], 0);
+               if(tottrans==0) return OPERATOR_CANCELLED;
+               
+               copy_m3_m4(bmat, obedit->obmat);
+               invert_m3_m3(imat, bmat);
+               
+               tv= transvmain;
+               for(a=0; a<tottrans; a++, tv++) {
+                       VECCOPY(vec, tv->loc);
+                       mul_m3_v3(bmat, vec);
+                       add_v3_v3v3(vec, vec, obedit->obmat[3]);
+                       add_v3_v3v3(centroid, centroid, vec);
+                       DO_MINMAX(vec, min, max);
+               }
+               
+               if(v3d->around==V3D_CENTROID) {
+                       mul_v3_fl(centroid, 1.0/(float)tottrans);
+                       VECCOPY(snaploc, centroid);
+               }
+               else {
+                       snaploc[0]= (min[0]+max[0])/2;
+                       snaploc[1]= (min[1]+max[1])/2;
+                       snaploc[2]= (min[2]+max[2])/2;
+               }
+               
+               MEM_freeN(transvmain);
+               transvmain= NULL;
+       }
+       else {
+               
+               CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+                       if(ob->mode & OB_MODE_POSE) {
+                               bPoseChannel *pchan;
+                               bArmature *arm= ob->data;
+                               
+                               for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+                                       if(pchan->bone->flag & BONE_SELECTED) {
+                                               if(pchan->bone->layer & arm->layer) {
+                                                       VECCOPY(vec, pchan->pose_mat[3]);
+                                                       add_v3_v3v3(centroid, centroid, vec);
+                                                       DO_MINMAX(vec, min, max);
+                                                       count++;
+                                               }
+                                       }
+                               }
+                       }
+                       else {
+                               /* not armature bones (i.e. objects) */
+                               VECCOPY(vec, ob->obmat[3]);
+                               add_v3_v3v3(centroid, centroid, vec);
+                               DO_MINMAX(vec, min, max);
+                               count++;
+                       }
+               }
+               CTX_DATA_END;
+
+               if(count) {
+                       if(v3d->around==V3D_CENTROID) {
+                               mul_v3_fl(centroid, 1.0/(float)count);
+                               VECCOPY(snaploc, centroid);
+                       }
+                       else {
+                               snaploc[0]= (min[0]+max[0])/2;
+                               snaploc[1]= (min[1]+max[1])/2;
+                               snaploc[2]= (min[2]+max[2])/2;
+                       }
+               }
+       }
+
+       /* Snap the selection to the snaplocation (duh!) */
+       if(obedit) {
+               tottrans= 0;
+               
+               if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
+                       make_trans_verts(obedit, bmat[0], bmat[1], 0);
+               if(tottrans==0) return OPERATOR_CANCELLED;
+               
+               copy_m3_m4(bmat, obedit->obmat);
+               invert_m3_m3(imat, bmat);
+               
+               tv= transvmain;
+               for(a=0; a<tottrans; a++, tv++) {
+                       vec[0]= snaploc[0]-obedit->obmat[3][0];
+                       vec[1]= snaploc[1]-obedit->obmat[3][1];
+                       vec[2]= snaploc[2]-obedit->obmat[3][2];
+                       
+                       mul_m3_v3(imat, vec);
+                       VECCOPY(tv->loc, vec);
+               }
+               
+               special_transvert_update(scene, obedit);
+               
+               MEM_freeN(transvmain);
+               transvmain= NULL;
+               
+       }
+       else {
+
+               CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
+                       if(ob->mode & OB_MODE_POSE) {
+                               bPoseChannel *pchan;
+                               bArmature *arm= ob->data;
+                               
+                               for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+                                       if(pchan->bone->flag & BONE_SELECTED) {
+                                               if(pchan->bone->layer & arm->layer) {
+                                                       if((pchan->bone->flag & BONE_CONNECTED)==0) { 
+                                                               /* get location of cursor in bone-space */
+                                                               armature_loc_pose_to_bone(pchan, snaploc, vec);
+                                                               
+                                                               /* calculate new position */
+                                                               VECCOPY(pchan->loc, vec);
+                                                       }
+                                                       /* if the bone has a parent and is connected to the parent, 
+                                                        * don't do anything - will break chain unless we do auto-ik. 
+                                                        */
+                                               }
+                                       }
+                               }
+                               
+                               /* auto-keyframing */
+                               ob->pose->flag |= POSE_DO_UNLOCK;
+// XXX                         autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
+                               DAG_id_flush_update(ob->data, OB_RECALC_DATA);
+                       }
+                       else {
+                               ob->recalc |= OB_RECALC_OB;
+                               
+                               vec[0]= -ob->obmat[3][0] + snaploc[0];
+                               vec[1]= -ob->obmat[3][1] + snaploc[1];
+                               vec[2]= -ob->obmat[3][2] + snaploc[2];
+                               
+                               if(ob->parent) {
+                                       where_is_object(scene, ob);
+                                       
+                                       invert_m3_m3(imat, originmat);
+                                       mul_m3_v3(imat, vec);
+                                       ob->loc[0]+= vec[0];
+                                       ob->loc[1]+= vec[1];
+                                       ob->loc[2]+= vec[2];
+                               }
+                               else {
+                                       ob->loc[0]+= vec[0];
+                                       ob->loc[1]+= vec[1];
+                                       ob->loc[2]+= vec[2];
+                               }
+                               /* auto-keyframing */
+// XXX                         autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
+                       }
+               }
+               CTX_DATA_END;
+       }
        
-       WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
+       DAG_ids_flush_update(CTX_data_main(C), 0);
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
        
        return OPERATOR_FINISHED;
 }
 
+void VIEW3D_OT_snap_selected_to_center(wmOperatorType *ot)
+{
+       
+       /* identifiers */
+       ot->name= "Snap Selection to Center";
+       ot->idname= "VIEW3D_OT_snap_selected_to_center";
+       
+       /* api callbacks */
+       ot->exec= snap_selected_to_center;
+       ot->poll= ED_operator_view3d_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+
+/* **************************************************** */
+/*New Code - Snap Cursor to Center -*/
+static int snap_curs_to_center(bContext *C, wmOperator *op)
+{
+    Scene *scene= CTX_data_scene(C);
+    View3D *v3d= CTX_wm_view3d(C);
+    float *curs;
+    curs= give_cursor(scene, v3d);
+
+    curs[0]= 0.0;
+    curs[1]= 0.0;
+    curs[2]= 0.0;
+       
+    WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
+       
+    return OPERATOR_FINISHED;
+}
+
 void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
 {
        
@@ -890,12 +1115,12 @@ void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
        ot->description= "Snap cursor to the Center";
        ot->idname= "VIEW3D_OT_snap_cursor_to_center";
        
-       /* api callbacks */ 
-       ot->exec= snap_curs_to_center;
-          ot->poll= ED_operator_view3d_active;
+    /* api callbacks */ 
+    ot->exec= snap_curs_to_center;
+       ot->poll= ED_operator_view3d_active;
        
-       /* flags */
-          ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+    /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
 /* **************************************************** */
@@ -919,8 +1144,8 @@ int minmax_verts(Object *obedit, float *min, float *max)
        for(a=0; a<tottrans; a++, tv++) {               
                VECCOPY(vec, tv->loc);
                mul_m3_v3(bmat, vec);
-               add_v3_v3(vec, obedit->obmat[3]);
-               add_v3_v3(centroid, vec);
+               add_v3_v3v3(vec, vec, obedit->obmat[3]);
+               add_v3_v3v3(centroid, centroid, vec);
                DO_MINMAX(vec, min, max);               
        }
        
@@ -929,4 +1154,3 @@ int minmax_verts(Object *obedit, float *min, float *max)
        
        return 1;
 }
-