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