Merge with blender svn -> svn merge -r 12064:12150 https://svn.blender.org/svnroot...
[blender-staging.git] / source / blender / src / transform_generics.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34 #include <math.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_action_types.h"
39 #include "DNA_armature_types.h"
40 #include "DNA_constraint_types.h"
41 #include "DNA_curve_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_mesh_types.h"
44 #include "DNA_modifier_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_object_force.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_space_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_userdef_types.h"
51 #include "DNA_view3d_types.h"
52
53 #include "BIF_screen.h"
54 #include "BIF_resources.h"
55 #include "BIF_mywindow.h"
56 #include "BIF_gl.h"
57 #include "BIF_editaction.h"
58 #include "BIF_editarmature.h"
59 #include "BIF_editmesh.h"
60 #include "BIF_editnla.h"
61 #include "BIF_editsima.h"
62 #include "BIF_meshtools.h"
63 #include "BIF_retopo.h"
64
65 #ifdef WITH_VERSE
66 #include "BIF_verse.h"
67 #endif
68
69 #include "BKE_action.h"
70 #include "BKE_anim.h"
71 #include "BKE_armature.h"
72 #include "BKE_cloth.h"
73 #include "BKE_curve.h"
74 #include "BKE_depsgraph.h"
75 #include "BKE_displist.h"
76 #include "BKE_depsgraph.h"
77 #include "BKE_global.h"
78 #include "BKE_group.h"
79 #include "BKE_ipo.h"
80 #include "BKE_lattice.h"
81 #include "BKE_key.h"
82 #include "BKE_mesh.h"
83 #include "BKE_modifier.h"
84 #include "BKE_object.h"
85 #include "BKE_utildefines.h"
86
87 #ifdef WITH_VERSE
88 #include "BKE_verse.h"
89 #endif
90
91 #include "BSE_view.h"
92 #include "BSE_editaction_types.h"
93 #include "BDR_unwrapper.h"
94
95 #include "BLI_arithb.h"
96 #include "BLI_blenlib.h"
97 #include "BLI_editVert.h"
98 #include "BLI_rand.h"
99
100 #include "blendef.h"
101
102 #include "mydevice.h"
103
104 #include "transform.h"
105
106 extern ListBase editNurb;
107 extern ListBase editelems;
108
109 extern TransInfo Trans; /* From transform.c */
110
111 /* ************************** Functions *************************** */
112
113
114 void getViewVector(float coord[3], float vec[3])
115 {
116         TransInfo *t = BIF_GetTransInfo();
117
118         if (t->persp)
119         {
120                 float p1[4], p2[4];
121
122                 VECCOPY(p1, coord);
123                 p1[3] = 1.0f;
124                 VECCOPY(p2, p1);
125                 p2[3] = 1.0f;
126                 Mat4MulVec4fl(t->viewmat, p2);
127
128                 p2[0] = 2.0f * p2[0];
129                 p2[1] = 2.0f * p2[1];
130                 p2[2] = 2.0f * p2[2];
131
132                 Mat4MulVec4fl(t->viewinv, p2);
133
134                 VecSubf(vec, p1, p2);
135         }
136         else {
137                 VECCOPY(vec, t->viewinv[2]);
138         }
139         Normalize(vec);
140 }
141
142 /* ************************** GENERICS **************************** */
143
144 static void clipMirrorModifier(TransInfo *t, Object *ob)
145 {
146         ModifierData *md= ob->modifiers.first;
147         float tolerance[3] = {0.0f, 0.0f, 0.0f};
148         int axis = 0;
149
150         for (; md; md=md->next) {
151                 if (md->type==eModifierType_Mirror) {
152                         MirrorModifierData *mmd = (MirrorModifierData*) md;     
153                 
154                         if(mmd->flag & MOD_MIR_CLIPPING) {
155                                 if(mmd->flag & MOD_MIR_AXIS_X) {
156                                         axis |= 1;
157                                         tolerance[0] = mmd->tolerance;
158                                 }
159                                 if(mmd->flag & MOD_MIR_AXIS_Y) {
160                                         axis |= 2;
161                                         tolerance[1] = mmd->tolerance;
162                                 }
163                                 if(mmd->flag & MOD_MIR_AXIS_Z) {
164                                         axis |= 4;
165                                         tolerance[2] = mmd->tolerance;
166                                 }
167                         }
168                 }
169         }
170         if (axis) {
171                 TransData *td = t->data;
172                 int i;
173                 
174                 for(i = 0 ; i < t->total; i++, td++) {
175                         if (td->flag & TD_NOACTION)
176                                 break;
177                         if (td->loc==NULL)
178                                 break;
179                         
180                         if(axis & 1) {
181                                 if(fabs(td->iloc[0])<=tolerance[0] || td->loc[0]*td->iloc[0]<0.0f) td->loc[0]= 0.0f;
182                         }
183                         
184                         if(axis & 2) {
185                                 if(fabs(td->iloc[1])<=tolerance[1] || td->loc[1]*td->iloc[1]<0.0f) td->loc[1]= 0.0f;
186                         }
187                         if(axis & 4) {
188                                 if(fabs(td->iloc[2])<=tolerance[2] || td->loc[2]*td->iloc[2]<0.0f) td->loc[2]= 0.0f;
189                         }
190                 }
191         }
192 }
193
194 /* assumes G.obedit set to mesh object */
195 static void editmesh_apply_to_mirror(TransInfo *t)
196 {
197         TransData *td = t->data;
198         EditVert *eve;
199         int i;
200         
201         for(i = 0 ; i < t->total; i++, td++) {
202                 if (td->flag & TD_NOACTION)
203                         break;
204                 if (td->loc==NULL)
205                         break;
206                 
207                 eve= td->tdmir;
208                 if(eve) {
209                         eve->co[0]= -td->loc[0];
210                         eve->co[1]= td->loc[1];
211                         eve->co[2]= td->loc[2];
212                 }               
213         }               
214 }
215
216 /* called for updating while transform acts, once per redraw */
217 void recalcData(TransInfo *t)
218 {
219         Base *base;
220 #ifdef WITH_VERSE
221         struct TransData *td;
222 #endif
223         
224         if (t->spacetype == SPACE_ACTION) {
225                 Object *ob= OBACT;
226                 void *data;
227                 short context;
228                 
229                 /* determine what type of data we are operating on */
230                 data = get_action_context(&context);
231                 if (data == NULL) return;
232         
233                 if (G.saction->lock) {
234                         if (context == ACTCONT_ACTION) {
235                                 if(ob) {
236                                         ob->ctime= -1234567.0f;
237                                         if(ob->pose || ob_get_key(ob))
238                                                 DAG_object_flush_update(G.scene, ob, OB_RECALC);
239                                         else
240                                                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
241                                 }
242                         }
243                         else if (context == ACTCONT_SHAPEKEY) {
244                                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
245                         }
246                 }
247         }       
248         else if (t->spacetype == SPACE_NLA) {
249                 if (G.snla->lock) {
250                         for (base=G.scene->base.first; base; base=base->next) {
251                                 if (base->flag & BA_HAS_RECALC_OB)
252                                         base->object->recalc |= OB_RECALC_OB;
253                                 if (base->flag & BA_HAS_RECALC_DATA)
254                                         base->object->recalc |= OB_RECALC_DATA;
255                                 
256                                 if (base->object->recalc) 
257                                         base->object->ctime= -1234567.0f;       // eveil! 
258                         }
259                         
260                         DAG_scene_flush_update(G.scene, screen_view3d_layers());
261                 }
262         }
263         else if (G.obedit) {
264                 if (G.obedit->type == OB_MESH) {
265                         if(t->spacetype==SPACE_IMAGE) {
266                                 flushTransUVs(t);
267                                 if (G.sima->flag & SI_LIVE_UNWRAP)
268                                         unwrap_lscm_live_re_solve();
269                         } else {
270                         
271                                 retopo_do_all();
272         
273                                 /* mirror modifier clipping? */
274                                 if(t->state != TRANS_CANCEL)
275                                         clipMirrorModifier(t, G.obedit);
276                                 
277                                 if(G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR)
278                                         editmesh_apply_to_mirror(t);
279                                 
280                                 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);  /* sets recalc flags */
281                                 
282                                 recalc_editnormals();
283                         }
284                 }
285                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
286                         Nurb *nu= editNurb.first;
287                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);  /* sets recalc flags */
288                         
289                         while(nu) {
290                                 test2DNurb(nu);
291                                 testhandlesNurb(nu); /* test for bezier too */
292                                 nu= nu->next;
293                         }
294
295                         retopo_do_all();
296                 }
297                 else if(G.obedit->type==OB_ARMATURE){   /* no recalc flag, does pose */
298                         bArmature *arm= G.obedit->data;
299                         EditBone *ebo;
300                         
301                         /* Ensure all bones are correctly adjusted */
302                         for (ebo=G.edbo.first; ebo; ebo=ebo->next){
303                                 
304                                 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
305                                         /* If this bone has a parent tip that has been moved */
306                                         if (ebo->parent->flag & BONE_TIPSEL){
307                                                 VECCOPY (ebo->head, ebo->parent->tail);
308                                                 if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
309                                         }
310                                         /* If this bone has a parent tip that has NOT been moved */
311                                         else{
312                                                 VECCOPY (ebo->parent->tail, ebo->head);
313                                                 if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
314                                         }
315                                 }
316                                 
317                                 /* on extrude bones, oldlength==0.0f, so we scale radius of points */
318                                 ebo->length= VecLenf(ebo->head, ebo->tail);
319                                 if(ebo->oldlength==0.0f) {
320                                         ebo->rad_head= 0.25f*ebo->length;
321                                         ebo->rad_tail= 0.10f*ebo->length;
322                                         ebo->dist= 0.25f*ebo->length;
323                                         if(ebo->parent) {
324                                                 if(ebo->rad_head > ebo->parent->rad_tail)
325                                                         ebo->rad_head= ebo->parent->rad_tail;
326                                         }
327                                 }
328                                 else if(t->mode!=TFM_BONE_ENVELOPE) {
329                                         /* if bones change length, lets do that for the deform distance as well */
330                                         ebo->dist*= ebo->length/ebo->oldlength;
331                                         ebo->rad_head*= ebo->length/ebo->oldlength;
332                                         ebo->rad_tail*= ebo->length/ebo->oldlength;
333                                         ebo->oldlength= ebo->length;
334                                 }
335                         }
336                         if(arm->flag & ARM_MIRROR_EDIT) 
337                                 transform_armature_mirror_update();
338                         
339                 }
340                 else if(G.obedit->type==OB_LATTICE) {
341                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);  /* sets recalc flags */
342                         
343                         if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
344                 }
345                 else {
346                         DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);  /* sets recalc flags */
347                 }
348         }
349         else if( (t->flag & T_POSE) && t->poseobj) {
350                 Object *ob= t->poseobj;
351                 bArmature *arm= ob->data;
352                 
353                 /* old optimize trick... this enforces to bypass the depgraph */
354                 if (!(arm->flag & ARM_DELAYDEFORM)) {
355                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);  /* sets recalc flags */
356                         
357                         /* bah, softbody exception... recalcdata doesnt reset */
358                         for(base= FIRSTBASE; base; base= base->next) {
359                                 if(base->object->recalc & OB_RECALC_DATA)
360                                 {                                       
361                                         ClothModifierData *clmd = NULL;
362                                         
363                                         if(modifiers_isSoftbodyEnabled(base->object)) {
364                                                 base->object->softflag |= OB_SB_REDO;
365                                         }
366                                         else if(modifiers_isClothEnabled(ob)) {
367                                                 cloth_free_modifier(modifiers_isClothEnabled(ob));
368                                         }
369                                         
370                                 }
371                         }
372                 }
373                 else
374                         where_is_pose(ob);
375         }
376         else {
377                 for(base= FIRSTBASE; base; base= base->next) {
378                         Object *ob= base->object;
379                         
380                         /* this flag is from depgraph, was stored in nitialize phase, handled in drawview.c */
381                         if(base->flag & BA_HAS_RECALC_OB)
382                                 ob->recalc |= OB_RECALC_OB;
383                         if(base->flag & BA_HAS_RECALC_DATA)
384                                 ob->recalc |= OB_RECALC_DATA;
385                         
386                         /* thanks to ob->ctime usage, ipos are not called in where_is_object,
387                            unless we edit ipokeys */
388                         if(base->flag & BA_DO_IPO) {
389                                 if(ob->ipo) {
390                                         IpoCurve *icu;
391                                         
392                                         ob->ctime= -1234567.0;
393                                         
394                                         icu= ob->ipo->curve.first;
395                                         while(icu) {
396                                                 calchandles_ipocurve(icu);
397                                                 icu= icu->next;
398                                         }
399                                 }                               
400                         }
401                         
402                         /* softbody & cloth exception */
403                         if(ob->recalc & OB_RECALC_DATA)
404                         {
405                                 ClothModifierData *clmd = NULL;
406                                 
407                                 if(modifiers_isSoftbodyEnabled(ob)) {
408                                                 ob->softflag |= OB_SB_REDO;
409                                 }
410                                 else if(modifiers_isClothEnabled(ob)) {
411                                         cloth_free_modifier(modifiers_isClothEnabled(ob));
412                                 }
413                         }
414                         
415                         /* proxy exception */
416                         if(ob->proxy)
417                                 ob->proxy->recalc |= ob->recalc;
418                         if(ob->proxy_group)
419                                 group_tag_recalc(ob->proxy_group->dup_group);
420                 } 
421         }
422
423 #ifdef WITH_VERSE
424         for (td = t->data; td < t->data + t->total; td++) {
425                 if(td->flag & TD_VERSE_VERT) {
426                         if(td->verse)
427                                 send_versevert_pos((VerseVert*)td->verse);
428                 }
429                 else if(td->flag & TD_VERSE_OBJECT)
430                         if(td->verse) b_verse_send_transformation((Object*)td->verse);
431         }
432 #endif
433         
434         /* update shaded drawmode while transform */
435         if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
436                 reshadeall_displist();
437         
438 }
439
440 void drawLine(float *center, float *dir, char axis, short options)
441 {
442         extern void make_axis_color(char *col, char *col2, char axis);  // drawview.c
443         float v1[3], v2[3], v3[3];
444         char col[3], col2[3];
445         
446         //if(G.obedit) mymultmatrix(G.obedit->obmat);   // sets opengl viewing
447
448         VecCopyf(v3, dir);
449         VecMulf(v3, G.vd->far);
450         
451         VecSubf(v2, center, v3);
452         VecAddf(v1, center, v3);
453
454         if (options & DRAWLIGHT) {
455                 col[0] = col[1] = col[2] = 220;
456         }
457         else {
458                 BIF_GetThemeColor3ubv(TH_GRID, col);
459         }
460         make_axis_color(col, col2, axis);
461         glColor3ubv((GLubyte *)col2);
462
463         setlinestyle(0);
464         glBegin(GL_LINE_STRIP); 
465                 glVertex3fv(v1); 
466                 glVertex3fv(v2); 
467         glEnd();
468         
469         myloadmatrix(G.vd->viewmat);
470 }
471
472 void initTrans (TransInfo *t)
473 {
474         /* moving: is shown in drawobject() (transform color) */
475         if(G.obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
476         else G.moving= G_TRANSFORM_OBJ;
477
478         t->data = NULL;
479         t->ext = NULL;
480
481         t->flag = 0;
482         t->num.flag = 0;
483
484
485         /* setting PET flag */
486         if ((t->context & CTX_NO_PET) == 0 && (G.scene->proportional)) {
487                 t->flag |= T_PROP_EDIT;
488                 if(G.scene->proportional==2) t->flag |= T_PROP_CONNECTED;       // yes i know, has to become define
489         }
490
491         getmouseco_areawin(t->imval);
492         t->con.imval[0] = t->imval[0];
493         t->con.imval[1] = t->imval[1];
494
495         t->transform            = NULL;
496         t->handleEvent          = NULL;
497         t->customData           = NULL;
498
499         t->total                        =
500                 t->num.idx              =
501                 t->num.idx_max  =
502                 t->num.ctrl[0]  = 
503                 t->num.ctrl[1]  = 
504                 t->num.ctrl[2]  = 0;
505
506         t->val = 0.0f;
507
508         t->num.val[0]           = 
509                 t->num.val[1]   = 
510                 t->num.val[2]   = 0.0f;
511
512         t->vec[0]                       =
513                 t->vec[1]               =
514                 t->vec[2]               = 0.0f;
515         
516         t->center[0]            =
517                 t->center[1]    =
518                 t->center[2]    = 0.0f;
519         
520         Mat3One(t->mat);
521         
522         t->spacetype = curarea->spacetype;
523         if(t->spacetype==SPACE_VIEW3D) {
524                 if(G.vd->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
525                 t->around = G.vd->around;
526         } else if(t->spacetype==SPACE_IMAGE) {
527                 t->around = G.v2d->around;
528         }
529         else
530                 t->around = V3D_CENTER;
531
532         setTransformViewMatrices(t);
533 }
534
535 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
536 void postTrans (TransInfo *t) 
537 {
538         TransData *td;
539
540         G.moving = 0; // Set moving flag off (display as usual)
541 #ifdef WITH_VERSE
542
543         for (td = t->data; td < t->data + t->total; td++) {
544                 if(td->flag & TD_VERSE_VERT) {
545                         if(td->verse) send_versevert_pos((VerseVert*)td->verse);
546                 }
547                 else if(td->flag & TD_VERSE_OBJECT) {
548                         if(td->verse) {
549                                 struct VNode *vnode;
550                                 vnode = (VNode*)((Object*)td->verse)->vnode;
551                                 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
552                                 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
553                                 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
554                                 b_verse_send_transformation((Object*)td->verse);
555                         }
556                 }
557         }
558 #endif
559
560         stopConstraint(t);
561         
562         /* postTrans can be called when nothing is selected, so data is NULL already */
563         if (t->data) {
564                 int a;
565
566                 /* since ipokeys are optional on objects, we mallocced them per trans-data */
567                 for(a=0, td= t->data; a<t->total; a++, td++) {
568                         if(td->tdi) MEM_freeN(td->tdi);
569                 }
570                 MEM_freeN(t->data);
571         }
572
573         if (t->ext) MEM_freeN(t->ext);
574         if (t->data2d) {
575                 MEM_freeN(t->data2d);
576                 t->data2d= NULL;
577         }
578         
579         if ((t->flag & T_FREE_CUSTOMDATA) && t->customData != NULL) {
580                 MEM_freeN(t->customData);
581         }
582
583         if(t->spacetype==SPACE_IMAGE) {
584                 if (G.sima->flag & SI_LIVE_UNWRAP)
585                         unwrap_lscm_live_end(t->state == TRANS_CANCEL);
586         }
587 }
588
589 void applyTransObjects(TransInfo *t)
590 {
591         TransData *td;
592         
593         for (td = t->data; td < t->data + t->total; td++) {
594                 VECCOPY(td->iloc, td->loc);
595                 if (td->ext->rot) {
596                         VECCOPY(td->ext->irot, td->ext->rot);
597                 }
598                 if (td->ext->size) {
599                         VECCOPY(td->ext->isize, td->ext->size);
600                 }
601         }       
602         recalcData(t);
603
604
605 /* helper for below */
606 static void restore_ipokey(float *poin, float *old)
607 {
608         if(poin) {
609                 poin[0]= old[0];
610                 poin[-3]= old[3];
611                 poin[3]= old[6];
612         }
613 }
614
615 static void restoreElement(TransData *td) {
616         /* TransData for crease has no loc */
617         if (td->loc) {
618                 VECCOPY(td->loc, td->iloc);
619         }
620         if (td->val) {
621                 *td->val = td->ival;
622         }
623         if (td->ext) {
624                 if (td->ext->rot) {
625                         VECCOPY(td->ext->rot, td->ext->irot);
626                 }
627                 if (td->ext->size) {
628                         VECCOPY(td->ext->size, td->ext->isize);
629                 }
630                 if(td->flag & TD_USEQUAT) {
631                         if (td->ext->quat) {
632                                 QUATCOPY(td->ext->quat, td->ext->iquat);
633                         }
634                 }
635         }
636         if(td->tdi) {
637                 TransDataIpokey *tdi= td->tdi;
638                 
639                 restore_ipokey(tdi->locx, tdi->oldloc);
640                 restore_ipokey(tdi->locy, tdi->oldloc+1);
641                 restore_ipokey(tdi->locz, tdi->oldloc+2);
642
643                 restore_ipokey(tdi->rotx, tdi->oldrot);
644                 restore_ipokey(tdi->roty, tdi->oldrot+1);
645                 restore_ipokey(tdi->rotz, tdi->oldrot+2);
646                 
647                 restore_ipokey(tdi->sizex, tdi->oldsize);
648                 restore_ipokey(tdi->sizey, tdi->oldsize+1);
649                 restore_ipokey(tdi->sizez, tdi->oldsize+2);
650         }
651 }
652
653 void restoreTransObjects(TransInfo *t)
654 {
655         TransData *td;
656         
657         for (td = t->data; td < t->data + t->total; td++) {
658                 restoreElement(td);
659 #ifdef WITH_VERSE
660                 /* position of vertexes and object transformation matrix is sent
661                  * extra, becuase blender uses synchronous sending of vertexes
662                  * position as well object trans. matrix and it isn't possible to
663                  * send it in recalcData sometimes */
664                 if(td->flag & TD_VERSE_VERT) {
665                         if(td->verse) {
666                                 ((VerseVert*)td->verse)->flag |= VERT_POS_OBSOLETE;
667                         }
668                 }
669                 else if(td->flag & TD_VERSE_OBJECT)
670                         if(td->verse) {
671                                 struct VNode *vnode;
672                                 vnode = (VNode*)((Object*)td->verse)->vnode;
673                                 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
674                                 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
675                                 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
676                         }
677 #endif
678         }       
679         recalcData(t);
680 }
681
682 void calculateCenter2D(TransInfo *t)
683 {
684         if (t->flag & (T_EDIT|T_POSE)) {
685                 Object *ob= G.obedit?G.obedit:t->poseobj;
686                 float vec[3];
687                 
688                 VECCOPY(vec, t->center);
689                 Mat4MulVecfl(ob->obmat, vec);
690                 projectIntView(t, vec, t->center2d);
691         }
692         else {
693                 projectIntView(t, t->center, t->center2d);
694         }
695 }
696
697 void calculateCenterCursor(TransInfo *t)
698 {
699         float *cursor;
700
701         cursor = give_cursor();
702         VECCOPY(t->center, cursor);
703
704         /* If edit or pose mode, move cursor in local space */
705         if (t->flag & (T_EDIT|T_POSE)) {
706                 Object *ob = G.obedit?G.obedit:t->poseobj;
707                 float mat[3][3], imat[3][3];
708                 
709                 VecSubf(t->center, t->center, ob->obmat[3]);
710                 Mat3CpyMat4(mat, ob->obmat);
711                 Mat3Inv(imat, mat);
712                 Mat3MulVecfl(imat, t->center);
713         }
714         
715         calculateCenter2D(t);
716 }
717
718 void calculateCenterCursor2D(TransInfo *t)
719 {
720         float aspx=1.0, aspy=1.0;
721         
722         if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */
723                 transform_aspect_ratio_tface_uv(&aspx, &aspy);
724         if (G.v2d) {
725                 t->center[0] = G.v2d->cursor[0] * aspx; 
726                 t->center[1] = G.v2d->cursor[1] * aspy; 
727         }
728         calculateCenter2D(t);
729 }
730
731 void calculateCenterMedian(TransInfo *t)
732 {
733         float partial[3] = {0.0f, 0.0f, 0.0f};
734         int i;
735         
736         for(i = 0; i < t->total; i++) {
737                 if (t->data[i].flag & TD_SELECTED) {
738                         VecAddf(partial, partial, t->data[i].center);
739                 }
740                 else {
741                         /* 
742                            All the selected elements are at the head of the array 
743                            which means we can stop when it finds unselected data
744                         */
745                         break;
746                 }
747         }
748         if(i)
749                 VecMulf(partial, 1.0f / i);
750         VECCOPY(t->center, partial);
751
752         calculateCenter2D(t);
753 }
754
755 void calculateCenterBound(TransInfo *t)
756 {
757         float max[3];
758         float min[3];
759         int i;
760         for(i = 0; i < t->total; i++) {
761                 if (i) {
762                         if (t->data[i].flag & TD_SELECTED) {
763                                 MinMax3(min, max, t->data[i].center);
764                         }
765                         else {
766                                 /* 
767                                    All the selected elements are at the head of the array 
768                                    which means we can stop when it finds unselected data
769                                 */
770                                 break;
771                         }
772                 }
773                 else {
774                         VECCOPY(max, t->data[i].center);
775                         VECCOPY(min, t->data[i].center);
776                 }
777         }
778         VecAddf(t->center, min, max);
779         VecMulf(t->center, 0.5);
780
781         calculateCenter2D(t);
782 }
783
784 void calculateCenter(TransInfo *t) 
785 {
786         switch(t->around) {
787         case V3D_CENTER:
788                 calculateCenterBound(t);
789                 break;
790         case V3D_CENTROID:
791                 calculateCenterMedian(t);
792                 break;
793         case V3D_CURSOR:
794                 if(t->spacetype==SPACE_IMAGE)
795                         calculateCenterCursor2D(t);
796                 else
797                         calculateCenterCursor(t);
798                 break;
799         case V3D_LOCAL:
800                 /* Individual element center uses median center for helpline and such */
801                 calculateCenterMedian(t);
802                 break;
803         case V3D_ACTIVE:
804                 /* set median, and if if if... do object center */
805                 
806                 /* EDIT MODE ACTIVE EDITMODE ELEMENT */
807                 if (G.obedit && G.obedit->type == OB_MESH && G.editMesh->selected.last) {
808                         EM_editselection_center(t->center, G.editMesh->selected.last);
809                         calculateCenter2D(t);
810                         break;
811                 } /* END EDIT MODE ACTIVE ELEMENT */
812                 
813                 calculateCenterMedian(t);
814                 if((t->flag & (T_EDIT|T_POSE))==0) {
815                         Object *ob= OBACT;
816                         if(ob) {
817                                 VECCOPY(t->center, ob->obmat[3]);
818                                 projectIntView(t, t->center, t->center2d);
819                         }
820                 }
821         }
822
823         /* setting constraint center */
824         VECCOPY(t->con.center, t->center);
825         if(t->flag & (T_EDIT|T_POSE)) {
826                 Object *ob= G.obedit?G.obedit:t->poseobj;
827                 Mat4MulVecfl(ob->obmat, t->con.center);
828         }
829
830         /* voor panning from cameraview */
831         if(t->flag & T_OBJECT) {
832                 if( G.vd->camera==OBACT && G.vd->persp>1) {
833                         float axis[3];
834                         /* persinv is nasty, use viewinv instead, always right */
835                         VECCOPY(axis, t->viewinv[2]);
836                         Normalize(axis);
837
838                         /* 6.0 = 6 grid units */
839                         axis[0]= t->center[0]- 6.0f*axis[0];
840                         axis[1]= t->center[1]- 6.0f*axis[1];
841                         axis[2]= t->center[2]- 6.0f*axis[2];
842                         
843                         projectIntView(t, axis, t->center2d);
844                         
845                         /* rotate only needs correct 2d center, grab needs initgrabz() value */
846                         if(t->mode==TFM_TRANSLATION) {
847                                 VECCOPY(t->center, axis);
848                                 VECCOPY(t->con.center, t->center);
849                         }
850                 }
851         }       
852
853         if(t->spacetype==SPACE_VIEW3D)
854                 initgrabz(t->center[0], t->center[1], t->center[2]);
855 }
856
857 void calculatePropRatio(TransInfo *t)
858 {
859         TransData *td = t->data;
860         int i;
861         float dist;
862         short connected = t->flag & T_PROP_CONNECTED;
863
864         if (t->flag & T_PROP_EDIT) {
865                 for(i = 0 ; i < t->total; i++, td++) {
866                         if (td->flag & TD_SELECTED) {
867                                 td->factor = 1.0f;
868                         }
869                         else if ((connected && 
870                                                 (td->flag & TD_NOTCONNECTED || td->dist > t->propsize))
871                                 ||
872                                         (connected == 0 &&
873                                                 td->rdist > t->propsize)) {
874                                 /* 
875                                    The elements are sorted according to their dist member in the array,
876                                    that means we can stop when it finds one element outside of the propsize.
877                                 */
878                                 td->flag |= TD_NOACTION;
879                                 td->factor = 0.0f;
880                                 restoreElement(td);
881                         }
882                         else {
883                                 /* Use rdist for falloff calculations, it is the real distance */
884                                 td->flag &= ~TD_NOACTION;
885                                 dist= (t->propsize-td->rdist)/t->propsize;
886                                 
887                                 /*
888                                  * Clamp to positive numbers.
889                                  * Certain corner cases with connectivity and individual centers
890                                  * can give values of rdist larger than propsize.
891                                  */
892                                 if (dist < 0.0f)
893                                         dist = 0.0f;
894                                 
895                                 switch(G.scene->prop_mode) {
896                                 case PROP_SHARP:
897                                         td->factor= dist*dist;
898                                         break;
899                                 case PROP_SMOOTH:
900                                         td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
901                                         break;
902                                 case PROP_ROOT:
903                                         td->factor = (float)sqrt(dist);
904                                         break;
905                                 case PROP_LIN:
906                                         td->factor = dist;
907                                         break;
908                                 case PROP_CONST:
909                                         td->factor = 1.0f;
910                                         break;
911                                 case PROP_SPHERE:
912                                         td->factor = (float)sqrt(2*dist - dist * dist);
913                                         break;
914                                 case PROP_RANDOM:
915                                         BLI_srand( BLI_rand() ); /* random seed */
916                                         td->factor = BLI_frand()*dist;
917                                         break;
918                                 default:
919                                         td->factor = 1;
920                                 }
921                         }
922                 }
923                 switch(G.scene->prop_mode) {
924                 case PROP_SHARP:
925                         strcpy(t->proptext, "(Sharp)");
926                         break;
927                 case PROP_SMOOTH:
928                         strcpy(t->proptext, "(Smooth)");
929                         break;
930                 case PROP_ROOT:
931                         strcpy(t->proptext, "(Root)");
932                         break;
933                 case PROP_LIN:
934                         strcpy(t->proptext, "(Linear)");
935                         break;
936                 case PROP_CONST:
937                         strcpy(t->proptext, "(Constant)");
938                         break;
939                 case PROP_SPHERE:
940                         strcpy(t->proptext, "(Sphere)");
941                         break;
942                 case PROP_RANDOM:
943                         strcpy(t->proptext, "(Random)");
944                         break;
945                 default:
946                         strcpy(t->proptext, "");
947                 }
948         }
949         else {
950                 for(i = 0 ; i < t->total; i++, td++) {
951                         td->factor = 1.0;
952                 }
953                 strcpy(t->proptext, "");
954         }
955 }
956
957 TransInfo * BIF_GetTransInfo() {
958         return &Trans;
959 }
960