Blender V2.61 - r43446

view3d_snap.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <math.h>
00034 #include <string.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "DNA_armature_types.h"
00039 #include "DNA_curve_types.h"
00040 #include "DNA_lattice_types.h"
00041 #include "DNA_meta_types.h"
00042 #include "DNA_scene_types.h"
00043 #include "DNA_object_types.h"
00044 
00045 #include "BLI_blenlib.h"
00046 #include "BLI_math.h"
00047 #include "BLI_editVert.h"
00048 #include "BLI_linklist.h"
00049 #include "BLI_utildefines.h"
00050 
00051 #include "BKE_armature.h"
00052 #include "BKE_context.h"
00053 #include "BKE_curve.h"
00054 #include "BKE_depsgraph.h"
00055 #include "BKE_lattice.h"
00056 #include "BKE_main.h"
00057 #include "BKE_object.h"
00058 #include "BKE_scene.h"
00059 #include "BKE_tracking.h"
00060 
00061 #include "WM_api.h"
00062 #include "WM_types.h"
00063 
00064 
00065 
00066 #include "ED_armature.h"
00067 #include "ED_mesh.h"
00068 #include "ED_keyframing.h"
00069 #include "ED_screen.h"
00070 #include "ED_curve.h" /* for curve_editnurbs */
00071 
00072 #include "view3d_intern.h"
00073 
00074 extern float originmat[3][3];   /* XXX object.c */
00075 
00076 /* ************************************************** */
00077 /* ********************* old transform stuff ******** */
00078 /* *********** will get replaced with new transform * */
00079 /* ************************************************** */
00080 
00081 typedef struct TransVert {
00082     float *loc;
00083     float oldloc[3], fac;
00084     float *val, oldval;
00085     int flag;
00086     float *nor;
00087 } TransVert;
00088 
00089 static TransVert *transvmain=NULL;
00090 static int tottrans= 0;
00091 
00092 /* copied from editobject.c, now uses (almost) proper depgraph */
00093 static void special_transvert_update(Object *obedit)
00094 {
00095     if(obedit) {
00096         DAG_id_tag_update(obedit->data, 0);
00097         
00098         if(obedit->type==OB_MESH) {
00099             Mesh *me= obedit->data;
00100             recalc_editnormals(me->edit_mesh);  // does face centers too
00101         }
00102         else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
00103             Curve *cu= obedit->data;
00104             ListBase *nurbs= curve_editnurbs(cu);
00105             Nurb *nu= nurbs->first;
00106 
00107             while(nu) {
00108                 /* keep handles' vectors unchanged */
00109                 if(nu->bezt) {
00110                     int a= nu->pntsu;
00111                     TransVert *tv= transvmain;
00112                     BezTriple *bezt= nu->bezt;
00113 
00114                     while(a--) {
00115                         if(bezt->f1 & SELECT) tv++;
00116 
00117                         if(bezt->f2 & SELECT) {
00118                             float v[3];
00119 
00120                             if(bezt->f1 & SELECT) {
00121                                 sub_v3_v3v3(v, (tv-1)->oldloc, tv->oldloc);
00122                                 add_v3_v3v3(bezt->vec[0], bezt->vec[1], v);
00123                             }
00124 
00125                             if(bezt->f3 & SELECT) {
00126                                 sub_v3_v3v3(v, (tv+1)->oldloc, tv->oldloc);
00127                                 add_v3_v3v3(bezt->vec[2], bezt->vec[1], v);
00128                             }
00129 
00130                             tv++;
00131                         }
00132 
00133                         if(bezt->f3 & SELECT) tv++;
00134 
00135                         bezt++;
00136                     }
00137                 }
00138 
00139                 test2DNurb(nu);
00140                 testhandlesNurb(nu); /* test for bezier too */
00141                 nu= nu->next;
00142             }
00143         }
00144         else if(obedit->type==OB_ARMATURE){
00145             bArmature *arm= obedit->data;
00146             EditBone *ebo;
00147             TransVert *tv= transvmain;
00148             int a=0;
00149             
00150             /* Ensure all bone tails are correctly adjusted */
00151             for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
00152                 /* adjust tip if both ends selected */
00153                 if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
00154                     if (tv) {
00155                         float diffvec[3];
00156                         
00157                         sub_v3_v3v3(diffvec, tv->loc, tv->oldloc);
00158                         add_v3_v3(ebo->tail, diffvec);
00159                         
00160                         a++;
00161                         if (a<tottrans) tv++;
00162                     }
00163                 }
00164             }
00165             
00166             /* Ensure all bones are correctly adjusted */
00167             for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
00168                 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
00169                     /* If this bone has a parent tip that has been moved */
00170                     if (ebo->parent->flag & BONE_TIPSEL){
00171                         copy_v3_v3(ebo->head, ebo->parent->tail);
00172                     }
00173                     /* If this bone has a parent tip that has NOT been moved */
00174                     else{
00175                         copy_v3_v3(ebo->parent->tail, ebo->head);
00176                     }
00177                 }
00178             }
00179             if(arm->flag & ARM_MIRROR_EDIT)
00180                 transform_armature_mirror_update(obedit);
00181         }
00182         else if(obedit->type==OB_LATTICE) {
00183             Lattice *lt= obedit->data;
00184             
00185             if(lt->editlatt->latt->flag & LT_OUTSIDE)
00186                 outside_lattice(lt->editlatt->latt);
00187         }
00188     }
00189 }
00190 
00191 /* copied from editobject.c, needs to be replaced with new transform code still */
00192 /* mode flags: */
00193 #define TM_ALL_JOINTS       1 /* all joints (for bones only) */
00194 #define TM_SKIP_HANDLES     2 /* skip handles when control point is selected (for curves only) */
00195 static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
00196 {
00197     Nurb *nu;
00198     BezTriple *bezt;
00199     BPoint *bp;
00200     TransVert *tv=NULL;
00201     MetaElem *ml;
00202     EditVert *eve;
00203     EditBone    *ebo;
00204     float total, center[3], centroid[3];
00205     int a;
00206 
00207     tottrans= 0; // global!
00208     
00209     INIT_MINMAX(min, max);
00210     centroid[0]=centroid[1]=centroid[2]= 0.0;
00211     
00212     if(obedit->type==OB_MESH) {
00213         Mesh *me= obedit->data;
00214         EditMesh *em= me->edit_mesh;
00215         
00216         // transform now requires awareness for select mode, so we tag the f1 flags in verts
00217         tottrans= 0;
00218         if(em->selectmode & SCE_SELECT_VERTEX) {
00219             for(eve= em->verts.first; eve; eve= eve->next) {
00220                 if(eve->h==0 && (eve->f & SELECT)) {
00221                     eve->f1= SELECT;
00222                     tottrans++;
00223                 }
00224                 else eve->f1= 0;
00225             }
00226         }
00227         else if(em->selectmode & SCE_SELECT_EDGE) {
00228             EditEdge *eed;
00229             for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
00230             for(eed= em->edges.first; eed; eed= eed->next) {
00231                 if(eed->h==0 && (eed->f & SELECT)) eed->v1->f1= eed->v2->f1= SELECT;
00232             }
00233             for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
00234         }
00235         else {
00236             EditFace *efa;
00237             for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
00238             for(efa= em->faces.first; efa; efa= efa->next) {
00239                 if(efa->h==0 && (efa->f & SELECT)) {
00240                     efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
00241                     if(efa->v4) efa->v4->f1= SELECT;
00242                 }
00243             }
00244             for(eve= em->verts.first; eve; eve= eve->next) if(eve->f1) tottrans++;
00245         }
00246         
00247         /* and now make transverts */
00248         if(tottrans) {
00249             tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
00250 
00251             for(eve= em->verts.first; eve; eve= eve->next) {
00252                 if(eve->f1) {
00253                     copy_v3_v3(tv->oldloc, eve->co);
00254                     tv->loc= eve->co;
00255                     if(eve->no[0] != 0.0f || eve->no[1] != 0.0f ||eve->no[2] != 0.0f)
00256                         tv->nor= eve->no; // note this is a hackish signal (ton)
00257                     tv->flag= eve->f1 & SELECT;
00258                     tv++;
00259                 }
00260             }
00261         }
00262     }
00263     else if (obedit->type==OB_ARMATURE){
00264         bArmature *arm= obedit->data;
00265         int totmalloc= BLI_countlist(arm->edbo);
00266 
00267         totmalloc *= 2;  /* probably overkill but bones can have 2 trans verts each */
00268 
00269         tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts armature");
00270         
00271         for (ebo= arm->edbo->first; ebo; ebo=ebo->next){
00272             if(ebo->layer & arm->layer) {
00273                 short tipsel= (ebo->flag & BONE_TIPSEL);
00274                 short rootsel= (ebo->flag & BONE_ROOTSEL);
00275                 short rootok= (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL));
00276                 
00277                 if ((tipsel && rootsel) || (rootsel)) {
00278                     /* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
00279                      * otherwise we get zero-length bones as tips will snap to the same
00280                      * location as heads.
00281                      */
00282                     if (rootok) {
00283                         copy_v3_v3(tv->oldloc, ebo->head);
00284                         tv->loc= ebo->head;
00285                         tv->nor= NULL;
00286                         tv->flag= 1;
00287                         tv++;
00288                         tottrans++;
00289                     }   
00290                     
00291                     if ((mode & TM_ALL_JOINTS) && (tipsel)) {
00292                         copy_v3_v3(tv->oldloc, ebo->tail);
00293                         tv->loc= ebo->tail;
00294                         tv->nor= NULL;
00295                         tv->flag= 1;
00296                         tv++;
00297                         tottrans++;
00298                     }
00299                 }
00300                 else if (tipsel) {
00301                     copy_v3_v3(tv->oldloc, ebo->tail);
00302                     tv->loc= ebo->tail;
00303                     tv->nor= NULL;
00304                     tv->flag= 1;
00305                     tv++;
00306                     tottrans++;
00307                 }
00308             }
00309         }
00310     }
00311     else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
00312         Curve *cu= obedit->data;
00313         int totmalloc= 0;
00314         ListBase *nurbs= curve_editnurbs(cu);
00315 
00316         for(nu= nurbs->first; nu; nu= nu->next) {
00317             if(nu->type == CU_BEZIER)
00318                 totmalloc += 3*nu->pntsu;
00319             else
00320                 totmalloc += nu->pntsu*nu->pntsv;
00321         }
00322         tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts curve");
00323 
00324         nu= nurbs->first;
00325         while(nu) {
00326             if(nu->type == CU_BEZIER) {
00327                 a= nu->pntsu;
00328                 bezt= nu->bezt;
00329                 while(a--) {
00330                     if(bezt->hide==0) {
00331                         int skip_handle= 0;
00332                         if(bezt->f2 & SELECT)
00333                             skip_handle= mode & TM_SKIP_HANDLES;
00334 
00335                         if((bezt->f1 & SELECT) && !skip_handle) {
00336                             copy_v3_v3(tv->oldloc, bezt->vec[0]);
00337                             tv->loc= bezt->vec[0];
00338                             tv->flag= bezt->f1 & SELECT;
00339                             tv++;
00340                             tottrans++;
00341                         }
00342                         if(bezt->f2 & SELECT) {
00343                             copy_v3_v3(tv->oldloc, bezt->vec[1]);
00344                             tv->loc= bezt->vec[1];
00345                             tv->val= &(bezt->alfa);
00346                             tv->oldval= bezt->alfa;
00347                             tv->flag= bezt->f2 & SELECT;
00348                             tv++;
00349                             tottrans++;
00350                         }
00351                         if((bezt->f3 & SELECT) && !skip_handle) {
00352                             copy_v3_v3(tv->oldloc, bezt->vec[2]);
00353                             tv->loc= bezt->vec[2];
00354                             tv->flag= bezt->f3 & SELECT;
00355                             tv++;
00356                             tottrans++;
00357                         }
00358                     }
00359                     bezt++;
00360                 }
00361             }
00362             else {
00363                 a= nu->pntsu*nu->pntsv;
00364                 bp= nu->bp;
00365                 while(a--) {
00366                     if(bp->hide==0) {
00367                         if(bp->f1 & SELECT) {
00368                             copy_v3_v3(tv->oldloc, bp->vec);
00369                             tv->loc= bp->vec;
00370                             tv->val= &(bp->alfa);
00371                             tv->oldval= bp->alfa;
00372                             tv->flag= bp->f1 & SELECT;
00373                             tv++;
00374                             tottrans++;
00375                         }
00376                     }
00377                     bp++;
00378                 }
00379             }
00380             nu= nu->next;
00381         }
00382     }
00383     else if(obedit->type==OB_MBALL) {
00384         MetaBall *mb= obedit->data;
00385         int totmalloc= BLI_countlist(mb->editelems);
00386         
00387         tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts mball");
00388         
00389         ml= mb->editelems->first;
00390         while(ml) {
00391             if(ml->flag & SELECT) {
00392                 tv->loc= &ml->x;
00393                 copy_v3_v3(tv->oldloc, tv->loc);
00394                 tv->val= &(ml->rad);
00395                 tv->oldval= ml->rad;
00396                 tv->flag= 1;
00397                 tv++;
00398                 tottrans++;
00399             }
00400             ml= ml->next;
00401         }
00402     }
00403     else if(obedit->type==OB_LATTICE) {
00404         Lattice *lt= obedit->data;
00405         
00406         bp= lt->editlatt->latt->def;
00407         
00408         a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
00409         
00410         tv=transvmain= MEM_callocN(a*sizeof(TransVert), "maketransverts latt");
00411         
00412         while(a--) {
00413             if(bp->f1 & SELECT) {
00414                 if(bp->hide==0) {
00415                     copy_v3_v3(tv->oldloc, bp->vec);
00416                     tv->loc= bp->vec;
00417                     tv->flag= bp->f1 & SELECT;
00418                     tv++;
00419                     tottrans++;
00420                 }
00421             }
00422             bp++;
00423         }
00424     }
00425     
00426     if(!tottrans && transvmain) {
00427         /* prevent memory leak. happens for curves/latticies due to */
00428         /* difficult condition of adding points to trans data */
00429         MEM_freeN(transvmain);
00430         transvmain= NULL;
00431     }
00432 
00433     /* cent etc */
00434     tv= transvmain;
00435     total= 0.0;
00436     for(a=0; a<tottrans; a++, tv++) {
00437         if(tv->flag & SELECT) {
00438             add_v3_v3(centroid, tv->oldloc);
00439             total += 1.0f;
00440             DO_MINMAX(tv->oldloc, min, max);
00441         }
00442     }
00443     if(total != 0.0f) {
00444         mul_v3_fl(centroid, 1.0f/total);
00445     }
00446 
00447     mid_v3_v3v3(center, min, max);
00448 }
00449 
00450 /* *********************** operators ******************** */
00451 
00452 static int snap_sel_to_grid(bContext *C, wmOperator *UNUSED(op))
00453 {
00454     Main *bmain= CTX_data_main(C);
00455     Object *obedit= CTX_data_edit_object(C);
00456     Scene *scene= CTX_data_scene(C);
00457     RegionView3D *rv3d= CTX_wm_region_data(C);
00458     TransVert *tv;
00459     float gridf, imat[3][3], bmat[3][3], vec[3];
00460     int a;
00461 
00462     gridf= rv3d->gridview;
00463 
00464     if(obedit) {
00465         tottrans= 0;
00466         
00467         if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
00468             make_trans_verts(obedit, bmat[0], bmat[1], 0);
00469         if(tottrans==0) return OPERATOR_CANCELLED;
00470         
00471         copy_m3_m4(bmat, obedit->obmat);
00472         invert_m3_m3(imat, bmat);
00473         
00474         tv= transvmain;
00475         for(a=0; a<tottrans; a++, tv++) {
00476             copy_v3_v3(vec, tv->loc);
00477             mul_m3_v3(bmat, vec);
00478             add_v3_v3(vec, obedit->obmat[3]);
00479             vec[0]= gridf*floorf(0.5f+ vec[0]/gridf);
00480             vec[1]= gridf*floorf(0.5f+ vec[1]/gridf);
00481             vec[2]= gridf*floorf(0.5f+ vec[2]/gridf);
00482             sub_v3_v3(vec, obedit->obmat[3]);
00483             
00484             mul_m3_v3(imat, vec);
00485             copy_v3_v3(tv->loc, vec);
00486         }
00487         
00488         special_transvert_update(obedit);
00489         
00490         MEM_freeN(transvmain);
00491         transvmain= NULL;
00492     }
00493     else {
00494         struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
00495 
00496         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
00497             if(ob->mode & OB_MODE_POSE) {
00498                 bPoseChannel *pchan;
00499                 bArmature *arm= ob->data;
00500                 
00501                 invert_m4_m4(ob->imat, ob->obmat);
00502                 
00503                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
00504                     if(pchan->bone->flag & BONE_SELECTED) {
00505                         if(pchan->bone->layer & arm->layer) {
00506                             if((pchan->bone->flag & BONE_CONNECTED)==0) {
00507                                 float nLoc[3];
00508                                 float inv_restmat[4][4];
00509                                 
00510                                 /* get nearest grid point to snap to */
00511                                 copy_v3_v3(nLoc, pchan->pose_mat[3]);
00512                                 /* We must operate in world space! */
00513                                 mul_m4_v3(ob->obmat, nLoc);
00514                                 vec[0]= gridf * (float)(floor(0.5f+ nLoc[0]/gridf));
00515                                 vec[1]= gridf * (float)(floor(0.5f+ nLoc[1]/gridf));
00516                                 vec[2]= gridf * (float)(floor(0.5f+ nLoc[2]/gridf));
00517                                 /* Back in object space... */
00518                                 mul_m4_v3(ob->imat, vec);
00519                                 
00520                                 /* get location of grid point in *rest* bone-space */
00521                                 invert_m4_m4(inv_restmat, pchan->bone->arm_mat);
00522                                 mul_m4_v3(inv_restmat, vec);
00523                                 
00524                                 /* adjust location */
00525                                 if ((pchan->protectflag & OB_LOCK_LOCX)==0)
00526                                     pchan->loc[0]= vec[0];
00527                                 if ((pchan->protectflag & OB_LOCK_LOCY)==0)
00528                                     pchan->loc[1]= vec[1];
00529                                 if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
00530                                     pchan->loc[2]= vec[2];
00531 
00532                                 /* auto-keyframing */
00533                                 ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
00534                             }
00535                             /* if the bone has a parent and is connected to the parent,
00536                              * don't do anything - will break chain unless we do auto-ik.
00537                              */
00538                         }
00539                     }
00540                 }
00541                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
00542                 
00543                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00544             }
00545             else {
00546                 ob->recalc |= OB_RECALC_OB;
00547                 
00548                 vec[0]= -ob->obmat[3][0]+gridf*floorf(0.5f+ ob->obmat[3][0]/gridf);
00549                 vec[1]= -ob->obmat[3][1]+gridf*floorf(0.5f+ ob->obmat[3][1]/gridf);
00550                 vec[2]= -ob->obmat[3][2]+gridf*floorf(0.5f+ ob->obmat[3][2]/gridf);
00551                 
00552                 if(ob->parent) {
00553                     where_is_object(scene, ob);
00554                     
00555                     invert_m3_m3(imat, originmat);
00556                     mul_m3_v3(imat, vec);
00557                 }
00558                 if ((ob->protectflag & OB_LOCK_LOCX)==0)
00559                     ob->loc[0]+= vec[0];
00560                 if ((ob->protectflag & OB_LOCK_LOCY)==0)
00561                     ob->loc[1]+= vec[1];
00562                 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
00563                     ob->loc[2]+= vec[2];
00564                 
00565                 /* auto-keyframing */
00566                 ED_autokeyframe_object(C, scene, ob, ks);
00567             }
00568         }
00569         CTX_DATA_END;
00570     }
00571 
00572     DAG_ids_flush_update(bmain, 0);
00573     WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
00574     
00575     return OPERATOR_FINISHED;
00576 }
00577 
00578 void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
00579 {
00580     /* identifiers */
00581     ot->name= "Snap Selection to Grid";
00582     ot->description= "Snap selected item(s) to nearest grid node";
00583     ot->idname= "VIEW3D_OT_snap_selected_to_grid";
00584     
00585     /* api callbacks */
00586     ot->exec= snap_sel_to_grid;
00587     ot->poll= ED_operator_region_view3d_active;
00588     
00589     /* flags */
00590     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00591 }
00592 
00593 /* *************************************************** */
00594 
00595 static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op))
00596 {
00597     Main *bmain= CTX_data_main(C);
00598     Object *obedit= CTX_data_edit_object(C);
00599     Scene *scene= CTX_data_scene(C);
00600     View3D *v3d= CTX_wm_view3d(C);
00601     TransVert *tv;
00602     float *curs, imat[3][3], bmat[3][3], vec[3];
00603     int a;
00604 
00605     curs= give_cursor(scene, v3d);
00606 
00607     if(obedit) {
00608         tottrans= 0;
00609         
00610         if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
00611             make_trans_verts(obedit, bmat[0], bmat[1], 0);
00612         if(tottrans==0) return OPERATOR_CANCELLED;
00613         
00614         copy_m3_m4(bmat, obedit->obmat);
00615         invert_m3_m3(imat, bmat);
00616         
00617         tv= transvmain;
00618         for(a=0; a<tottrans; a++, tv++) {
00619             sub_v3_v3v3(vec, curs, obedit->obmat[3]);
00620             mul_m3_v3(imat, vec);
00621             copy_v3_v3(tv->loc, vec);
00622         }
00623         
00624         special_transvert_update(obedit);
00625         
00626         MEM_freeN(transvmain);
00627         transvmain= NULL;
00628     }
00629     else {
00630         struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
00631 
00632         CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
00633             if(ob->mode & OB_MODE_POSE) {
00634                 bPoseChannel *pchan;
00635                 bArmature *arm= ob->data;
00636                 
00637                 invert_m4_m4(ob->imat, ob->obmat);
00638                 copy_v3_v3(vec, curs);
00639                 mul_m4_v3(ob->imat, vec);
00640                 
00641                 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
00642                     if(pchan->bone->flag & BONE_SELECTED) {
00643                         if(pchan->bone->layer & arm->layer) {
00644                             if((pchan->bone->flag & BONE_CONNECTED)==0) {
00645                                 float inv_restmat[4][4];
00646                                 
00647                                 /* get location of cursor in *rest* bone-space */
00648                                 invert_m4_m4(inv_restmat, pchan->bone->arm_mat);
00649                                 mul_m4_v3(inv_restmat, vec);
00650                                 
00651                                 /* copy new position */
00652                                 if ((pchan->protectflag & OB_LOCK_LOCX)==0)
00653                                     pchan->loc[0]= vec[0];
00654                                 if ((pchan->protectflag & OB_LOCK_LOCY)==0)
00655                                     pchan->loc[1]= vec[1];
00656                                 if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
00657                                     pchan->loc[2]= vec[2];
00658 
00659                                 /* auto-keyframing */
00660                                 ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
00661                             }
00662                             /* if the bone has a parent and is connected to the parent,
00663                              * don't do anything - will break chain unless we do auto-ik.
00664                              */
00665                         }
00666                     }
00667                 }
00668                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
00669                 
00670                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00671             }
00672             else {
00673                 ob->recalc |= OB_RECALC_OB;
00674                 
00675                 vec[0]= -ob->obmat[3][0] + curs[0];
00676                 vec[1]= -ob->obmat[3][1] + curs[1];
00677                 vec[2]= -ob->obmat[3][2] + curs[2];
00678                 
00679                 if(ob->parent) {
00680                     where_is_object(scene, ob);
00681                     
00682                     invert_m3_m3(imat, originmat);
00683                     mul_m3_v3(imat, vec);
00684                 }
00685                 if ((ob->protectflag & OB_LOCK_LOCX)==0)
00686                     ob->loc[0]+= vec[0];
00687                 if ((ob->protectflag & OB_LOCK_LOCY)==0)
00688                     ob->loc[1]+= vec[1];
00689                 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
00690                     ob->loc[2]+= vec[2];
00691 
00692                 /* auto-keyframing */
00693                 ED_autokeyframe_object(C, scene, ob, ks);
00694             }
00695         }
00696         CTX_DATA_END;
00697     }
00698 
00699     DAG_ids_flush_update(bmain, 0);
00700     WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
00701     
00702     return OPERATOR_FINISHED;
00703 }
00704 
00705 void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
00706 {
00707     /* identifiers */
00708     ot->name= "Snap Selection to Cursor";
00709     ot->description= "Snap selected item(s) to cursor";
00710     ot->idname= "VIEW3D_OT_snap_selected_to_cursor";
00711     
00712     /* api callbacks */
00713     ot->exec= snap_sel_to_curs;
00714     ot->poll= ED_operator_view3d_active;
00715     
00716     /* flags */
00717     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00718 }
00719 
00720 /* *************************************************** */
00721 
00722 static int snap_curs_to_grid(bContext *C, wmOperator *UNUSED(op))
00723 {
00724     Scene *scene= CTX_data_scene(C);
00725     RegionView3D *rv3d= CTX_wm_region_data(C);
00726     View3D *v3d= CTX_wm_view3d(C);
00727     float gridf, *curs;
00728 
00729     gridf= rv3d->gridview;
00730     curs= give_cursor(scene, v3d);
00731 
00732     curs[0]= gridf*floorf(0.5f+curs[0]/gridf);
00733     curs[1]= gridf*floorf(0.5f+curs[1]/gridf);
00734     curs[2]= gridf*floorf(0.5f+curs[2]/gridf);
00735     
00736     WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);    // hrm
00737     
00738     return OPERATOR_FINISHED;
00739 }
00740 
00741 void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
00742 {
00743     /* identifiers */
00744     ot->name= "Snap Cursor to Grid";
00745     ot->description= "Snap cursor to nearest grid node";
00746     ot->idname= "VIEW3D_OT_snap_cursor_to_grid";
00747     
00748     /* api callbacks */
00749     ot->exec= snap_curs_to_grid;
00750     ot->poll= ED_operator_region_view3d_active;
00751     
00752     /* flags */
00753     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00754 }
00755 
00756 /* **************************************************** */
00757 
00758 static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
00759 {
00760     MovieClip *clip= object_get_movieclip(scene, ob, 0);
00761     MovieTracking *tracking;
00762     MovieTrackingObject *object;
00763     int ok= 0;
00764     float min[3], max[3], mat[4][4], pos[3], cammat[4][4] = MAT4_UNITY;
00765 
00766     if(!clip)
00767         return;
00768 
00769     tracking= &clip->tracking;
00770 
00771     copy_m4_m4(cammat, ob->obmat);
00772 
00773     BKE_get_tracking_mat(scene, ob, mat);
00774 
00775     INIT_MINMAX(min, max);
00776 
00777     for (object= tracking->objects.first; object; object= object->next) {
00778         ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
00779         MovieTrackingTrack *track= tracksbase->first;
00780         float obmat[4][4];
00781 
00782         if(object->flag & TRACKING_OBJECT_CAMERA) {
00783             copy_m4_m4(obmat, mat);
00784         }
00785         else {
00786             float imat[4][4];
00787 
00788             BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, imat);
00789             invert_m4(imat);
00790 
00791             mult_m4_m4m4(obmat, cammat, imat);
00792         }
00793 
00794         while(track) {
00795             if((track->flag&TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
00796                 ok= 1;
00797                 mul_v3_m4v3(pos, obmat, track->bundle_pos);
00798                 DO_MINMAX(pos, min, max);
00799             }
00800 
00801             track= track->next;
00802         }
00803     }
00804 
00805     if(ok) {
00806         mid_v3_v3v3(vec, min, max);
00807     }
00808 }
00809 
00810 static int snap_curs_to_sel(bContext *C, wmOperator *UNUSED(op))
00811 {
00812     Object *obedit= CTX_data_edit_object(C);
00813     Scene *scene= CTX_data_scene(C);
00814     View3D *v3d= CTX_wm_view3d(C);
00815     TransVert *tv;
00816     float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3];
00817     int count, a;
00818 
00819     curs= give_cursor(scene, v3d);
00820 
00821     count= 0;
00822     INIT_MINMAX(min, max);
00823     centroid[0]= centroid[1]= centroid[2]= 0.0;
00824 
00825     if(obedit) {
00826         tottrans=0;
00827         
00828         if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
00829             make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS|TM_SKIP_HANDLES);
00830         if(tottrans==0) return OPERATOR_CANCELLED;
00831         
00832         copy_m3_m4(bmat, obedit->obmat);
00833         
00834         tv= transvmain;
00835         for(a=0; a<tottrans; a++, tv++) {
00836             copy_v3_v3(vec, tv->loc);
00837             mul_m3_v3(bmat, vec);
00838             add_v3_v3(vec, obedit->obmat[3]);
00839             add_v3_v3(centroid, vec);
00840             DO_MINMAX(vec, min, max);
00841         }
00842         
00843         if(v3d->around==V3D_CENTROID) {
00844             mul_v3_fl(centroid, 1.0f/(float)tottrans);
00845             copy_v3_v3(curs, centroid);
00846         }
00847         else {
00848             mid_v3_v3v3(curs, min, max);
00849         }
00850         MEM_freeN(transvmain);
00851         transvmain= NULL;
00852     }
00853     else {
00854         Object *obact= CTX_data_active_object(C);
00855         
00856         if(obact && (obact->mode & OB_MODE_POSE)) {
00857             bArmature *arm= obact->data;
00858             bPoseChannel *pchan;
00859             for (pchan = obact->pose->chanbase.first; pchan; pchan=pchan->next) {
00860                 if(arm->layer & pchan->bone->layer) {
00861                     if(pchan->bone->flag & BONE_SELECTED) {
00862                         copy_v3_v3(vec, pchan->pose_head);
00863                         mul_m4_v3(obact->obmat, vec);
00864                         add_v3_v3(centroid, vec);
00865                         DO_MINMAX(vec, min, max);
00866                         count++;
00867                     }
00868                 }
00869             }
00870         }
00871         else {
00872             CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
00873                 copy_v3_v3(vec, ob->obmat[3]);
00874 
00875                 /* special case for camera -- snap to bundles */
00876                 if(ob->type==OB_CAMERA) {
00877                     /* snap to bundles should happen only when bundles are visible */
00878                     if(v3d->flag2&V3D_SHOW_RECONSTRUCTION) {
00879                         bundle_midpoint(scene, ob, vec);
00880                     }
00881                 }
00882 
00883                 add_v3_v3(centroid, vec);
00884                 DO_MINMAX(vec, min, max);
00885                 count++;
00886             }
00887             CTX_DATA_END;
00888         }
00889         if(count) {
00890             if(v3d->around==V3D_CENTROID) {
00891                 mul_v3_fl(centroid, 1.0f/(float)count);
00892                 copy_v3_v3(curs, centroid);
00893             }
00894             else {
00895                 mid_v3_v3v3(curs, min, max);
00896             }
00897         }
00898     }
00899     WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
00900     
00901     return OPERATOR_FINISHED;
00902 }
00903 
00904 void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
00905 {
00906     /* identifiers */
00907     ot->name= "Snap Cursor to Selected";
00908     ot->description= "Snap cursor to center of selected item(s)";
00909     ot->idname= "VIEW3D_OT_snap_cursor_to_selected";
00910     
00911     /* api callbacks */
00912     ot->exec= snap_curs_to_sel;
00913     ot->poll= ED_operator_view3d_active;
00914     
00915     /* flags */
00916     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00917 }
00918 
00919 /* ********************************************** */
00920 
00921 static int snap_curs_to_active(bContext *C, wmOperator *UNUSED(op))
00922 {
00923     Object *obedit= CTX_data_edit_object(C);
00924     Object *obact= CTX_data_active_object(C);
00925     Scene *scene= CTX_data_scene(C);
00926     View3D *v3d= CTX_wm_view3d(C);
00927     float *curs;
00928     
00929     curs = give_cursor(scene, v3d);
00930 
00931     if (obedit)  {
00932         if (obedit->type == OB_MESH) {
00933             /* check active */
00934             Mesh *me= obedit->data;
00935             EditSelection ese;
00936             
00937             if (EM_get_actSelection(me->edit_mesh, &ese)) {
00938                 EM_editselection_center(curs, &ese);
00939             }
00940             
00941             mul_m4_v3(obedit->obmat, curs);
00942         }
00943     }
00944     else {
00945         if (obact) {
00946             copy_v3_v3(curs, obact->obmat[3]);
00947         }
00948     }
00949     
00950     WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
00951     return OPERATOR_FINISHED;
00952 }
00953 
00954 void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
00955 {
00956     /* identifiers */
00957     ot->name= "Snap Cursor to Active";
00958     ot->description= "Snap cursor to active item";
00959     ot->idname= "VIEW3D_OT_snap_cursor_to_active";
00960     
00961     /* api callbacks */
00962     ot->exec= snap_curs_to_active;
00963     ot->poll= ED_operator_view3d_active;
00964     
00965     /* flags */
00966     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00967 }
00968 
00969 /* **************************************************** */
00970 /*New Code - Snap Cursor to Center -*/
00971 static int snap_curs_to_center(bContext *C, wmOperator *UNUSED(op))
00972 {
00973     Scene *scene= CTX_data_scene(C);
00974     View3D *v3d= CTX_wm_view3d(C);
00975     float *curs;
00976     curs= give_cursor(scene, v3d);
00977 
00978     curs[0]= 0.0;
00979     curs[1]= 0.0;
00980     curs[2]= 0.0;
00981     
00982     WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
00983     
00984     return OPERATOR_FINISHED;
00985 }
00986 
00987 void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
00988 {
00989     /* identifiers */
00990     ot->name= "Snap Cursor to Center";
00991     ot->description= "Snap cursor to the Center";
00992     ot->idname= "VIEW3D_OT_snap_cursor_to_center";
00993     
00994     /* api callbacks */
00995     ot->exec= snap_curs_to_center;
00996     ot->poll= ED_operator_view3d_active;
00997     
00998     /* flags */
00999     ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
01000 }
01001 
01002 /* **************************************************** */
01003 
01004 
01005 int minmax_verts(Object *obedit, float *min, float *max)
01006 {
01007     TransVert *tv;
01008     float centroid[3], vec[3], bmat[3][3];
01009     int a;
01010 
01011     tottrans=0;
01012     if ELEM5(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE)
01013         make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS);
01014     
01015     if(tottrans==0) return 0;
01016 
01017     copy_m3_m4(bmat, obedit->obmat);
01018     
01019     tv= transvmain;
01020     for(a=0; a<tottrans; a++, tv++) {
01021         copy_v3_v3(vec, tv->loc);
01022         mul_m3_v3(bmat, vec);
01023         add_v3_v3(vec, obedit->obmat[3]);
01024         add_v3_v3(centroid, vec);
01025         DO_MINMAX(vec, min, max);
01026     }
01027     
01028     MEM_freeN(transvmain);
01029     transvmain= NULL;
01030     
01031     return 1;
01032 }
01033