Removed casting warnings from transform_manipulator.
[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         /* setting PET flag */
391         if ((t->context & CTX_NOPET) == 0 && (G.f & G_PROPORTIONAL)) {
392                 t->flag |= T_PROP_EDIT;
393         }
394
395         getmouseco_areawin(t->imval);
396         t->con.imval[0] = t->imval[0];
397         t->con.imval[1] = t->imval[1];
398
399         t->transform            = NULL;
400
401         t->total                        =
402                 t->num.idx              =
403                 t->num.idx_max  =
404                 t->num.ctrl[0]  = 
405                 t->num.ctrl[1]  = 
406                 t->num.ctrl[2]  = 0;
407
408         t->val = 0.0f;
409
410         t->num.val[0]           = 
411                 t->num.val[1]   = 
412                 t->num.val[2]   = 0.0f;
413
414         t->vec[0]                       =
415                 t->vec[1]               =
416                 t->vec[2]               = 0.0f;
417         
418         Mat3One(t->mat);
419         
420         Mat4CpyMat4(t->viewmat, G.vd->viewmat);
421         Mat4CpyMat4(t->viewinv, G.vd->viewinv);
422         Mat4CpyMat4(t->persinv, G.vd->persinv);
423 }
424
425 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
426 void postTrans (TransInfo *t) 
427 {
428         TransData *td;
429         int a;
430         
431         G.moving = 0; // Set moving flag off (display as usual)
432
433         stopConstraint(t);
434         t->con.drawExtra = NULL;
435         t->con.applyVec = NULL;
436         t->con.applySize= NULL;
437         t->con.applyRot = NULL;
438         t->con.mode             = 0;
439
440         /* since ipokeys are optional on objects, we mallocced them per trans-data */
441         for(a=0, td= t->data; a<t->total; a++, td++) {
442                 if(td->tdi) MEM_freeN(td->tdi);
443         }
444         
445         MEM_freeN(t->data);
446         t->data = NULL;
447
448         if (t->ext) MEM_freeN(t->ext);
449         
450 }
451
452 void apply_grid3(float *val, int max_index, float fac1, float fac2, float fac3)
453 {
454         /* fac1 is for 'nothing', fac2 for CTRL, fac3 for SHIFT */
455         int invert = U.flag & USER_AUTOGRABGRID;
456         int ctrl;
457         int i;
458
459         for (i=0; i<=max_index; i++) {
460
461                 if(invert) {
462                         if(G.qual & LR_CTRLKEY) ctrl= 0;
463                         else ctrl= 1;
464                 }
465                 else ctrl= (G.qual & LR_CTRLKEY);
466
467                 if(ctrl && (G.qual & LR_SHIFTKEY)) {
468                         if(fac3!= 0.0) {
469                                 for (i=0; i<=max_index; i++) {
470                                         val[i]= fac3*(float)floor(val[i]/fac3 +.5);
471                                 }
472                         }
473                 }
474                 else if(ctrl) {
475                         if(fac2!= 0.0) {
476                                 for (i=0; i<=max_index; i++) {
477                                         val[i]= fac2*(float)floor(val[i]/fac2 +.5);
478                                 }
479                         }
480                 }
481                 else {
482                         if(fac1!= 0.0) {
483                                 for (i=0; i<=max_index; i++) {
484                                         val[i]= fac1*(float)floor(val[i]/fac1 +.5);
485                                 }
486                         }
487                 }
488         }
489 }
490
491 void snapGrid(TransInfo *t, float *val) {
492         apply_grid3(val, t->idx_max, t->snap[0], t->snap[1], t->snap[2]);
493 }
494
495 void applyTransObjects(TransInfo *t)
496 {
497         TransData *td;
498         
499         for (td = t->data; td < t->data + t->total; td++) {
500                 VECCOPY(td->iloc, td->loc);
501                 if (td->ext->rot) {
502                         VECCOPY(td->ext->irot, td->ext->rot);
503                 }
504                 if (td->ext->size) {
505                         VECCOPY(td->ext->isize, td->ext->size);
506                 }
507         }       
508         recalcData(t);
509
510
511 /* helper for below */
512 static void restore_ipokey(float *poin, float *old)
513 {
514         if(poin) {
515                 poin[0]= old[0];
516                 poin[-3]= old[3];
517                 poin[3]= old[6];
518         }
519 }
520
521 void restoreElement(TransData *td) {
522         VECCOPY(td->loc, td->iloc);
523         if (td->val) {
524                 *td->val = td->ival;
525         }
526         if (td->ext) {
527                 if (td->ext->rot) {
528                         VECCOPY(td->ext->rot, td->ext->irot);
529                 }
530                 if (td->ext->size) {
531                         VECCOPY(td->ext->size, td->ext->isize);
532                 }
533                 if(td->flag & TD_USEQUAT) {
534                         if (td->ext->quat) {
535                                 QUATCOPY(td->ext->quat, td->ext->iquat);
536                         }
537                 }
538         }
539         if(td->tdi) {
540                 TransDataIpokey *tdi= td->tdi;
541                 
542                 restore_ipokey(tdi->locx, tdi->oldloc);
543                 restore_ipokey(tdi->locy, tdi->oldloc+1);
544                 restore_ipokey(tdi->locz, tdi->oldloc+2);
545
546                 restore_ipokey(tdi->rotx, tdi->oldrot);
547                 restore_ipokey(tdi->roty, tdi->oldrot+1);
548                 restore_ipokey(tdi->rotz, tdi->oldrot+2);
549                 
550                 restore_ipokey(tdi->sizex, tdi->oldsize);
551                 restore_ipokey(tdi->sizey, tdi->oldsize+1);
552                 restore_ipokey(tdi->sizez, tdi->oldsize+2);
553         }
554 }
555
556 void restoreTransObjects(TransInfo *t)
557 {
558         TransData *td;
559         
560         for (td = t->data; td < t->data + t->total; td++) {
561                 restoreElement(td);
562         }       
563         recalcData(t);
564
565
566 void calculateCenterCursor(TransInfo *t)
567 {
568         float *cursor;
569
570         cursor = give_cursor();
571         VECCOPY(t->center, cursor);
572
573         if(t->flag & (T_EDIT|T_POSE)) {
574                 Object *ob= G.obedit?G.obedit:G.obpose;
575                 float mat[3][3], imat[3][3];
576                 float vec[3];
577                 
578                 VecSubf(t->center, t->center, ob->obmat[3]);
579                 Mat3CpyMat4(mat, ob->obmat);
580                 Mat3Inv(imat, mat);
581                 Mat3MulVecfl(imat, t->center);
582                 
583                 VECCOPY(vec, t->center);
584                 Mat4MulVecfl(ob->obmat, vec);
585                 project_short_noclip(vec, t->center2d);
586         }
587         else {
588                 project_short_noclip(t->center, t->center2d);
589         }
590 }
591
592 void calculateCenterMedian(TransInfo *t)
593 {
594         float partial[3] = {0.0f, 0.0f, 0.0f};
595         int i;
596         for(i = 0; i < t->total; i++) {
597                 if (t->data[i].flag & TD_SELECTED) {
598                         VecAddf(partial, partial, t->data[i].center);
599                 }
600                 else {
601                         /* 
602                            All the selected elements are at the head of the array 
603                            which means we can stop when it finds unselected data
604                         */
605                         break;
606                 }
607         }
608         VecMulf(partial, 1.0f / t->total);
609         VECCOPY(t->center, partial);
610
611         if (t->flag & (T_EDIT|T_POSE)) {
612                 Object *ob= G.obedit?G.obedit:G.obpose;
613                 float vec[3];
614                 
615                 VECCOPY(vec, t->center);
616                 Mat4MulVecfl(ob->obmat, vec);
617                 project_short_noclip(vec, t->center2d);
618         }
619         else {
620                 project_short_noclip(t->center, t->center2d);
621         }
622 }
623
624 void calculateCenterBound(TransInfo *t)
625 {
626         float max[3];
627         float min[3];
628         int i;
629         for(i = 0; i < t->total; i++) {
630                 if (i) {
631                         if (t->data[i].flag & TD_SELECTED) {
632                                 MinMax3(min, max, t->data[i].center);
633                         }
634                         else {
635                                 /* 
636                                    All the selected elements are at the head of the array 
637                                    which means we can stop when it finds unselected data
638                                 */
639                                 break;
640                         }
641                 }
642                 else {
643                         VECCOPY(max, t->data[i].center);
644                         VECCOPY(min, t->data[i].center);
645                 }
646         }
647         VecAddf(t->center, min, max);
648         VecMulf(t->center, 0.5);
649
650         if (t->flag & (T_EDIT|T_POSE)) {
651                 Object *ob= G.obedit?G.obedit:G.obpose;
652                 float vec[3];
653                 
654                 VECCOPY(vec, t->center);
655                 Mat4MulVecfl(ob->obmat, vec);
656                 project_short_noclip(vec, t->center2d);
657         }
658         else {
659                 project_short_noclip(t->center, t->center2d);
660         }
661 }
662
663 void calculateCenter(TransInfo *t) 
664 {
665         switch(G.vd->around) {
666         case V3D_CENTRE:
667                 calculateCenterBound(t);
668                 break;
669         case V3D_CENTROID:
670                 calculateCenterMedian(t);
671                 break;
672         case V3D_CURSOR:
673                 calculateCenterCursor(t);
674                 break;
675         case V3D_LOCAL:
676                 // NEED TO REPLACE THIS
677                 calculateCenterMedian(t);
678                 printf("local\n");
679                 break;
680         }
681
682         /* setting constraint center */
683         VECCOPY(t->con.center, t->center);
684         if(t->flag & (T_EDIT|T_POSE)) {
685                 Object *ob= G.obedit?G.obedit:G.obpose;
686                 Mat4MulVecfl(ob->obmat, t->con.center);
687         }
688
689         /* voor panning from cameraview */
690         if(t->flag & T_OBJECT) {
691                 if( G.vd->camera==OBACT && G.vd->persp>1) {
692                         float axis[3];
693                         VECCOPY(axis, G.vd->persinv[2]);
694                         Normalise(axis);
695
696                         /* 6.0 = 6 grid units */
697                         axis[0]= t->center[0]+ 6.0f*axis[0];
698                         axis[1]= t->center[1]+ 6.0f*axis[1];
699                         axis[2]= t->center[2]+ 6.0f*axis[2];
700                         
701                         project_short_noclip(axis, t->center2d);
702                         
703                         /* rotate only needs correct 2d center, grab needs initgrabz() value */
704                         if(t->mode==TFM_TRANSLATION) VECCOPY(t->center, axis);
705                 }
706         }       
707         initgrabz(t->center[0], t->center[1], t->center[2]);
708 }
709
710 void calculatePropRatio(TransInfo *t)
711 {
712         TransData *td = t->data;
713         int i;
714         float dist;
715         extern int prop_mode;
716
717         if (t->flag & T_PROP_EDIT) {
718                 for(i = 0 ; i < t->total; i++, td++) {
719                         if (td->flag & TD_SELECTED) {
720                                 td->factor = 1.0f;
721                         }
722                         else if (td->flag & TD_NOTCONNECTED || td->dist > t->propsize) {
723                                 /* 
724                                    The elements are sorted according to their dist member in the array,
725                                    that means we can stop when it finds one element outside of the propsize.
726                                 */
727                                 td->flag |= TD_NOACTION;
728                                 td->factor = 0.0f;
729                                 restoreElement(td);
730                         }
731                         else {
732                                 /* Use rdist for falloff calculations, it is the real distance */
733                                 td->flag &= ~TD_NOACTION;
734                                 dist= (t->propsize-td->rdist)/t->propsize;
735                                 switch(prop_mode) {
736                                 case PROP_SHARP:
737                                         td->factor= dist*dist;
738                                         break;
739                                 case PROP_SMOOTH:
740                                         td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
741                                         break;
742                                 case PROP_ROOT:
743                                         td->factor = (float)sqrt(dist);
744                                         break;
745                                 case PROP_LIN:
746                                         td->factor = dist;
747                                         break;
748                                 case PROP_CONST:
749                                         td->factor = 1.0f;
750                                         break;
751                                 case PROP_SPHERE:
752                                         td->factor = (float)sqrt(2*dist - dist * dist);
753                                         break;
754                                 default:
755                                         td->factor = 1;
756                                 }
757                         }
758                 }
759                 switch(prop_mode) {
760                 case PROP_SHARP:
761                         strcpy(t->proptext, "(Sharp)");
762                         break;
763                 case PROP_SMOOTH:
764                         strcpy(t->proptext, "(Smooth)");
765                         break;
766                 case PROP_ROOT:
767                         strcpy(t->proptext, "(Root)");
768                         break;
769                 case PROP_LIN:
770                         strcpy(t->proptext, "(Linear)");
771                         break;
772                 case PROP_CONST:
773                         strcpy(t->proptext, "(Constant)");
774                         break;
775                 case PROP_SPHERE:
776                         strcpy(t->proptext, "(Sphere)");
777                         break;
778                 default:
779                         strcpy(t->proptext, "");
780                 }
781         }
782         else {
783                 for(i = 0 ; i < t->total; i++, td++) {
784                         td->factor = 1.0;
785                 }
786                 strcpy(t->proptext, "");
787         }
788 }
789
790 TransInfo * BIF_GetTransInfo() {
791         return &Trans;
792 }
793