svn merge ^/trunk/blender -r42991:43009
[blender.git] / source / blender / editors / space_view3d / view3d_snap.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_view3d/view3d_snap.c
29  *  \ingroup spview3d
30  */
31
32
33 #include <math.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_armature_types.h"
39 #include "DNA_curve_types.h"
40 #include "DNA_lattice_types.h"
41 #include "DNA_meta_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_object_types.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_math.h"
47 #include "BLI_editVert.h"
48 #include "BLI_linklist.h"
49 #include "BLI_utildefines.h"
50
51 #include "BKE_armature.h"
52 #include "BKE_context.h"
53 #include "BKE_curve.h"
54 #include "BKE_depsgraph.h"
55 #include "BKE_lattice.h"
56 #include "BKE_main.h"
57 #include "BKE_object.h"
58 #include "BKE_tessmesh.h"
59 #include "BKE_DerivedMesh.h"
60 #include "BKE_scene.h"
61 #include "BKE_tracking.h"
62
63 #include "WM_api.h"
64 #include "WM_types.h"
65
66
67
68 #include "ED_armature.h"
69 #include "ED_mesh.h"
70 #include "ED_keyframing.h"
71 #include "ED_screen.h"
72 #include "ED_curve.h" /* for curve_editnurbs */
73
74 #include "view3d_intern.h"
75
76 extern float originmat[3][3];   /* XXX object.c */
77
78 /* ************************************************** */
79 /* ********************* old transform stuff ******** */
80 /* *********** will get replaced with new transform * */
81 /* ************************************************** */
82
83 typedef struct TransVert {
84         float *loc;
85         float oldloc[3], maploc[3], fac;
86         float *val, oldval;
87         int flag;
88         float *nor;
89         int f1;
90 } TransVert;
91
92 static TransVert *transvmain=NULL;
93 static int tottrans= 0;
94
95 /* copied from editobject.c, now uses (almost) proper depgraph */
96 static void special_transvert_update(Object *obedit)
97 {
98         if(obedit) {
99                 DAG_id_tag_update(obedit->data, 0);
100                 
101                 if(obedit->type==OB_MESH) {
102                         Mesh *me= obedit->data;
103                         BM_Compute_Normals(me->edit_btmesh->bm);        // does face centers too
104                 }
105                 else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
106                         Curve *cu= obedit->data;
107                         ListBase *nurbs= curve_editnurbs(cu);
108                         Nurb *nu= nurbs->first;
109
110                         while(nu) {
111                                 /* keep handles' vectors unchanged */
112                                 if(nu->bezt) {
113                                         int a= nu->pntsu;
114                                         TransVert *tv= transvmain;
115                                         BezTriple *bezt= nu->bezt;
116
117                                         while(a--) {
118                                                 if(bezt->f1 & SELECT) tv++;
119
120                                                 if(bezt->f2 & SELECT) {
121                                                         float v[3];
122
123                                                         if(bezt->f1 & SELECT) {
124                                                                 sub_v3_v3v3(v, (tv-1)->oldloc, tv->oldloc);
125                                                                 add_v3_v3v3(bezt->vec[0], bezt->vec[1], v);
126                                                         }
127
128                                                         if(bezt->f3 & SELECT) {
129                                                                 sub_v3_v3v3(v, (tv+1)->oldloc, tv->oldloc);
130                                                                 add_v3_v3v3(bezt->vec[2], bezt->vec[1], v);
131                                                         }
132
133                                                         tv++;
134                                                 }
135
136                                                 if(bezt->f3 & SELECT) tv++;
137
138                                                 bezt++;
139                                         }
140                                 }
141
142                                 test2DNurb(nu);
143                                 testhandlesNurb(nu); /* test for bezier too */
144                                 nu= nu->next;
145                         }
146                 }
147                 else if(obedit->type==OB_ARMATURE){
148                         bArmature *arm= obedit->data;
149                         EditBone *ebo;
150                         TransVert *tv= transvmain;
151                         int a=0;
152                         
153                         /* Ensure all bone tails are correctly adjusted */
154                         for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
155                                 /* adjust tip if both ends selected */
156                                 if ((ebo->flag & BONE_ROOTSEL) && (ebo->flag & BONE_TIPSEL)) {
157                                         if (tv) {
158                                                 float diffvec[3];
159                                                 
160                                                 sub_v3_v3v3(diffvec, tv->loc, tv->oldloc);
161                                                 add_v3_v3(ebo->tail, diffvec);
162                                                 
163                                                 a++;
164                                                 if (a<tottrans) tv++;
165                                         }
166                                 }
167                         }
168                         
169                         /* Ensure all bones are correctly adjusted */
170                         for (ebo= arm->edbo->first; ebo; ebo=ebo->next) {
171                                 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
172                                         /* If this bone has a parent tip that has been moved */
173                                         if (ebo->parent->flag & BONE_TIPSEL){
174                                                 copy_v3_v3(ebo->head, ebo->parent->tail);
175                                         }
176                                         /* If this bone has a parent tip that has NOT been moved */
177                                         else{
178                                                 copy_v3_v3(ebo->parent->tail, ebo->head);
179                                         }
180                                 }
181                         }
182                         if(arm->flag & ARM_MIRROR_EDIT)
183                                 transform_armature_mirror_update(obedit);
184                 }
185                 else if(obedit->type==OB_LATTICE) {
186                         Lattice *lt= obedit->data;
187                         
188                         if(lt->editlatt->latt->flag & LT_OUTSIDE)
189                                 outside_lattice(lt->editlatt->latt);
190                 }
191         }
192 }
193
194 static void set_mapped_co(void *vuserdata, int index, float *co, float *UNUSED(no), short *UNUSED(no_s))
195 {
196         void ** userdata = vuserdata;
197         BMEditMesh *em = userdata[0];
198         TransVert *tv = userdata[1];
199         BMVert *eve = EDBM_get_vert_for_index(em, index);
200         
201         if (BM_GetIndex(eve) != -1 && !tv[BM_GetIndex(eve)].f1) {
202                 copy_v3_v3(tv[BM_GetIndex(eve)].maploc, co);
203                 tv[BM_GetIndex(eve)].f1 = 1;
204         }
205 }
206
207 /* copied from editobject.c, needs to be replaced with new transform code still */
208 /* mode flags: */
209 #define TM_ALL_JOINTS           1 /* all joints (for bones only) */
210 #define TM_SKIP_HANDLES         2 /* skip handles when control point is selected (for curves only) */
211 static void make_trans_verts(Object *obedit, float *min, float *max, int mode)
212 {
213         Nurb *nu;
214         BezTriple *bezt;
215         BPoint *bp;
216         TransVert *tv=NULL;
217         MetaElem *ml;
218         BMVert *eve;
219         EditBone        *ebo;
220         float total, center[3], centroid[3];
221         int a;
222
223         tottrans= 0; // global!
224         
225         INIT_MINMAX(min, max);
226         centroid[0]=centroid[1]=centroid[2]= 0.0;
227         
228         if(obedit->type==OB_MESH) {
229                 Mesh *me= obedit->data;
230                 BMEditMesh *em= me->edit_btmesh;
231                 BMesh *bm = em->bm;
232                 BMIter iter;
233                 void *userdata[2] = {em, NULL};
234                 /*int proptrans= 0; */ /*UNUSED*/
235                 
236                 /* abuses vertex index all over, set, just set dirty here,
237                  * perhaps this could use its own array instead? - campbell */
238
239                 // transform now requires awareness for select mode, so we tag the f1 flags in verts
240                 tottrans= 0;
241                 if(em->selectmode & SCE_SELECT_VERTEX) {
242                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
243                                 if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) {
244                                         BM_SetIndex(eve, 1); /* set_dirty! */
245                                         tottrans++;
246                                 }
247                                 else BM_SetIndex(eve, 0); /* set_dirty! */
248                         }
249                 }
250                 else if(em->selectmode & SCE_SELECT_EDGE) {
251                         BMEdge *eed;
252
253                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
254                                 BM_SetIndex(eve, 0); /* set_dirty! */
255
256                         BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
257                                 if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT)) {
258                                         BM_SetIndex(eed->v1, 1); /* set_dirty! */
259                                         BM_SetIndex(eed->v2, 1); /* set_dirty! */
260                                 }
261                         }
262
263                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
264                                 if(BM_GetIndex(eve)) tottrans++;
265                 }
266                 else {
267                         BMFace *efa;
268
269                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
270                                 BM_SetIndex(eve, 0); /* set_dirty! */
271
272                         BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
273                                 if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) {
274                                         BMIter liter;
275                                         BMLoop *l;
276                                         
277                                         BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
278                                                 BM_SetIndex(l->v, 1); /* set_dirty! */
279                                         }
280                                 }
281                         }
282
283                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
284                                 if(BM_GetIndex(eve)) tottrans++;
285                 }
286                 /* for any of the 3 loops above which all dirty the indicies */
287                 bm->elem_index_dirty |= BM_VERT;
288                 
289                 /* and now make transverts */
290                 if(tottrans) {
291                         tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
292                 
293                         a = 0;
294                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
295                                 if(BM_GetIndex(eve)) {
296                                         BM_SetIndex(eve, a); /* set_dirty! */
297                                         copy_v3_v3(tv->oldloc, eve->co);
298                                         tv->loc= eve->co;
299                                         if(eve->no[0] != 0.0f || eve->no[1] != 0.0f ||eve->no[2] != 0.0f)
300                                                 tv->nor= eve->no; // note this is a hackish signal (ton)
301                                         tv->flag= BM_GetIndex(eve) & SELECT;
302                                         tv++;
303                                         a++;
304                                 } else BM_SetIndex(eve, -1); /* set_dirty! */
305                         }
306                         /* set dirty already, above */
307
308                         userdata[1] = transvmain;
309                 }
310                 
311                 if (transvmain && em->derivedCage) {
312                         EDBM_init_index_arrays(em, 1, 0, 0);
313                         em->derivedCage->foreachMappedVert(em->derivedCage, set_mapped_co, userdata);
314                         EDBM_free_index_arrays(em);
315                 } else if (transvmain) {
316                         tv = transvmain;
317                         for (a=0; a<tottrans; a++, tv++) {
318                                 copy_v3_v3(tv->maploc, tv->loc);
319                         }
320                 }
321         }
322         else if (obedit->type==OB_ARMATURE){
323                 bArmature *arm= obedit->data;
324                 int totmalloc= BLI_countlist(arm->edbo);
325
326                 totmalloc *= 2;  /* probably overkill but bones can have 2 trans verts each */
327
328                 tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts armature");
329                 
330                 for (ebo= arm->edbo->first; ebo; ebo=ebo->next){
331                         if(ebo->layer & arm->layer) {
332                                 short tipsel= (ebo->flag & BONE_TIPSEL);
333                                 short rootsel= (ebo->flag & BONE_ROOTSEL);
334                                 short rootok= (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL));
335                                 
336                                 if ((tipsel && rootsel) || (rootsel)) {
337                                         /* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
338                                          * otherwise we get zero-length bones as tips will snap to the same
339                                          * location as heads.
340                                          */
341                                         if (rootok) {
342                                                 copy_v3_v3(tv->oldloc, ebo->head);
343                                                 tv->loc= ebo->head;
344                                                 tv->nor= NULL;
345                                                 tv->flag= 1;
346                                                 tv++;
347                                                 tottrans++;
348                                         }       
349                                         
350                                         if ((mode & TM_ALL_JOINTS) && (tipsel)) {
351                                                 copy_v3_v3(tv->oldloc, ebo->tail);
352                                                 tv->loc= ebo->tail;
353                                                 tv->nor= NULL;
354                                                 tv->flag= 1;
355                                                 tv++;
356                                                 tottrans++;
357                                         }
358                                 }
359                                 else if (tipsel) {
360                                         copy_v3_v3(tv->oldloc, ebo->tail);
361                                         tv->loc= ebo->tail;
362                                         tv->nor= NULL;
363                                         tv->flag= 1;
364                                         tv++;
365                                         tottrans++;
366                                 }
367                         }
368                 }
369         }
370         else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
371                 Curve *cu= obedit->data;
372                 int totmalloc= 0;
373                 ListBase *nurbs= curve_editnurbs(cu);
374
375                 for(nu= nurbs->first; nu; nu= nu->next) {
376                         if(nu->type == CU_BEZIER)
377                                 totmalloc += 3*nu->pntsu;
378                         else
379                                 totmalloc += nu->pntsu*nu->pntsv;
380                 }
381                 tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts curve");
382
383                 nu= nurbs->first;
384                 while(nu) {
385                         if(nu->type == CU_BEZIER) {
386                                 a= nu->pntsu;
387                                 bezt= nu->bezt;
388                                 while(a--) {
389                                         if(bezt->hide==0) {
390                                                 int skip_handle= 0;
391                                                 if(bezt->f2 & SELECT)
392                                                         skip_handle= mode & TM_SKIP_HANDLES;
393
394                                                 if((bezt->f1 & SELECT) && !skip_handle) {
395                                                         copy_v3_v3(tv->oldloc, bezt->vec[0]);
396                                                         tv->loc= bezt->vec[0];
397                                                         tv->flag= bezt->f1 & SELECT;
398                                                         tv++;
399                                                         tottrans++;
400                                                 }
401                                                 if(bezt->f2 & SELECT) {
402                                                         copy_v3_v3(tv->oldloc, bezt->vec[1]);
403                                                         tv->loc= bezt->vec[1];
404                                                         tv->val= &(bezt->alfa);
405                                                         tv->oldval= bezt->alfa;
406                                                         tv->flag= bezt->f2 & SELECT;
407                                                         tv++;
408                                                         tottrans++;
409                                                 }
410                                                 if((bezt->f3 & SELECT) && !skip_handle) {
411                                                         copy_v3_v3(tv->oldloc, bezt->vec[2]);
412                                                         tv->loc= bezt->vec[2];
413                                                         tv->flag= bezt->f3 & SELECT;
414                                                         tv++;
415                                                         tottrans++;
416                                                 }
417                                         }
418                                         bezt++;
419                                 }
420                         }
421                         else {
422                                 a= nu->pntsu*nu->pntsv;
423                                 bp= nu->bp;
424                                 while(a--) {
425                                         if(bp->hide==0) {
426                                                 if(bp->f1 & SELECT) {
427                                                         copy_v3_v3(tv->oldloc, bp->vec);
428                                                         tv->loc= bp->vec;
429                                                         tv->val= &(bp->alfa);
430                                                         tv->oldval= bp->alfa;
431                                                         tv->flag= bp->f1 & SELECT;
432                                                         tv++;
433                                                         tottrans++;
434                                                 }
435                                         }
436                                         bp++;
437                                 }
438                         }
439                         nu= nu->next;
440                 }
441         }
442         else if(obedit->type==OB_MBALL) {
443                 MetaBall *mb= obedit->data;
444                 int totmalloc= BLI_countlist(mb->editelems);
445                 
446                 tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts mball");
447                 
448                 ml= mb->editelems->first;
449                 while(ml) {
450                         if(ml->flag & SELECT) {
451                                 tv->loc= &ml->x;
452                                 copy_v3_v3(tv->oldloc, tv->loc);
453                                 tv->val= &(ml->rad);
454                                 tv->oldval= ml->rad;
455                                 tv->flag= 1;
456                                 tv++;
457                                 tottrans++;
458                         }
459                         ml= ml->next;
460                 }
461         }
462         else if(obedit->type==OB_LATTICE) {
463                 Lattice *lt= obedit->data;
464                 
465                 bp= lt->editlatt->latt->def;
466                 
467                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
468                 
469                 tv=transvmain= MEM_callocN(a*sizeof(TransVert), "maketransverts latt");
470                 
471                 while(a--) {
472                         if(bp->f1 & SELECT) {
473                                 if(bp->hide==0) {
474                                         copy_v3_v3(tv->oldloc, bp->vec);
475                                         tv->loc= bp->vec;
476                                         tv->flag= bp->f1 & SELECT;
477                                         tv++;
478                                         tottrans++;
479                                 }
480                         }
481                         bp++;
482                 }
483         }
484         
485         if(!tottrans && transvmain) {
486                 /* prevent memory leak. happens for curves/latticies due to */
487                 /* difficult condition of adding points to trans data */
488                 MEM_freeN(transvmain);
489                 transvmain= NULL;
490         }
491
492         /* cent etc */
493         tv= transvmain;
494         total= 0.0;
495         for(a=0; a<tottrans; a++, tv++) {
496                 if(tv->flag & SELECT) {
497                         add_v3_v3(centroid, tv->oldloc);
498                         total += 1.0f;
499                         DO_MINMAX(tv->oldloc, min, max);
500                 }
501         }
502         if(total != 0.0f) {
503                 mul_v3_fl(centroid, 1.0f/total);
504         }
505
506         mid_v3_v3v3(center, min, max);
507 }
508
509 /* *********************** operators ******************** */
510
511 static int snap_sel_to_grid(bContext *C, wmOperator *UNUSED(op))
512 {
513         Main *bmain= CTX_data_main(C);
514         Object *obedit= CTX_data_edit_object(C);
515         Scene *scene= CTX_data_scene(C);
516         RegionView3D *rv3d= CTX_wm_region_data(C);
517         TransVert *tv;
518         float gridf, imat[3][3], bmat[3][3], vec[3];
519         int a;
520
521         gridf= rv3d->gridview;
522
523         if(obedit) {
524                 tottrans= 0;
525                 
526                 if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
527                         make_trans_verts(obedit, bmat[0], bmat[1], 0);
528                 if(tottrans==0) return OPERATOR_CANCELLED;
529                 
530                 copy_m3_m4(bmat, obedit->obmat);
531                 invert_m3_m3(imat, bmat);
532                 
533                 tv= transvmain;
534                 for(a=0; a<tottrans; a++, tv++) {
535                         copy_v3_v3(vec, tv->loc);
536                         mul_m3_v3(bmat, vec);
537                         add_v3_v3(vec, obedit->obmat[3]);
538                         vec[0]= gridf*floorf(0.5f+ vec[0]/gridf);
539                         vec[1]= gridf*floorf(0.5f+ vec[1]/gridf);
540                         vec[2]= gridf*floorf(0.5f+ vec[2]/gridf);
541                         sub_v3_v3(vec, obedit->obmat[3]);
542                         
543                         mul_m3_v3(imat, vec);
544                         copy_v3_v3(tv->loc, vec);
545                 }
546                 
547                 special_transvert_update(obedit);
548                 
549                 MEM_freeN(transvmain);
550                 transvmain= NULL;
551         }
552         else {
553                 struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
554
555                 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
556                         if(ob->mode & OB_MODE_POSE) {
557                                 bPoseChannel *pchan;
558                                 bArmature *arm= ob->data;
559                                 
560                                 invert_m4_m4(ob->imat, ob->obmat);
561                                 
562                                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
563                                         if(pchan->bone->flag & BONE_SELECTED) {
564                                                 if(pchan->bone->layer & arm->layer) {
565                                                         if((pchan->bone->flag & BONE_CONNECTED)==0) {
566                                                                 float nLoc[3];
567                                                                 float inv_restmat[4][4];
568                                                                 
569                                                                 /* get nearest grid point to snap to */
570                                                                 copy_v3_v3(nLoc, pchan->pose_mat[3]);
571                                                                 /* We must operate in world space! */
572                                                                 mul_m4_v3(ob->obmat, nLoc);
573                                                                 vec[0]= gridf * (float)(floor(0.5f+ nLoc[0]/gridf));
574                                                                 vec[1]= gridf * (float)(floor(0.5f+ nLoc[1]/gridf));
575                                                                 vec[2]= gridf * (float)(floor(0.5f+ nLoc[2]/gridf));
576                                                                 /* Back in object space... */
577                                                                 mul_m4_v3(ob->imat, vec);
578                                                                 
579                                                                 /* get location of grid point in *rest* bone-space */
580                                                                 invert_m4_m4(inv_restmat, pchan->bone->arm_mat);
581                                                                 mul_m4_v3(inv_restmat, vec);
582                                                                 
583                                                                 /* adjust location */
584                                                                 if ((pchan->protectflag & OB_LOCK_LOCX)==0)
585                                                                         pchan->loc[0]= vec[0];
586                                                                 if ((pchan->protectflag & OB_LOCK_LOCY)==0)
587                                                                         pchan->loc[1]= vec[1];
588                                                                 if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
589                                                                         pchan->loc[2]= vec[2];
590
591                                                                 /* auto-keyframing */
592                                                                 ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
593                                                         }
594                                                         /* if the bone has a parent and is connected to the parent,
595                                                          * don't do anything - will break chain unless we do auto-ik.
596                                                          */
597                                                 }
598                                         }
599                                 }
600                                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
601                                 
602                                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
603                         }
604                         else {
605                                 ob->recalc |= OB_RECALC_OB;
606                                 
607                                 vec[0]= -ob->obmat[3][0]+gridf*floorf(0.5f+ ob->obmat[3][0]/gridf);
608                                 vec[1]= -ob->obmat[3][1]+gridf*floorf(0.5f+ ob->obmat[3][1]/gridf);
609                                 vec[2]= -ob->obmat[3][2]+gridf*floorf(0.5f+ ob->obmat[3][2]/gridf);
610                                 
611                                 if(ob->parent) {
612                                         where_is_object(scene, ob);
613                                         
614                                         invert_m3_m3(imat, originmat);
615                                         mul_m3_v3(imat, vec);
616                                 }
617                                 if ((ob->protectflag & OB_LOCK_LOCX)==0)
618                                         ob->loc[0]+= vec[0];
619                                 if ((ob->protectflag & OB_LOCK_LOCY)==0)
620                                         ob->loc[1]+= vec[1];
621                                 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
622                                         ob->loc[2]+= vec[2];
623                                 
624                                 /* auto-keyframing */
625                                 ED_autokeyframe_object(C, scene, ob, ks);
626                         }
627                 }
628                 CTX_DATA_END;
629         }
630
631         DAG_ids_flush_update(bmain, 0);
632         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
633         
634         return OPERATOR_FINISHED;
635 }
636
637 void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
638 {
639         /* identifiers */
640         ot->name= "Snap Selection to Grid";
641         ot->description= "Snap selected item(s) to nearest grid node";
642         ot->idname= "VIEW3D_OT_snap_selected_to_grid";
643         
644         /* api callbacks */
645         ot->exec= snap_sel_to_grid;
646         ot->poll= ED_operator_region_view3d_active;
647         
648         /* flags */
649         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
650 }
651
652 /* *************************************************** */
653
654 static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op))
655 {
656         Main *bmain= CTX_data_main(C);
657         Object *obedit= CTX_data_edit_object(C);
658         Scene *scene= CTX_data_scene(C);
659         View3D *v3d= CTX_wm_view3d(C);
660         TransVert *tv;
661         float *curs, imat[3][3], bmat[3][3], vec[3];
662         int a;
663
664         curs= give_cursor(scene, v3d);
665
666         if(obedit) {
667                 tottrans= 0;
668                 
669                 if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
670                         make_trans_verts(obedit, bmat[0], bmat[1], 0);
671                 if(tottrans==0) return OPERATOR_CANCELLED;
672                 
673                 copy_m3_m4(bmat, obedit->obmat);
674                 invert_m3_m3(imat, bmat);
675                 
676                 tv= transvmain;
677                 for(a=0; a<tottrans; a++, tv++) {
678                         sub_v3_v3v3(vec, curs, obedit->obmat[3]);
679                         mul_m3_v3(imat, vec);
680                         copy_v3_v3(tv->loc, vec);
681                 }
682                 
683                 special_transvert_update(obedit);
684                 
685                 MEM_freeN(transvmain);
686                 transvmain= NULL;
687         }
688         else {
689                 struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
690
691                 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
692                         if(ob->mode & OB_MODE_POSE) {
693                                 bPoseChannel *pchan;
694                                 bArmature *arm= ob->data;
695                                 
696                                 invert_m4_m4(ob->imat, ob->obmat);
697                                 copy_v3_v3(vec, curs);
698                                 mul_m4_v3(ob->imat, vec);
699                                 
700                                 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
701                                         if(pchan->bone->flag & BONE_SELECTED) {
702                                                 if(pchan->bone->layer & arm->layer) {
703                                                         if((pchan->bone->flag & BONE_CONNECTED)==0) {
704                                                                 float inv_restmat[4][4];
705                                                                 
706                                                                 /* get location of cursor in *rest* bone-space */
707                                                                 invert_m4_m4(inv_restmat, pchan->bone->arm_mat);
708                                                                 mul_m4_v3(inv_restmat, vec);
709                                                                 
710                                                                 /* copy new position */
711                                                                 if ((pchan->protectflag & OB_LOCK_LOCX)==0)
712                                                                         pchan->loc[0]= vec[0];
713                                                                 if ((pchan->protectflag & OB_LOCK_LOCY)==0)
714                                                                         pchan->loc[1]= vec[1];
715                                                                 if ((pchan->protectflag & OB_LOCK_LOCZ)==0)
716                                                                         pchan->loc[2]= vec[2];
717
718                                                                 /* auto-keyframing */
719                                                                 ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
720                                                         }
721                                                         /* if the bone has a parent and is connected to the parent,
722                                                          * don't do anything - will break chain unless we do auto-ik.
723                                                          */
724                                                 }
725                                         }
726                                 }
727                                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
728                                 
729                                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
730                         }
731                         else {
732                                 ob->recalc |= OB_RECALC_OB;
733                                 
734                                 vec[0]= -ob->obmat[3][0] + curs[0];
735                                 vec[1]= -ob->obmat[3][1] + curs[1];
736                                 vec[2]= -ob->obmat[3][2] + curs[2];
737                                 
738                                 if(ob->parent) {
739                                         where_is_object(scene, ob);
740                                         
741                                         invert_m3_m3(imat, originmat);
742                                         mul_m3_v3(imat, vec);
743                                 }
744                                 if ((ob->protectflag & OB_LOCK_LOCX)==0)
745                                         ob->loc[0]+= vec[0];
746                                 if ((ob->protectflag & OB_LOCK_LOCY)==0)
747                                         ob->loc[1]+= vec[1];
748                                 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
749                                         ob->loc[2]+= vec[2];
750
751                                 /* auto-keyframing */
752                                 ED_autokeyframe_object(C, scene, ob, ks);
753                         }
754                 }
755                 CTX_DATA_END;
756         }
757
758         DAG_ids_flush_update(bmain, 0);
759         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
760         
761         return OPERATOR_FINISHED;
762 }
763
764 void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
765 {
766         /* identifiers */
767         ot->name= "Snap Selection to Cursor";
768         ot->description= "Snap selected item(s) to cursor";
769         ot->idname= "VIEW3D_OT_snap_selected_to_cursor";
770         
771         /* api callbacks */
772         ot->exec= snap_sel_to_curs;
773         ot->poll= ED_operator_view3d_active;
774         
775         /* flags */
776         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
777 }
778
779 /* *************************************************** */
780
781 static int snap_curs_to_grid(bContext *C, wmOperator *UNUSED(op))
782 {
783         Scene *scene= CTX_data_scene(C);
784         RegionView3D *rv3d= CTX_wm_region_data(C);
785         View3D *v3d= CTX_wm_view3d(C);
786         float gridf, *curs;
787
788         gridf= rv3d->gridview;
789         curs= give_cursor(scene, v3d);
790
791         curs[0]= gridf*floorf(0.5f+curs[0]/gridf);
792         curs[1]= gridf*floorf(0.5f+curs[1]/gridf);
793         curs[2]= gridf*floorf(0.5f+curs[2]/gridf);
794         
795         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);        // hrm
796         
797         return OPERATOR_FINISHED;
798 }
799
800 void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
801 {
802         /* identifiers */
803         ot->name= "Snap Cursor to Grid";
804         ot->description= "Snap cursor to nearest grid node";
805         ot->idname= "VIEW3D_OT_snap_cursor_to_grid";
806         
807         /* api callbacks */
808         ot->exec= snap_curs_to_grid;
809         ot->poll= ED_operator_region_view3d_active;
810         
811         /* flags */
812         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
813 }
814
815 /* **************************************************** */
816
817 static void bundle_midpoint(Scene *scene, Object *ob, float vec[3])
818 {
819         MovieClip *clip= object_get_movieclip(scene, ob, 0);
820         MovieTracking *tracking= &clip->tracking;
821         MovieTrackingObject *object= tracking->objects.first;
822         int ok= 0;
823         float min[3], max[3], mat[4][4], pos[3], cammat[4][4];
824
825         if(!clip)
826                 return;
827
828         unit_m4(cammat);
829
830         if(!scene->camera)
831                 scene->camera= scene_find_camera(scene);
832
833         if(scene->camera)
834                 copy_m4_m4(cammat, scene->camera->obmat);
835
836         BKE_get_tracking_mat(scene, ob, mat);
837
838         INIT_MINMAX(min, max);
839
840         while(object) {
841                 ListBase *tracksbase= BKE_tracking_object_tracks(tracking, object);
842                 MovieTrackingTrack *track= tracksbase->first;
843                 float obmat[4][4];
844
845                 if(object->flag & TRACKING_OBJECT_CAMERA) {
846                         copy_m4_m4(obmat, mat);
847                 }
848                 else {
849                         float imat[4][4];
850
851                         BKE_tracking_get_interpolated_camera(tracking, object, scene->r.cfra, imat);
852                         invert_m4(imat);
853
854                         mult_m4_m4m4(obmat, cammat, imat);
855                 }
856
857                 while(track) {
858                         if((track->flag&TRACK_HAS_BUNDLE) && TRACK_SELECTED(track)) {
859                                 ok= 1;
860                                 mul_v3_m4v3(pos, obmat, track->bundle_pos);
861                                 DO_MINMAX(pos, min, max);
862                         }
863
864                         track= track->next;
865                 }
866
867                 object= object->next;
868         }
869
870         if(ok) {
871                 mid_v3_v3v3(vec, min, max);
872         }
873 }
874
875 static int snap_curs_to_sel(bContext *C, wmOperator *UNUSED(op))
876 {
877         Object *obedit= CTX_data_edit_object(C);
878         Scene *scene= CTX_data_scene(C);
879         View3D *v3d= CTX_wm_view3d(C);
880         TransVert *tv;
881         float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3];
882         int count, a;
883
884         curs= give_cursor(scene, v3d);
885
886         count= 0;
887         INIT_MINMAX(min, max);
888         centroid[0]= centroid[1]= centroid[2]= 0.0;
889
890         if(obedit) {
891                 tottrans=0;
892                 
893                 if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL)
894                         make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS|TM_SKIP_HANDLES);
895                 if(tottrans==0) return OPERATOR_CANCELLED;
896                 
897                 copy_m3_m4(bmat, obedit->obmat);
898                 
899                 tv= transvmain;
900                 for(a=0; a<tottrans; a++, tv++) {
901                         copy_v3_v3(vec, tv->loc);
902                         mul_m3_v3(bmat, vec);
903                         add_v3_v3(vec, obedit->obmat[3]);
904                         add_v3_v3(centroid, vec);
905                         DO_MINMAX(vec, min, max);
906                 }
907                 
908                 if(v3d->around==V3D_CENTROID) {
909                         mul_v3_fl(centroid, 1.0f/(float)tottrans);
910                         copy_v3_v3(curs, centroid);
911                 }
912                 else {
913                         mid_v3_v3v3(curs, min, max);
914                 }
915                 MEM_freeN(transvmain);
916                 transvmain= NULL;
917         }
918         else {
919                 Object *obact= CTX_data_active_object(C);
920                 
921                 if(obact && (obact->mode & OB_MODE_POSE)) {
922                         bArmature *arm= obact->data;
923                         bPoseChannel *pchan;
924                         for (pchan = obact->pose->chanbase.first; pchan; pchan=pchan->next) {
925                                 if(arm->layer & pchan->bone->layer) {
926                                         if(pchan->bone->flag & BONE_SELECTED) {
927                                                 copy_v3_v3(vec, pchan->pose_head);
928                                                 mul_m4_v3(obact->obmat, vec);
929                                                 add_v3_v3(centroid, vec);
930                                                 DO_MINMAX(vec, min, max);
931                                                 count++;
932                                         }
933                                 }
934                         }
935                 }
936                 else {
937                         CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
938                                 copy_v3_v3(vec, ob->obmat[3]);
939
940                                 /* special case for camera -- snap to bundles */
941                                 if(ob->type==OB_CAMERA) {
942                                         /* snap to bundles should happen only when bundles are visible */
943                                         if(v3d->flag2&V3D_SHOW_RECONSTRUCTION) {
944                                                 bundle_midpoint(scene, ob, vec);
945                                         }
946                                 }
947
948                                 add_v3_v3(centroid, vec);
949                                 DO_MINMAX(vec, min, max);
950                                 count++;
951                         }
952                         CTX_DATA_END;
953                 }
954                 if(count) {
955                         if(v3d->around==V3D_CENTROID) {
956                                 mul_v3_fl(centroid, 1.0f/(float)count);
957                                 copy_v3_v3(curs, centroid);
958                         }
959                         else {
960                                 mid_v3_v3v3(curs, min, max);
961                         }
962                 }
963         }
964         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
965         
966         return OPERATOR_FINISHED;
967 }
968
969 void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
970 {
971         /* identifiers */
972         ot->name= "Snap Cursor to Selected";
973         ot->description= "Snap cursor to center of selected item(s)";
974         ot->idname= "VIEW3D_OT_snap_cursor_to_selected";
975         
976         /* api callbacks */
977         ot->exec= snap_curs_to_sel;
978         ot->poll= ED_operator_view3d_active;
979         
980         /* flags */
981         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
982 }
983
984 /* ********************************************** */
985
986 static int snap_curs_to_active(bContext *C, wmOperator *UNUSED(op))
987 {
988         Object *obedit= CTX_data_edit_object(C);
989         Object *obact= CTX_data_active_object(C);
990         Scene *scene= CTX_data_scene(C);
991         View3D *v3d= CTX_wm_view3d(C);
992         float *curs;
993         
994         curs = give_cursor(scene, v3d);
995
996         if (obedit)  {
997                 if (obedit->type == OB_MESH) {
998                         /* check active */
999                         Mesh *me= obedit->data;
1000                         BMEditSelection ese;
1001                         
1002                         if (EDBM_get_actSelection(me->edit_btmesh, &ese)) {
1003                                 EDBM_editselection_center(me->edit_btmesh, curs, &ese);
1004                         }
1005                         
1006                         mul_m4_v3(obedit->obmat, curs);
1007                 }
1008         }
1009         else {
1010                 if (obact) {
1011                         copy_v3_v3(curs, obact->obmat[3]);
1012                 }
1013         }
1014         
1015         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
1016         return OPERATOR_FINISHED;
1017 }
1018
1019 void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
1020 {
1021         /* identifiers */
1022         ot->name= "Snap Cursor to Active";
1023         ot->description= "Snap cursor to active item";
1024         ot->idname= "VIEW3D_OT_snap_cursor_to_active";
1025         
1026         /* api callbacks */
1027         ot->exec= snap_curs_to_active;
1028         ot->poll= ED_operator_view3d_active;
1029         
1030         /* flags */
1031         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1032 }
1033
1034 /* **************************************************** */
1035 /*New Code - Snap Cursor to Center -*/
1036 static int snap_curs_to_center(bContext *C, wmOperator *UNUSED(op))
1037 {
1038         Scene *scene= CTX_data_scene(C);
1039         View3D *v3d= CTX_wm_view3d(C);
1040         float *curs;
1041         curs= give_cursor(scene, v3d);
1042
1043         curs[0]= 0.0;
1044         curs[1]= 0.0;
1045         curs[2]= 0.0;
1046         
1047         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
1048         
1049         return OPERATOR_FINISHED;
1050 }
1051
1052 void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
1053 {
1054         /* identifiers */
1055         ot->name= "Snap Cursor to Center";
1056         ot->description= "Snap cursor to the Center";
1057         ot->idname= "VIEW3D_OT_snap_cursor_to_center";
1058         
1059         /* api callbacks */
1060         ot->exec= snap_curs_to_center;
1061         ot->poll= ED_operator_view3d_active;
1062         
1063         /* flags */
1064         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1065 }
1066
1067 /* **************************************************** */
1068
1069
1070 int minmax_verts(Object *obedit, float *min, float *max)
1071 {
1072         TransVert *tv;
1073         float centroid[3], vec[3], bmat[3][3];
1074         int a;
1075
1076         tottrans=0;
1077         if ELEM5(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE)
1078                 make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS);
1079         
1080         if(tottrans==0) return 0;
1081
1082         copy_m3_m4(bmat, obedit->obmat);
1083         
1084         tv= transvmain;
1085         for(a=0; a<tottrans; a++, tv++) {
1086                 copy_v3_v3(vec, tv->maploc);
1087                 mul_m3_v3(bmat, vec);
1088                 add_v3_v3(vec, obedit->obmat[3]);
1089                 add_v3_v3(centroid, vec);
1090                 DO_MINMAX(vec, min, max);
1091         }
1092         
1093         MEM_freeN(transvmain);
1094         transvmain= NULL;
1095         
1096         return 1;
1097 }