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