fixed 4 uses of un-inirialized vars + some compiler warnings.
[blender.git] / source / blender / editors / space_view3d / view3d_snap.c
1 /*
2  * $Id: view3d_snap.c 35106 2011-02-23 10:52:22Z jesterking $
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 #include "BKE_tessmesh.h"
61 #include "BKE_DerivedMesh.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_screen.h"
71 #include "ED_curve.h" /* for ED_curve_editnurbs */
72
73 #include "view3d_intern.h"
74
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], maploc[3], fac;
84         float *val, oldval;
85         int flag;
86         float *nor;
87         int f1;
88 } TransVert;
89
90 static TransVert *transvmain=NULL;
91 static int tottrans= 0;
92
93 /* copied from editobject.c, now uses (almost) proper depgraph */
94 static void special_transvert_update(Object *obedit)
95 {
96         
97         if(obedit) {
98                 
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= ED_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                                                 VECCOPY (ebo->head, ebo->parent->tail);
175                                         }
176                                         /* If this bone has a parent tip that has NOT been moved */
177                                         else{
178                                                 VECCOPY (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 (BMINDEX_GET(eve) != -1 && !tv[BMINDEX_GET(eve)].f1) {
202                 copy_v3_v3(tv[BMINDEX_GET(eve)].maploc, co);
203                 tv[BMINDEX_GET(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;
235                 
236                 // transform now requires awareness for select mode, so we tag the f1 flags in verts
237                 tottrans= 0;
238                 if(em->bm->selectmode & SCE_SELECT_VERTEX) {
239                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
240                                 if(!BM_TestHFlag(eve, BM_HIDDEN) && BM_TestHFlag(eve, BM_SELECT)) {
241                                         BMINDEX_SET(eve, 1);
242                                         tottrans++;
243                                 }
244                                 else BMINDEX_SET(eve, 0);
245                         }
246                 }
247                 else if(em->bm->selectmode & SCE_SELECT_EDGE) {
248                         BMEdge *eed;
249
250                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
251                                 BMINDEX_SET(eve, 0);
252
253                         BM_ITER(eed, &iter, bm, BM_EDGES_OF_MESH, NULL) {
254                                 if(!BM_TestHFlag(eed, BM_HIDDEN) && BM_TestHFlag(eed, BM_SELECT))
255                                         BMINDEX_SET(eed->v1, 1), BMINDEX_SET(eed->v2, 1);
256                         }
257
258                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
259                                 if(BMINDEX_GET(eve)) tottrans++;
260                 }
261                 else {
262                         BMFace *efa;
263
264                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
265                                 BMINDEX_SET(eve, 0);
266
267                         BM_ITER(efa, &iter, bm, BM_FACES_OF_MESH, NULL) {
268                                 if(!BM_TestHFlag(efa, BM_HIDDEN) && BM_TestHFlag(efa, BM_SELECT)) {
269                                         BMIter liter;
270                                         BMLoop *l;
271                                         
272                                         BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, efa) {
273                                                 BMINDEX_SET(l->v, 1);
274                                         }
275                                 }
276                         }
277
278                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL)
279                                 if(BMINDEX_GET(eve)) tottrans++;
280                 }
281                 
282                 /* and now make transverts */
283                 if(tottrans) {
284                         tv=transvmain= MEM_callocN(tottrans*sizeof(TransVert), "maketransverts");
285                 
286                         a = 0;
287                         BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
288                                 if(BMINDEX_GET(eve)) {
289                                         BMINDEX_SET(eve, a);
290                                         VECCOPY(tv->oldloc, eve->co);
291                                         tv->loc= eve->co;
292                                         if(eve->no[0] != 0.0f || eve->no[1] != 0.0f ||eve->no[2] != 0.0f)
293                                                 tv->nor= eve->no; // note this is a hackish signal (ton)
294                                         tv->flag= BMINDEX_GET(eve) & SELECT;
295                                         tv++;
296                                         a++;
297                                 } else BMINDEX_SET(eve, -1);
298                         }
299                         
300                         userdata[1] = transvmain;
301                 }
302                 
303                 if (transvmain && em->derivedCage) {
304                         EDBM_init_index_arrays(em, 1, 0, 0);
305                         em->derivedCage->foreachMappedVert(em->derivedCage, set_mapped_co, userdata);
306                         EDBM_free_index_arrays(em);
307                 } else if (transvmain) {
308                         tv = transvmain;
309                         for (a=0; a<tottrans; a++, tv++) {
310                                 copy_v3_v3(tv->maploc, tv->loc);
311                         }
312                 }
313         }
314         else if (obedit->type==OB_ARMATURE){
315                 bArmature *arm= obedit->data;
316                 int totmalloc= BLI_countlist(arm->edbo);
317
318                 totmalloc *= 2;  /* probably overkill but bones can have 2 trans verts each */
319
320                 tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts armature");
321                 
322                 for (ebo= arm->edbo->first; ebo; ebo=ebo->next){
323                         if(ebo->layer & arm->layer) {
324                                 short tipsel= (ebo->flag & BONE_TIPSEL);
325                                 short rootsel= (ebo->flag & BONE_ROOTSEL);
326                                 short rootok= (!(ebo->parent && (ebo->flag & BONE_CONNECTED) && ebo->parent->flag & BONE_TIPSEL));
327                                 
328                                 if ((tipsel && rootsel) || (rootsel)) {
329                                         /* Don't add the tip (unless mode & TM_ALL_JOINTS, for getting all joints),
330                                          * otherwise we get zero-length bones as tips will snap to the same
331                                          * location as heads. 
332                                          */
333                                         if (rootok) {
334                                                 VECCOPY (tv->oldloc, ebo->head);
335                                                 tv->loc= ebo->head;
336                                                 tv->nor= NULL;
337                                                 tv->flag= 1;
338                                                 tv++;
339                                                 tottrans++;
340                                         }       
341                                         
342                                         if ((mode & TM_ALL_JOINTS) && (tipsel)) {
343                                                 VECCOPY (tv->oldloc, ebo->tail);
344                                                 tv->loc= ebo->tail;
345                                                 tv->nor= NULL;
346                                                 tv->flag= 1;
347                                                 tv++;
348                                                 tottrans++;
349                                         }                                       
350                                 }
351                                 else if (tipsel) {
352                                         VECCOPY (tv->oldloc, ebo->tail);
353                                         tv->loc= ebo->tail;
354                                         tv->nor= NULL;
355                                         tv->flag= 1;
356                                         tv++;
357                                         tottrans++;
358                                 }
359                         }                       
360                 }
361         }
362         else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
363                 Curve *cu= obedit->data;
364                 int totmalloc= 0;
365                 ListBase *nurbs= ED_curve_editnurbs(cu);
366
367                 for(nu= nurbs->first; nu; nu= nu->next) {
368                         if(nu->type == CU_BEZIER)
369                                 totmalloc += 3*nu->pntsu;
370                         else
371                                 totmalloc += nu->pntsu*nu->pntsv;
372                 }
373                 tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts curve");
374
375                 nu= nurbs->first;
376                 while(nu) {
377                         if(nu->type == CU_BEZIER) {
378                                 a= nu->pntsu;
379                                 bezt= nu->bezt;
380                                 while(a--) {
381                                         if(bezt->hide==0) {
382                                                 int skip_handle= 0;
383                                                 if(bezt->f2 & SELECT)
384                                                         skip_handle= mode & TM_SKIP_HANDLES;
385
386                                                 if((bezt->f1 & SELECT) && !skip_handle) {
387                                                         VECCOPY(tv->oldloc, bezt->vec[0]);
388                                                         tv->loc= bezt->vec[0];
389                                                         tv->flag= bezt->f1 & SELECT;
390                                                         tv++;
391                                                         tottrans++;
392                                                 }
393                                                 if(bezt->f2 & SELECT) {
394                                                         VECCOPY(tv->oldloc, bezt->vec[1]);
395                                                         tv->loc= bezt->vec[1];
396                                                         tv->val= &(bezt->alfa);
397                                                         tv->oldval= bezt->alfa;
398                                                         tv->flag= bezt->f2 & SELECT;
399                                                         tv++;
400                                                         tottrans++;
401                                                 }
402                                                 if((bezt->f3 & SELECT) && !skip_handle) {
403                                                         VECCOPY(tv->oldloc, bezt->vec[2]);
404                                                         tv->loc= bezt->vec[2];
405                                                         tv->flag= bezt->f3 & SELECT;
406                                                         tv++;
407                                                         tottrans++;
408                                                 }
409                                         }
410                                         bezt++;
411                                 }
412                         }
413                         else {
414                                 a= nu->pntsu*nu->pntsv;
415                                 bp= nu->bp;
416                                 while(a--) {
417                                         if(bp->hide==0) {
418                                                 if(bp->f1 & SELECT) {
419                                                         VECCOPY(tv->oldloc, bp->vec);
420                                                         tv->loc= bp->vec;
421                                                         tv->val= &(bp->alfa);
422                                                         tv->oldval= bp->alfa;
423                                                         tv->flag= bp->f1 & SELECT;
424                                                         tv++;
425                                                         tottrans++;
426                                                 }
427                                         }
428                                         bp++;
429                                 }
430                         }
431                         nu= nu->next;
432                 }
433         }
434         else if(obedit->type==OB_MBALL) {
435                 MetaBall *mb= obedit->data;
436                 int totmalloc= BLI_countlist(mb->editelems);
437                 
438                 tv=transvmain= MEM_callocN(totmalloc*sizeof(TransVert), "maketransverts mball");
439                 
440                 ml= mb->editelems->first;
441                 while(ml) {
442                         if(ml->flag & SELECT) {
443                                 tv->loc= &ml->x;
444                                 copy_v3_v3(tv->oldloc, tv->loc);
445                                 tv->val= &(ml->rad);
446                                 tv->oldval= ml->rad;
447                                 tv->flag= 1;
448                                 tv++;
449                                 tottrans++;
450                         }
451                         ml= ml->next;
452                 }
453         }
454         else if(obedit->type==OB_LATTICE) {
455                 Lattice *lt= obedit->data;
456                 
457                 bp= lt->editlatt->latt->def;
458                 
459                 a= lt->editlatt->latt->pntsu*lt->editlatt->latt->pntsv*lt->editlatt->latt->pntsw;
460                 
461                 tv=transvmain= MEM_callocN(a*sizeof(TransVert), "maketransverts latt");
462                 
463                 while(a--) {
464                         if(bp->f1 & SELECT) {
465                                 if(bp->hide==0) {
466                                         copy_v3_v3(tv->oldloc, bp->vec);
467                                         tv->loc= bp->vec;
468                                         tv->flag= bp->f1 & SELECT;
469                                         tv++;
470                                         tottrans++;
471                                 }
472                         }
473                         bp++;
474                 }
475         }
476         
477         if(!tottrans && transvmain) {
478                 /* prevent memory leak. happens for curves/latticies due to */
479                 /* difficult condition of adding points to trans data */
480                 MEM_freeN(transvmain);
481                 transvmain= NULL;
482         }
483
484         /* cent etc */
485         tv= transvmain;
486         total= 0.0;
487         for(a=0; a<tottrans; a++, tv++) {
488                 if(tv->flag & SELECT) {
489                         add_v3_v3(centroid, tv->oldloc);
490                         total += 1.0f;
491                         DO_MINMAX(tv->oldloc, min, max);
492                 }
493         }
494         if(total != 0.0f) {
495                 mul_v3_fl(centroid, 1.0f/total);
496         }
497
498         mid_v3_v3v3(center, min, max);
499 }
500
501 /* *********************** operators ******************** */
502
503 static int snap_sel_to_grid(bContext *C, wmOperator *UNUSED(op))
504 {
505         extern float originmat[3][3];   /* XXX object.c */
506         Main *bmain= CTX_data_main(C);
507         Object *obedit= CTX_data_edit_object(C);
508         Scene *scene= CTX_data_scene(C);
509         RegionView3D *rv3d= CTX_wm_region_data(C);
510         TransVert *tv;
511         float gridf, imat[3][3], bmat[3][3], vec[3];
512         int a;
513
514         gridf= rv3d->gridview;
515
516         if(obedit) {
517                 tottrans= 0;
518                 
519                 if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
520                         make_trans_verts(obedit, bmat[0], bmat[1], 0);
521                 if(tottrans==0) return OPERATOR_CANCELLED;
522                 
523                 copy_m3_m4(bmat, obedit->obmat);
524                 invert_m3_m3(imat, bmat);
525                 
526                 tv= transvmain;
527                 for(a=0; a<tottrans; a++, tv++) {
528                         
529                         VECCOPY(vec, tv->loc);
530                         mul_m3_v3(bmat, vec);
531                         add_v3_v3(vec, obedit->obmat[3]);
532                         vec[0]= gridf*floorf(0.5f+ vec[0]/gridf);
533                         vec[1]= gridf*floorf(0.5f+ vec[1]/gridf);
534                         vec[2]= gridf*floorf(0.5f+ vec[2]/gridf);
535                         sub_v3_v3(vec, obedit->obmat[3]);
536                         
537                         mul_m3_v3(imat, vec);
538                         VECCOPY(tv->loc, vec);
539                 }
540                 
541                 special_transvert_update(obedit);
542                 
543                 MEM_freeN(transvmain);
544                 transvmain= NULL;
545         
546         }
547         else {
548
549                 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
550                         if(ob->mode & OB_MODE_POSE) {
551                                 bPoseChannel *pchan;
552                                 bArmature *arm= ob->data;
553                                 
554                                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
555                                         if(pchan->bone->flag & BONE_SELECTED) {
556                                                 if(pchan->bone->layer & arm->layer) {
557                                                         if((pchan->bone->flag & BONE_CONNECTED)==0) { 
558                                                                 float vecN[3], nLoc[3]; 
559                                                                 
560                                                                 /* get nearest grid point to snap to */
561                                                                 VECCOPY(nLoc, pchan->pose_mat[3]);
562                                                                 vec[0]= gridf * (float)(floor(0.5f+ nLoc[0]/gridf));
563                                                                 vec[1]= gridf * (float)(floor(0.5f+ nLoc[1]/gridf));
564                                                                 vec[2]= gridf * (float)(floor(0.5f+ nLoc[2]/gridf));
565                                                                 
566                                                                 /* get bone-space location of grid point */
567                                                                 armature_loc_pose_to_bone(pchan, vec, vecN);
568                                                                 
569                                                                 /* adjust location */
570                                                                 if ((pchan->protectflag & OB_LOCK_LOCX)==0)     
571                                                                         pchan->loc[0]= vecN[0];
572                                                                 if ((pchan->protectflag & OB_LOCK_LOCY)==0)     
573                                                                         pchan->loc[0]= vecN[1];
574                                                                 if ((pchan->protectflag & OB_LOCK_LOCZ)==0)     
575                                                                         pchan->loc[0]= vecN[2];
576                                                         }
577                                                         /* if the bone has a parent and is connected to the parent, 
578                                                          * don't do anything - will break chain unless we do auto-ik. 
579                                                          */
580                                                 }
581                                         }
582                                 }
583                                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
584                                 
585                                 /* auto-keyframing */
586 // XXX                          autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
587                                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
588                         }
589                         else {
590                                 ob->recalc |= OB_RECALC_OB;
591                                 
592                                 vec[0]= -ob->obmat[3][0]+gridf*floorf(0.5f+ ob->obmat[3][0]/gridf);
593                                 vec[1]= -ob->obmat[3][1]+gridf*floorf(0.5f+ ob->obmat[3][1]/gridf);
594                                 vec[2]= -ob->obmat[3][2]+gridf*floorf(0.5f+ ob->obmat[3][2]/gridf);
595                                 
596                                 if(ob->parent) {
597                                         where_is_object(scene, ob);
598                                         
599                                         invert_m3_m3(imat, originmat);
600                                         mul_m3_v3(imat, vec);
601                                 }
602                                 if ((ob->protectflag & OB_LOCK_LOCX)==0)
603                                         ob->loc[0]+= vec[0];
604                                 if ((ob->protectflag & OB_LOCK_LOCY)==0)
605                                         ob->loc[1]+= vec[1];
606                                 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
607                                         ob->loc[2]+= vec[2];
608                                 
609                                 /* auto-keyframing */
610 // XXX                          autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
611                         }
612                 }
613                 CTX_DATA_END;
614         }
615
616         DAG_ids_flush_update(bmain, 0);
617         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
618         
619         return OPERATOR_FINISHED;
620 }
621
622 void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot)
623 {
624         
625         /* identifiers */
626         ot->name= "Snap Selection to Grid";
627         ot->description= "Snap selected item(s) to nearest grid node";
628         ot->idname= "VIEW3D_OT_snap_selected_to_grid";
629         
630         /* api callbacks */
631         ot->exec= snap_sel_to_grid;
632         ot->poll= ED_operator_region_view3d_active;
633         
634         /* flags */
635         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
636 }
637
638 /* *************************************************** */
639
640 static int snap_sel_to_curs(bContext *C, wmOperator *UNUSED(op))
641 {
642         extern float originmat[3][3];   /* XXX object.c */
643         Main *bmain= CTX_data_main(C);
644         Object *obedit= CTX_data_edit_object(C);
645         Scene *scene= CTX_data_scene(C);
646         View3D *v3d= CTX_wm_view3d(C);
647         TransVert *tv;
648         float *curs, imat[3][3], bmat[3][3], vec[3];
649         int a;
650
651         curs= give_cursor(scene, v3d);
652
653         if(obedit) {
654                 tottrans= 0;
655                 
656                 if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
657                         make_trans_verts(obedit, bmat[0], bmat[1], 0);
658                 if(tottrans==0) return OPERATOR_CANCELLED;
659                 
660                 copy_m3_m4(bmat, obedit->obmat);
661                 invert_m3_m3(imat, bmat);
662                 
663                 tv= transvmain;
664                 for(a=0; a<tottrans; a++, tv++) {
665                         sub_v3_v3v3(vec, curs, obedit->obmat[3]);
666                         mul_m3_v3(imat, vec);
667                         copy_v3_v3(tv->loc, vec);
668                 }
669                 
670                 special_transvert_update(obedit);
671                 
672                 MEM_freeN(transvmain);
673                 transvmain= NULL;
674                 
675         }
676         else {
677                 CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) {
678                         if(ob->mode & OB_MODE_POSE) {
679                                 bPoseChannel *pchan;
680                                 bArmature *arm= ob->data;
681                                 float cursp[3];
682                                 
683                                 invert_m4_m4(ob->imat, ob->obmat);
684                                 VECCOPY(cursp, curs);
685                                 mul_m4_v3(ob->imat, cursp);
686                                 
687                                 for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
688                                         if(pchan->bone->flag & BONE_SELECTED) {
689                                                 if(pchan->bone->layer & arm->layer) {
690                                                         if((pchan->bone->flag & BONE_CONNECTED)==0) { 
691                                                                 float curspn[3];
692                                                                 
693                                                                 /* get location of cursor in bone-space */
694                                                                 armature_loc_pose_to_bone(pchan, cursp, curspn);
695                                                                 
696                                                                 /* copy new position */
697                                                                 if ((pchan->protectflag & OB_LOCK_LOCX)==0)     
698                                                                         pchan->loc[0]= curspn[0];
699                                                                 if ((pchan->protectflag & OB_LOCK_LOCY)==0)     
700                                                                         pchan->loc[1]= curspn[1];
701                                                                 if ((pchan->protectflag & OB_LOCK_LOCZ)==0)     
702                                                                         pchan->loc[2]= curspn[2];
703                                                         }
704                                                         /* if the bone has a parent and is connected to the parent, 
705                                                          * don't do anything - will break chain unless we do auto-ik. 
706                                                          */
707                                                 }
708                                         }
709                                 }
710                                 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
711                                 
712                                 /* auto-keyframing */
713 // XXX                          autokeyframe_pose_cb_func(ob, TFM_TRANSLATION, 0);
714                                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
715                         }
716                         else {
717                                 ob->recalc |= OB_RECALC_OB;
718                                 
719                                 vec[0]= -ob->obmat[3][0] + curs[0];
720                                 vec[1]= -ob->obmat[3][1] + curs[1];
721                                 vec[2]= -ob->obmat[3][2] + curs[2];
722                                 
723                                 if(ob->parent) {
724                                         where_is_object(scene, ob);
725                                         
726                                         invert_m3_m3(imat, originmat);
727                                         mul_m3_v3(imat, vec);
728                                 }
729                                 if ((ob->protectflag & OB_LOCK_LOCX)==0)
730                                         ob->loc[0]+= vec[0];
731                                 if ((ob->protectflag & OB_LOCK_LOCY)==0)
732                                         ob->loc[1]+= vec[1];
733                                 if ((ob->protectflag & OB_LOCK_LOCZ)==0)
734                                         ob->loc[2]+= vec[2];
735                                 
736                                 /* auto-keyframing */
737 // XXX                          autokeyframe_ob_cb_func(ob, TFM_TRANSLATION);
738                         }
739                 }
740                 CTX_DATA_END;
741         }
742
743         DAG_ids_flush_update(bmain, 0);
744         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
745         
746         return OPERATOR_FINISHED;
747 }
748
749 void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot)
750 {
751         
752         /* identifiers */
753         ot->name= "Snap Selection to Cursor";
754         ot->description= "Snap selected item(s) to cursor";
755         ot->idname= "VIEW3D_OT_snap_selected_to_cursor";
756         
757         /* api callbacks */
758         ot->exec= snap_sel_to_curs;
759         ot->poll= ED_operator_view3d_active;
760         
761         /* flags */
762         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
763 }
764
765 /* *************************************************** */
766
767 static int snap_curs_to_grid(bContext *C, wmOperator *UNUSED(op))
768 {
769         Scene *scene= CTX_data_scene(C);
770         RegionView3D *rv3d= CTX_wm_region_data(C);
771         View3D *v3d= CTX_wm_view3d(C);
772         float gridf, *curs;
773
774         gridf= rv3d->gridview;
775         curs= give_cursor(scene, v3d);
776
777         curs[0]= gridf*floorf(0.5f+curs[0]/gridf);
778         curs[1]= gridf*floorf(0.5f+curs[1]/gridf);
779         curs[2]= gridf*floorf(0.5f+curs[2]/gridf);
780         
781         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);        // hrm
782         
783         return OPERATOR_FINISHED;
784 }
785
786 void VIEW3D_OT_snap_cursor_to_grid(wmOperatorType *ot)
787 {
788         
789         /* identifiers */
790         ot->name= "Snap Cursor to Grid";
791         ot->description= "Snap cursor to nearest grid node";
792         ot->idname= "VIEW3D_OT_snap_cursor_to_grid";
793         
794         /* api callbacks */
795         ot->exec= snap_curs_to_grid;
796         ot->poll= ED_operator_region_view3d_active;
797         
798         /* flags */
799         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
800 }
801
802 /* **************************************************** */
803
804 static int snap_curs_to_sel(bContext *C, wmOperator *UNUSED(op))
805 {
806         Object *obedit= CTX_data_edit_object(C);
807         Scene *scene= CTX_data_scene(C);
808         View3D *v3d= CTX_wm_view3d(C);
809         TransVert *tv;
810         float *curs, bmat[3][3], vec[3], min[3], max[3], centroid[3];
811         int count, a;
812
813         curs= give_cursor(scene, v3d);
814
815         count= 0;
816         INIT_MINMAX(min, max);
817         centroid[0]= centroid[1]= centroid[2]= 0.0;
818
819         if(obedit) {
820                 tottrans=0;
821                 
822                 if ELEM6(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE, OB_MBALL) 
823                         make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS|TM_SKIP_HANDLES);
824                 if(tottrans==0) return OPERATOR_CANCELLED;
825                 
826                 copy_m3_m4(bmat, obedit->obmat);
827                 
828                 tv= transvmain;
829                 for(a=0; a<tottrans; a++, tv++) {
830                         VECCOPY(vec, tv->loc);
831                         mul_m3_v3(bmat, vec);
832                         add_v3_v3(vec, obedit->obmat[3]);
833                         add_v3_v3(centroid, vec);
834                         DO_MINMAX(vec, min, max);
835                 }
836                 
837                 if(v3d->around==V3D_CENTROID) {
838                         mul_v3_fl(centroid, 1.0f/(float)tottrans);
839                         VECCOPY(curs, centroid);
840                 }
841                 else {
842                         mid_v3_v3v3(curs, min, max);
843                 }
844                 MEM_freeN(transvmain);
845                 transvmain= NULL;
846         }
847         else {
848                 Object *obact= CTX_data_active_object(C);
849                 
850                 if(obact && (obact->mode & OB_MODE_POSE)) {
851                         bArmature *arm= obact->data;
852                         bPoseChannel *pchan;
853                         for (pchan = obact->pose->chanbase.first; pchan; pchan=pchan->next) {
854                                 if(arm->layer & pchan->bone->layer) {
855                                         if(pchan->bone->flag & BONE_SELECTED) {
856                                                 VECCOPY(vec, pchan->pose_head);
857                                                 mul_m4_v3(obact->obmat, vec);
858                                                 add_v3_v3(centroid, vec);
859                                                 DO_MINMAX(vec, min, max);
860                                                 count++;
861                                         }
862                                 }
863                         }
864                 }
865                 else {
866                         CTX_DATA_BEGIN(C, Object*, ob, selected_objects) {
867                                 VECCOPY(vec, ob->obmat[3]);
868                                 add_v3_v3(centroid, vec);
869                                 DO_MINMAX(vec, min, max);
870                                 count++;
871                         }
872                         CTX_DATA_END;
873                 }
874                 if(count) {
875                         if(v3d->around==V3D_CENTROID) {
876                                 mul_v3_fl(centroid, 1.0f/(float)count);
877                                 VECCOPY(curs, centroid);
878                         }
879                         else {
880                                 mid_v3_v3v3(curs, min, max);
881                         }
882                 }
883         }
884         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
885         
886         return OPERATOR_FINISHED;
887 }
888
889 void VIEW3D_OT_snap_cursor_to_selected(wmOperatorType *ot)
890 {
891         
892         /* identifiers */
893         ot->name= "Snap Cursor to Selected";
894         ot->description= "Snap cursor to center of selected item(s)"; 
895         ot->idname= "VIEW3D_OT_snap_cursor_to_selected";
896         
897         /* api callbacks */
898         ot->exec= snap_curs_to_sel;
899         ot->poll= ED_operator_view3d_active;
900         
901         /* flags */
902         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
903 }
904
905 /* ********************************************** */
906
907 static int snap_curs_to_active(bContext *C, wmOperator *UNUSED(op))
908 {
909         Object *obedit= CTX_data_edit_object(C);
910         Object *obact= CTX_data_active_object(C);
911         Scene *scene= CTX_data_scene(C);
912         View3D *v3d= CTX_wm_view3d(C);
913         float *curs;
914         
915         curs = give_cursor(scene, v3d);
916
917         if (obedit)  {
918                 if (obedit->type == OB_MESH) {
919                         /* check active */
920                         Mesh *me= obedit->data;
921                         BMEditSelection ese;
922                         
923                         if (EDBM_get_actSelection(me->edit_btmesh, &ese)) {
924                                 EDBM_editselection_center(me->edit_btmesh, curs, &ese);
925                         }
926                         
927                         mul_m4_v3(obedit->obmat, curs);
928                 }
929         }
930         else {
931                 if (obact) {
932                         VECCOPY(curs, obact->obmat[3]);
933                 }
934         }
935         
936         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
937         return OPERATOR_FINISHED;
938 }
939
940 void VIEW3D_OT_snap_cursor_to_active(wmOperatorType *ot)
941 {
942         
943         /* identifiers */
944         ot->name= "Snap Cursor to Active";
945         ot->description= "Snap cursor to active item";
946         ot->idname= "VIEW3D_OT_snap_cursor_to_active";
947         
948         /* api callbacks */
949         ot->exec= snap_curs_to_active;
950         ot->poll= ED_operator_view3d_active;
951         
952         /* flags */
953         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
954 }
955
956 /* **************************************************** */
957 /*New Code - Snap Cursor to Center -*/
958 static int snap_curs_to_center(bContext *C, wmOperator *UNUSED(op))
959 {
960         Scene *scene= CTX_data_scene(C);
961         View3D *v3d= CTX_wm_view3d(C);
962         float *curs;
963         curs= give_cursor(scene, v3d);
964
965         curs[0]= 0.0;
966         curs[1]= 0.0;
967         curs[2]= 0.0;
968         
969         WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, v3d);
970         
971         return OPERATOR_FINISHED;
972 }
973
974 void VIEW3D_OT_snap_cursor_to_center(wmOperatorType *ot)
975 {
976         
977         /* identifiers */
978         ot->name= "Snap Cursor to Center";
979         ot->description= "Snap cursor to the Center";
980         ot->idname= "VIEW3D_OT_snap_cursor_to_center";
981         
982         /* api callbacks */ 
983         ot->exec= snap_curs_to_center;
984         ot->poll= ED_operator_view3d_active;
985         
986         /* flags */
987            ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
988 }
989
990 /* **************************************************** */
991
992
993 int minmax_verts(Object *obedit, float *min, float *max)
994 {
995         TransVert *tv;
996         float centroid[3], vec[3], bmat[3][3];
997         int a;
998
999         tottrans=0;
1000         if ELEM5(obedit->type, OB_ARMATURE, OB_LATTICE, OB_MESH, OB_SURF, OB_CURVE) 
1001                 make_trans_verts(obedit, bmat[0], bmat[1], TM_ALL_JOINTS);
1002         
1003         if(tottrans==0) return 0;
1004
1005         copy_m3_m4(bmat, obedit->obmat);
1006         
1007         tv= transvmain;
1008         for(a=0; a<tottrans; a++, tv++) {               
1009                 VECCOPY(vec, tv->maploc);
1010                 mul_m3_v3(bmat, vec);
1011                 add_v3_v3(vec, obedit->obmat[3]);
1012                 add_v3_v3(centroid, vec);
1013                 DO_MINMAX(vec, min, max);               
1014         }
1015         
1016         MEM_freeN(transvmain);
1017         transvmain= NULL;
1018         
1019         return 1;
1020 }