ad49b74b1ff59a214622bc30664c829a5994a20a
[blender.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 <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #ifndef WIN32
42 #include <unistd.h>
43 #else
44 #include <io.h>
45 #endif
46
47 #include "MEM_guardedalloc.h"
48
49 #include "DNA_action_types.h"
50 #include "DNA_armature_types.h"
51 #include "DNA_camera_types.h"
52 #include "DNA_curve_types.h"
53 #include "DNA_effect_types.h"
54 #include "DNA_ika_types.h"
55 #include "DNA_image_types.h"
56 #include "DNA_ipo_types.h"
57 #include "DNA_key_types.h"
58 #include "DNA_lamp_types.h"
59 #include "DNA_lattice_types.h"
60 #include "DNA_mesh_types.h"
61 #include "DNA_meshdata_types.h"
62 #include "DNA_meta_types.h"
63 #include "DNA_object_types.h"
64 #include "DNA_scene_types.h"
65 #include "DNA_screen_types.h"
66 #include "DNA_texture_types.h"
67 #include "DNA_view3d_types.h"
68 #include "DNA_world_types.h"
69 #include "DNA_userdef_types.h"
70 #include "DNA_property_types.h"
71 #include "DNA_vfont_types.h"
72 #include "DNA_constraint_types.h"
73
74 #include "BIF_screen.h"
75 #include "BIF_space.h"
76 #include "BIF_editview.h"
77 #include "BIF_resources.h"
78 #include "BIF_mywindow.h"
79 #include "BIF_gl.h"
80 #include "BIF_editlattice.h"
81 #include "BIF_editarmature.h"
82 #include "BIF_editmesh.h"
83
84 #include "BKE_action.h"
85 #include "BKE_anim.h"
86 #include "BKE_armature.h"
87 #include "BKE_curve.h"
88 #include "BKE_displist.h"
89 #include "BKE_global.h"
90 #include "BKE_ipo.h"
91 #include "BKE_lattice.h"
92 #include "BKE_object.h"
93 #include "BKE_utildefines.h"
94
95 #include "BSE_edit.h"
96 #include "BSE_view.h"
97
98 #include "BLI_arithb.h"
99 #include "BLI_editVert.h"
100
101 #include "blendef.h"
102
103 #include "mydevice.h"
104
105 #include "transform.h"
106 #include "transform_generics.h"
107 #include "transform_constraints.h"
108
109 extern ListBase editNurb;
110 extern ListBase editelems;
111
112 /* GLOBAL VARIABLE THAT SHOULD MOVED TO SCREEN MEMBER OR SOMETHING  */
113 extern TransInfo Trans;
114
115 /* ************************** Functions *************************** */
116
117
118 void getViewVector(float coord[3], float vec[3]) {
119         if (G.vd->persp)
120         {
121                 float p1[4], p2[4];
122
123                 VECCOPY(p1, coord);
124                 p1[3] = 1.0f;
125                 VECCOPY(p2, p1);
126                 p2[3] = 1.0f;
127                 Mat4MulVec4fl(G.vd->viewmat, p2);
128
129                 p2[0] = 2.0f * p2[0];
130                 p2[1] = 2.0f * p2[1];
131                 p2[2] = 2.0f * p2[2];
132
133                 Mat4MulVec4fl(G.vd->viewinv, p2);
134
135                 VecSubf(vec, p1, p2);
136         }
137         else {
138                 VECCOPY(vec, G.vd->viewinv[2]);
139         }
140         Normalise(vec);
141 }
142
143 /* ************************** GENERICS **************************** */
144
145 /* called for objects updating while transform acts, once per redraw */
146 void recalcData(TransInfo *t)
147 {
148         Base *base;
149         
150         if(G.obpose) {
151                 TransData *td= t->data;
152                 bPoseChannel    *chan;
153                 int     i;
154                 
155                 if (!G.obpose->pose) G.obpose->pose= MEM_callocN(sizeof(bPose), "pose");
156                 
157                 /*      Make channels for the transforming bones (in posemode) */
158                 for (i=0; i<t->total; i++, td++) {
159                         chan = MEM_callocN (sizeof (bPoseChannel), "transPoseChannel");
160                         
161                         if (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL) {
162                                 chan->flag |= POSE_ROT;
163                                 memcpy (chan->quat, td->ext->quat, sizeof (chan->quat));
164                         }
165                         if (t->mode == TFM_TRANSLATION) {
166                                 chan->flag |= POSE_LOC;
167                                 memcpy (chan->loc, td->loc, sizeof (chan->loc));
168                         }
169                         if (t->mode == TFM_RESIZE) {
170                                 chan->flag |= POSE_SIZE;
171                                 memcpy (chan->size, td->ext->size, sizeof (chan->size));
172                         }
173                         
174                         strcpy (chan->name, ((Bone*) td->ext->bone)->name);
175                         
176                         set_pose_channel (G.obpose->pose, chan);
177
178                 }
179                 
180                 clear_pose_constraint_status(G.obpose);
181                 
182                 if (!is_delay_deform()) make_displists_by_armature(G.obpose);
183                 
184         }
185         else if (G.obedit) {
186                 if (G.obedit->type == OB_MESH) {
187                         recalc_editnormals();
188                         makeDispList(G.obedit);
189                 }
190                 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
191                         Nurb *nu= editNurb.first;
192                         while(nu) {
193                                 test2DNurb(nu);
194                                 testhandlesNurb(nu); /* test for bezier too */
195                                 nu= nu->next;
196                         }
197                         makeDispList(G.obedit);
198
199                         makeBevelList(G.obedit); // might be needed for deform
200                         calc_curvepath(G.obedit);
201                         
202                         // deform, bevel, taper
203                         base= FIRSTBASE;
204                         while(base) {
205                                 if(base->lay & G.vd->lay) {
206                                         if(base->object->parent==G.obedit && base->object->partype==PARSKEL)
207                                                 makeDispList(base->object);
208                                         else if(base->object->type==OB_CURVE) {
209                                                 Curve *cu= base->object->data;
210                                                 if(G.obedit==cu->bevobj || G.obedit==cu->taperobj)
211                                                         makeDispList(base->object);
212                                         }
213                                 }
214                                 base= base->next;
215                         }
216                 }
217                 else if(G.obedit->type==OB_ARMATURE){
218                         EditBone *ebo;
219                         
220                         /* Ensure all bones are correctly adjusted */
221                         for (ebo=G.edbo.first; ebo; ebo=ebo->next){
222                                 
223                                 if ((ebo->flag & BONE_IK_TOPARENT) && ebo->parent){
224                                         /* If this bone has a parent tip that has been moved */
225                                         if (ebo->parent->flag & BONE_TIPSEL){
226                                                 VECCOPY (ebo->head, ebo->parent->tail);
227                                         }
228                                         /* If this bone has a parent tip that has NOT been moved */
229                                         else{
230                                                 VECCOPY (ebo->parent->tail, ebo->head);
231                                         }
232                                 }
233                         }
234                 }
235                 else if(G.obedit->type==OB_LATTICE) {
236                         
237                         if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
238                         
239                         base= FIRSTBASE;
240                         while(base) {
241                                 if(base->lay & G.vd->lay) {
242                                         if(base->object->parent==G.obedit) {
243                                                 makeDispList(base->object);
244                                         }
245                                 }
246                                 base= base->next;
247                         }
248                 }
249                 else if (G.obedit->type == OB_MBALL) {
250                         makeDispList(G.obedit); 
251                 }       
252         }
253         else {
254                 
255                 base= FIRSTBASE;
256                 while(base) {
257                         if(base->flag & BA_DO_IPO) {
258                                 if(base->object->ipo) {
259                                         IpoCurve *icu;
260                                         
261                                         base->object->ctime= -1234567.0;
262                                         
263                                         icu= base->object->ipo->curve.first;
264                                         while(icu) {
265                                                 calchandles_ipocurve(icu);
266                                                 icu= icu->next;
267                                         }
268                                 }                               
269                         }
270                         if(base->object->partype & PARSLOW) {
271                                 base->object->partype -= PARSLOW;
272                                 where_is_object(base->object);
273                                 base->object->partype |= PARSLOW;
274                         }
275                         else if(base->flag & BA_WHERE_UPDATE) {
276                                 where_is_object(base->object);
277                         }
278                         
279                         base= base->next;
280                 } 
281                 
282                 base= FIRSTBASE;
283                 while(base) {
284                         
285                         if(base->flag & BA_DISP_UPDATE) makeDispList(base->object);
286                         
287                         base= base->next;
288                 }
289         }
290         
291         /* ugly stuff for posemode, copied from old system */
292         base= FIRSTBASE;
293         while(base) {
294                 extern int pose_flags_reset_done(Object *ob);   // linker solves
295                 
296                 if (pose_flags_reset_done(base->object)) {
297                         if (!is_delay_deform())
298                                 make_displists_by_armature(base->object);
299                 }
300                 
301                 base= base->next;
302         }
303         
304         if (G.obpose && G.obpose->type == OB_ARMATURE)
305                 clear_pose_constraint_status(G.obpose);
306         
307         if (!is_delay_deform()) make_displists_by_armature(G.obpose);
308
309         
310         /* update shaded drawmode while transform */
311         if(G.vd->drawtype == OB_SHADED) reshadeall_displist();
312         
313 }
314
315 void initTransModeFlags(TransInfo *t, int mode) 
316 {
317         t->mode = mode;
318         t->num.flag = 0;
319
320         /* REMOVING RESTRICTIONS FLAGS */
321         t->flag &= ~T_ALL_RESTRICTIONS;
322         
323         switch (mode) {
324         case TFM_RESIZE:
325                 t->flag |= T_NULL_ONE;
326                 t->num.flag |= NUM_NULL_ONE;
327                 t->num.flag |= NUM_AFFECT_ALL;
328                 if (!G.obedit) {
329                         t->flag |= T_NO_ZERO;
330                         t->num.flag |= NUM_NO_ZERO;
331                 }
332                 break;
333         case TFM_TOSPHERE:
334                 t->num.flag |= NUM_NULL_ONE;
335                 t->num.flag |= NUM_NO_NEGATIVE;
336                 t->flag |= T_NO_CONSTRAINT;
337                 break;
338         case TFM_SHEAR:
339                 t->flag |= T_NO_CONSTRAINT;
340                 break;
341         }
342 }
343
344 void drawLine(float *center, float *dir, char axis, short options)
345 {
346         extern void make_axis_color(char *col, char *col2, char axis);  // drawview.c
347         float v1[3], v2[3], v3[3];
348         char col[3], col2[3];
349         
350         //if(G.obedit) mymultmatrix(G.obedit->obmat);   // sets opengl viewing
351
352         VecCopyf(v3, dir);
353         VecMulf(v3, G.vd->far);
354         
355         VecSubf(v2, center, v3);
356         VecAddf(v1, center, v3);
357
358         if (options & DRAWLIGHT) {
359                 col[0] = col[1] = col[2] = 220;
360         }
361         else {
362                 BIF_GetThemeColor3ubv(TH_GRID, col);
363         }
364         make_axis_color(col, col2, axis);
365         glColor3ubv(col2);
366
367         setlinestyle(0);
368         glLineWidth(2.0);
369         glBegin(GL_LINE_STRIP); 
370                 glVertex3fv(v1); 
371                 glVertex3fv(v2); 
372         glEnd();
373         glLineWidth(1.0);
374         
375         myloadmatrix(G.vd->viewmat);
376 }
377
378 void initTrans (TransInfo *t)
379 {
380
381         /* moving: is shown in drawobject() (transform color) */
382         if(G.obedit || G.obpose) G.moving= G_TRANSFORM_EDIT;
383         else G.moving= G_TRANSFORM_OBJ;
384
385         t->data = NULL;
386         t->ext = NULL;
387
388         t->flag = 0;
389
390         getmouseco_areawin(t->imval);
391         t->con.imval[0] = t->imval[0];
392         t->con.imval[1] = t->imval[1];
393
394         t->transform            = NULL;
395
396         t->total                        =
397                 t->num.idx              =
398                 t->num.idx_max  =
399                 t->num.ctrl[0]  = 
400                 t->num.ctrl[1]  = 
401                 t->num.ctrl[2]  = 0;
402
403         t->val = 0.0f;
404
405         t->num.val[0]           = 
406                 t->num.val[1]   = 
407                 t->num.val[2]   = 0.0f;
408
409         t->vec[0]                       =
410                 t->vec[1]               =
411                 t->vec[2]               = 0.0f;
412         
413         Mat3One(t->mat);
414         
415         Mat4CpyMat4(t->viewmat, G.vd->viewmat);
416         Mat4CpyMat4(t->viewinv, G.vd->viewinv);
417         Mat4CpyMat4(t->persinv, G.vd->persinv);
418 }
419
420 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
421 void postTrans (TransInfo *t) 
422 {
423         TransData *td;
424         int a;
425         
426         G.moving = 0; // Set moving flag off (display as usual)
427
428         stopConstraint(t);
429         t->con.drawExtra = NULL;
430         t->con.applyVec = NULL;
431         t->con.applySize= NULL;
432         t->con.applyRot = NULL;
433         t->con.mode             = 0;
434
435         /* since ipokeys are optional on objects, we mallocced them per trans-data */
436         for(a=0, td= t->data; a<t->total; a++, td++) {
437                 if(td->tdi) MEM_freeN(td->tdi);
438         }
439         
440         MEM_freeN(t->data);
441         t->data = NULL;
442
443         if (t->ext) MEM_freeN(t->ext);
444         
445 }
446
447 void apply_grid3(float *val, int max_index, float fac1, float fac2, float fac3)
448 {
449         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
450         int invert = U.flag & USER_AUTOGRABGRID;
451         int ctrl;
452         int i;
453
454         for (i=0; i<=max_index; i++) {
455
456                 if(invert) {
457                         if(G.qual & LR_CTRLKEY) ctrl= 0;
458                         else ctrl= 1;
459                 }
460                 else ctrl= (G.qual & LR_CTRLKEY);
461
462                 if(ctrl && (G.qual & LR_SHIFTKEY)) {
463                         if(fac3!= 0.0) {
464                                 for (i=0; i<=max_index; i++) {
465                                         val[i]= fac3*(float)floor(val[i]/fac3 +.5);
466                                 }
467                         }
468                 }
469                 else if(ctrl) {
470                         if(fac2!= 0.0) {
471                                 for (i=0; i<=max_index; i++) {
472                                         val[i]= fac2*(float)floor(val[i]/fac2 +.5);
473                                 }
474                         }
475                 }
476                 else {
477                         if(fac1!= 0.0) {
478                                 for (i=0; i<=max_index; i++) {
479                                         val[i]= fac1*(float)floor(val[i]/fac1 +.5);
480                                 }
481                         }
482                 }
483         }
484 }
485
486 void snapGrid(TransInfo *t, float *val) {
487         apply_grid3(val, t->idx_max, t->snap[0], t->snap[1], t->snap[2]);
488 }
489
490 void applyTransObjects(TransInfo *t)
491 {
492         TransData *td;
493         
494         for (td = t->data; td < t->data + t->total; td++) {
495                 VECCOPY(td->iloc, td->loc);
496                 if (td->ext->rot) {
497                         VECCOPY(td->ext->irot, td->ext->rot);
498                 }
499                 if (td->ext->size) {
500                         VECCOPY(td->ext->isize, td->ext->size);
501                 }
502         }       
503         recalcData(t);
504
505
506 /* helper for below */
507 static void restore_ipokey(float *poin, float *old)
508 {
509         if(poin) {
510                 poin[0]= old[0];
511                 poin[-3]= old[3];
512                 poin[3]= old[6];
513         }
514 }
515
516 void restoreElement(TransData *td) {
517         VECCOPY(td->loc, td->iloc);
518         if (td->val) {
519                 *td->val = td->ival;
520         }
521         if (td->ext) {
522                 if (td->ext->rot) {
523                         VECCOPY(td->ext->rot, td->ext->irot);
524                 }
525                 if (td->ext->size) {
526                         VECCOPY(td->ext->size, td->ext->isize);
527                 }
528                 if(td->flag & TD_USEQUAT) {
529                         if (td->ext->quat) {
530                                 QUATCOPY(td->ext->quat, td->ext->iquat);
531                         }
532                 }
533         }
534         if(td->tdi) {
535                 TransDataIpokey *tdi= td->tdi;
536                 
537                 restore_ipokey(tdi->locx, tdi->oldloc);
538                 restore_ipokey(tdi->locy, tdi->oldloc+1);
539                 restore_ipokey(tdi->locz, tdi->oldloc+2);
540
541                 restore_ipokey(tdi->rotx, tdi->oldrot);
542                 restore_ipokey(tdi->roty, tdi->oldrot+1);
543                 restore_ipokey(tdi->rotz, tdi->oldrot+2);
544                 
545                 restore_ipokey(tdi->sizex, tdi->oldsize);
546                 restore_ipokey(tdi->sizey, tdi->oldsize+1);
547                 restore_ipokey(tdi->sizez, tdi->oldsize+2);
548         }
549 }
550
551 void restoreTransObjects(TransInfo *t)
552 {
553         TransData *td;
554         
555         for (td = t->data; td < t->data + t->total; td++) {
556                 restoreElement(td);
557         }       
558         recalcData(t);
559
560
561 void calculateCenterCursor(TransInfo *t)
562 {
563         float *cursor;
564
565         cursor = give_cursor();
566         VECCOPY(t->center, cursor);
567
568         if(t->flag & (T_EDIT|T_POSE)) {
569                 Object *ob= G.obedit?G.obedit:G.obpose;
570                 float mat[3][3], imat[3][3];
571                 float vec[3];
572                 
573                 VecSubf(t->center, t->center, ob->obmat[3]);
574                 Mat3CpyMat4(mat, ob->obmat);
575                 Mat3Inv(imat, mat);
576                 Mat3MulVecfl(imat, t->center);
577                 
578                 VECCOPY(vec, t->center);
579                 Mat4MulVecfl(ob->obmat, vec);
580                 project_short_noclip(vec, t->center2d);
581         }
582         else {
583                 project_short_noclip(t->center, t->center2d);
584         }
585 }
586
587 void calculateCenterMedian(TransInfo *t)
588 {
589         float partial[3] = {0.0f, 0.0f, 0.0f};
590         int i;
591         for(i = 0; i < t->total; i++) {
592                 if (t->data[i].flag & TD_SELECTED) {
593                         VecAddf(partial, partial, t->data[i].center);
594                 }
595                 else {
596                         /* 
597                            All the selected elements are at the head of the array 
598                            which means we can stop when it finds unselected data
599                         */
600                         break;
601                 }
602         }
603         VecMulf(partial, 1.0f / t->total);
604         VECCOPY(t->center, partial);
605
606         if (t->flag & (T_EDIT|T_POSE)) {
607                 Object *ob= G.obedit?G.obedit:G.obpose;
608                 float vec[3];
609                 
610                 VECCOPY(vec, t->center);
611                 Mat4MulVecfl(ob->obmat, vec);
612                 project_short_noclip(vec, t->center2d);
613         }
614         else {
615                 project_short_noclip(t->center, t->center2d);
616         }
617 }
618
619 void calculateCenterBound(TransInfo *t)
620 {
621         float max[3];
622         float min[3];
623         int i;
624         for(i = 0; i < t->total; i++) {
625                 if (i) {
626                         if (t->data[i].flag & TD_SELECTED) {
627                                 MinMax3(min, max, t->data[i].center);
628                         }
629                         else {
630                                 /* 
631                                    All the selected elements are at the head of the array 
632                                    which means we can stop when it finds unselected data
633                                 */
634                                 break;
635                         }
636                 }
637                 else {
638                         VECCOPY(max, t->data[i].center);
639                         VECCOPY(min, t->data[i].center);
640                 }
641         }
642         VecAddf(t->center, min, max);
643         VecMulf(t->center, 0.5);
644
645         if (t->flag & (T_EDIT|T_POSE)) {
646                 Object *ob= G.obedit?G.obedit:G.obpose;
647                 float vec[3];
648                 
649                 VECCOPY(vec, t->center);
650                 Mat4MulVecfl(ob->obmat, vec);
651                 project_short_noclip(vec, t->center2d);
652         }
653         else {
654                 project_short_noclip(t->center, t->center2d);
655         }
656 }
657
658 void calculateCenter(TransInfo *t) 
659 {
660         switch(G.vd->around) {
661         case V3D_CENTRE:
662                 calculateCenterBound(t);
663                 break;
664         case V3D_CENTROID:
665                 calculateCenterMedian(t);
666                 break;
667         case V3D_CURSOR:
668                 calculateCenterCursor(t);
669                 break;
670         case V3D_LOCAL:
671                 // NEED TO REPLACE THIS
672                 calculateCenterMedian(t);
673                 printf("local\n");
674                 break;
675         }
676
677         /* setting constraint center */
678         VECCOPY(t->con.center, t->center);
679         if(t->flag & (T_EDIT|T_POSE)) {
680                 Object *ob= G.obedit?G.obedit:G.obpose;
681                 Mat4MulVecfl(ob->obmat, t->con.center);
682         }
683
684         /* voor panning from cameraview */
685         if(t->flag & T_OBJECT) {
686                 if( G.vd->camera==OBACT && G.vd->persp>1) {
687                         float axis[3];
688                         VECCOPY(axis, G.vd->persinv[2]);
689                         Normalise(axis);
690
691                         /* 6.0 = 6 grid units */
692                         axis[0]= t->center[0]+ 6.0f*axis[0];
693                         axis[1]= t->center[1]+ 6.0f*axis[1];
694                         axis[2]= t->center[2]+ 6.0f*axis[2];
695                         
696                         project_short_noclip(axis, t->center2d);
697                         
698                         /* rotate only needs correct 2d center, grab needs initgrabz() value */
699                         if(t->mode==TFM_TRANSLATION) VECCOPY(t->center, axis);
700                 }
701         }       
702         initgrabz(t->center[0], t->center[1], t->center[2]);
703 }
704
705 void calculatePropRatio(TransInfo *t)
706 {
707         TransData *td = t->data;
708         int i;
709         float dist;
710         extern int prop_mode;
711
712         if (G.f & G_PROPORTIONAL) {
713                 for(i = 0 ; i < t->total; i++, td++) {
714                         if (td->flag & TD_SELECTED) {
715                                 td->factor = 1.0f;
716                         }
717                         else if (td->flag & TD_NOTCONNECTED || td->dist > t->propsize) {
718                                 /* 
719                                    The elements are sorted according to their dist member in the array,
720                                    that means we can stop when it finds one element outside of the propsize.
721                                 */
722                                 td->flag |= TD_NOACTION;
723                                 td->factor = 0.0f;
724                                 restoreElement(td);
725                         }
726                         else {
727                                 /* Use rdist for falloff calculations, it is the real distance */
728                                 td->flag &= ~TD_NOACTION;
729                                 dist= (t->propsize-td->rdist)/t->propsize;
730                                 switch(prop_mode) {
731                                 case PROP_SHARP:
732                                         td->factor= dist*dist;
733                                         break;
734                                 case PROP_SMOOTH:
735                                         td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
736                                         break;
737                                 case PROP_ROOT:
738                                         td->factor = (float)sqrt(dist);
739                                         break;
740                                 case PROP_LIN:
741                                         td->factor = dist;
742                                         break;
743                                 case PROP_CONST:
744                                         td->factor = 1.0f;
745                                         //td->factor = (float)sqrt(2*dist - dist * dist);
746                                         break;
747                                 default:
748                                         td->factor = 1;
749                                 }
750                         }
751                 }
752                 switch(prop_mode) {
753                 case PROP_SHARP:
754                         strcpy(t->proptext, "(Quad)");
755                         break;
756                 case PROP_SMOOTH:
757                         strcpy(t->proptext, "(Smooth)");
758                         break;
759                 case PROP_ROOT:
760                         strcpy(t->proptext, "(Root)");
761                         break;
762                 case PROP_LIN:
763                         strcpy(t->proptext, "(Linear)");
764                         break;
765                 case PROP_CONST:
766                         strcpy(t->proptext, "(Constant)");
767                         //strcpy(t->proptext, "(Sphere)");
768                         break;
769                 default:
770                         strcpy(t->proptext, "");
771                 }
772         }
773         else {
774                 for(i = 0 ; i < t->total; i++, td++) {
775                         td->factor = 1.0;
776                 }
777                 strcpy(t->proptext, "");
778         }
779 }
780
781 TransInfo * BIF_GetTransInfo() {
782         return &Trans;
783 }
784