4 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
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
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.
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.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
36 #include "MEM_guardedalloc.h"
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_particle_types.h"
48 #include "DNA_screen_types.h"
49 #include "DNA_space_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_userdef_types.h"
52 #include "DNA_view3d_types.h"
54 #include "BIF_screen.h"
55 #include "BIF_resources.h"
56 #include "BIF_mywindow.h"
58 #include "BIF_editaction.h"
59 #include "BIF_editarmature.h"
60 #include "BIF_editmesh.h"
61 #include "BIF_editnla.h"
62 #include "BIF_editsima.h"
63 #include "BIF_editparticle.h"
64 #include "BIF_meshtools.h"
65 #include "BIF_retopo.h"
67 #include "BSE_editipo.h"
68 #include "BSE_editipo_types.h"
71 #include "BIF_verse.h"
74 #include "BKE_action.h"
76 #include "BKE_armature.h"
77 #include "BKE_cloth.h"
78 #include "BKE_curve.h"
79 #include "BKE_depsgraph.h"
80 #include "BKE_displist.h"
81 #include "BKE_depsgraph.h"
82 #include "BKE_global.h"
83 #include "BKE_group.h"
85 #include "BKE_lattice.h"
88 #include "BKE_modifier.h"
89 #include "BKE_object.h"
90 #include "BKE_utildefines.h"
93 #include "BKE_verse.h"
97 #include "BSE_editaction_types.h"
98 #include "BDR_unwrapper.h"
100 #include "BLI_arithb.h"
101 #include "BLI_blenlib.h"
102 #include "BLI_editVert.h"
103 #include "BLI_rand.h"
107 #include "mydevice.h"
109 #include "transform.h"
111 extern ListBase editNurb;
112 extern ListBase editelems;
114 extern TransInfo Trans; /* From transform.c */
116 /* ************************** Functions *************************** */
119 void getViewVector(float coord[3], float vec[3])
121 TransInfo *t = BIF_GetTransInfo();
131 Mat4MulVec4fl(t->viewmat, p2);
133 p2[0] = 2.0f * p2[0];
134 p2[1] = 2.0f * p2[1];
135 p2[2] = 2.0f * p2[2];
137 Mat4MulVec4fl(t->viewinv, p2);
139 VecSubf(vec, p1, p2);
142 VECCOPY(vec, t->viewinv[2]);
147 /* ************************** GENERICS **************************** */
149 static void clipMirrorModifier(TransInfo *t, Object *ob)
151 ModifierData *md= ob->modifiers.first;
152 float tolerance[3] = {0.0f, 0.0f, 0.0f};
155 for (; md; md=md->next) {
156 if (md->type==eModifierType_Mirror) {
157 MirrorModifierData *mmd = (MirrorModifierData*) md;
159 if(mmd->flag & MOD_MIR_CLIPPING) {
161 if(mmd->flag & MOD_MIR_AXIS_X) {
163 tolerance[0] = mmd->tolerance;
165 if(mmd->flag & MOD_MIR_AXIS_Y) {
167 tolerance[1] = mmd->tolerance;
169 if(mmd->flag & MOD_MIR_AXIS_Z) {
171 tolerance[2] = mmd->tolerance;
174 float mtx[4][4], imtx[4][4];
176 TransData *td = t->data;
178 if (mmd->mirror_ob) {
181 Mat4Invert(obinv, mmd->mirror_ob->obmat);
182 Mat4MulMat4(mtx, ob->obmat, obinv);
183 Mat4Invert(imtx, mtx);
186 for(i = 0 ; i < t->total; i++, td++) {
188 float loc[3], iloc[3];
190 if (td->flag & TD_NOACTION)
194 if (td->flag & TD_SKIP)
197 VecCopyf(loc, td->loc);
198 VecCopyf(iloc, td->iloc);
200 if (mmd->mirror_ob) {
201 VecMat4MulVecfl(loc, mtx, loc);
202 VecMat4MulVecfl(iloc, mtx, iloc);
207 if(fabs(iloc[0])<=tolerance[0] ||
208 loc[0]*iloc[0]<0.0f) {
215 if(fabs(iloc[1])<=tolerance[1] ||
216 loc[1]*iloc[1]<0.0f) {
222 if(fabs(iloc[2])<=tolerance[2] ||
223 loc[2]*iloc[2]<0.0f) {
229 if (mmd->mirror_ob) {
230 VecMat4MulVecfl(loc, imtx, loc);
232 VecCopyf(td->loc, loc);
242 /* assumes G.obedit set to mesh object */
243 static void editmesh_apply_to_mirror(TransInfo *t)
245 TransData *td = t->data;
249 for(i = 0 ; i < t->total; i++, td++) {
250 if (td->flag & TD_NOACTION)
254 if (td->flag & TD_SKIP)
259 eve->co[0]= -td->loc[0];
260 eve->co[1]= td->loc[1];
261 eve->co[2]= td->loc[2];
266 /* called for updating while transform acts, once per redraw */
267 void recalcData(TransInfo *t)
271 struct TransData *td;
274 if (t->spacetype == SPACE_ACTION) {
279 /* determine what type of data we are operating on */
280 data = get_action_context(&context);
281 if (data == NULL) return;
283 if (G.saction->lock) {
284 if (context == ACTCONT_ACTION) {
286 ob->ctime= -1234567.0f;
287 if(ob->pose || ob_get_key(ob))
288 DAG_object_flush_update(G.scene, ob, OB_RECALC);
290 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
293 else if (context == ACTCONT_SHAPEKEY) {
294 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
298 else if (t->spacetype == SPACE_NLA) {
300 for (base=G.scene->base.first; base; base=base->next) {
301 if (base->flag & BA_HAS_RECALC_OB)
302 base->object->recalc |= OB_RECALC_OB;
303 if (base->flag & BA_HAS_RECALC_DATA)
304 base->object->recalc |= OB_RECALC_DATA;
306 if (base->object->recalc)
307 base->object->ctime= -1234567.0f; // eveil!
310 DAG_scene_flush_update(G.scene, screen_view3d_layers());
313 else if (t->spacetype == SPACE_IPO) {
318 /* do the flush first */
319 flushTransIpoData(t);
321 /* now test if there is a need to re-sort */
323 for (a=0; a<G.sipo->totipo; a++, ei++) {
324 if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
326 /* watch it: if the time is wrong: do not correct handles */
327 if (test_time_ipocurve(ei->icu)) dosort++;
328 else testhandles_ipocurve(ei->icu);
332 /* do resort and other updates? */
333 if (dosort) remake_ipo_transdata(t);
334 if (G.sipo->showkey) update_ipokey_val();
336 calc_ipo(G.sipo->ipo, (float)CFRA);
338 /* update realtime - not working? */
340 if (G.sipo->blocktype==ID_MA || G.sipo->blocktype==ID_TE) {
343 else if(G.sipo->blocktype==ID_CA) {
346 else if(G.sipo->blocktype==ID_KE) {
349 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
350 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
353 else if(G.sipo->blocktype==ID_PO) {
356 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
359 else if(G.sipo->blocktype==ID_OB) {
360 Base *base= FIRSTBASE;
363 if(base->object->ipo==G.sipo->ipo) {
364 do_ob_ipo(base->object);
365 base->object->recalc |= OB_RECALC_OB;
369 DAG_scene_flush_update(G.scene, screen_view3d_layers());
374 if (G.obedit->type == OB_MESH) {
375 if(t->spacetype==SPACE_IMAGE) {
377 if (G.sima->flag & SI_LIVE_UNWRAP)
378 unwrap_lscm_live_re_solve();
383 /* mirror modifier clipping? */
384 if(t->state != TRANS_CANCEL)
385 clipMirrorModifier(t, G.obedit);
387 if((t->context & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
388 editmesh_apply_to_mirror(t);
390 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); /* sets recalc flags */
392 recalc_editnormals();
395 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
396 Nurb *nu= editNurb.first;
397 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); /* sets recalc flags */
401 testhandlesNurb(nu); /* test for bezier too */
407 else if(G.obedit->type==OB_ARMATURE){ /* no recalc flag, does pose */
408 bArmature *arm= G.obedit->data;
411 /* Ensure all bones are correctly adjusted */
412 for (ebo=G.edbo.first; ebo; ebo=ebo->next){
414 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
415 /* If this bone has a parent tip that has been moved */
416 if (ebo->parent->flag & BONE_TIPSEL){
417 VECCOPY (ebo->head, ebo->parent->tail);
418 if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
420 /* If this bone has a parent tip that has NOT been moved */
422 VECCOPY (ebo->parent->tail, ebo->head);
423 if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
427 /* on extrude bones, oldlength==0.0f, so we scale radius of points */
428 ebo->length= VecLenf(ebo->head, ebo->tail);
429 if(ebo->oldlength==0.0f) {
430 ebo->rad_head= 0.25f*ebo->length;
431 ebo->rad_tail= 0.10f*ebo->length;
432 ebo->dist= 0.25f*ebo->length;
434 if(ebo->rad_head > ebo->parent->rad_tail)
435 ebo->rad_head= ebo->parent->rad_tail;
438 else if(t->mode!=TFM_BONE_ENVELOPE) {
439 /* if bones change length, lets do that for the deform distance as well */
440 ebo->dist*= ebo->length/ebo->oldlength;
441 ebo->rad_head*= ebo->length/ebo->oldlength;
442 ebo->rad_tail*= ebo->length/ebo->oldlength;
443 ebo->oldlength= ebo->length;
446 if(arm->flag & ARM_MIRROR_EDIT)
447 transform_armature_mirror_update();
450 else if(G.obedit->type==OB_LATTICE) {
451 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); /* sets recalc flags */
453 if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
456 DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA); /* sets recalc flags */
459 else if( (t->flag & T_POSE) && t->poseobj) {
460 Object *ob= t->poseobj;
461 bArmature *arm= ob->data;
463 /* old optimize trick... this enforces to bypass the depgraph */
464 if (!(arm->flag & ARM_DELAYDEFORM)) {
465 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* sets recalc flags */
467 /* bah, softbody exception... recalcdata doesnt reset */
468 for(base= FIRSTBASE; base; base= base->next) {
469 if(base->object->recalc & OB_RECALC_DATA)
471 ClothModifierData *clmd = NULL;
473 if(modifiers_isSoftbodyEnabled(base->object)) {
474 base->object->softflag |= OB_SB_REDO;
476 else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) {
477 cloth_free_modifier(clmd);
486 else if(G.f & G_PARTICLEEDIT) {
487 flushTransParticles(t);
490 for(base= FIRSTBASE; base; base= base->next) {
491 Object *ob= base->object;
493 /* this flag is from depgraph, was stored in nitialize phase, handled in drawview.c */
494 if(base->flag & BA_HAS_RECALC_OB)
495 ob->recalc |= OB_RECALC_OB;
496 if(base->flag & BA_HAS_RECALC_DATA)
497 ob->recalc |= OB_RECALC_DATA;
499 /* thanks to ob->ctime usage, ipos are not called in where_is_object,
500 unless we edit ipokeys */
501 if(base->flag & BA_DO_IPO) {
505 ob->ctime= -1234567.0;
507 icu= ob->ipo->curve.first;
509 calchandles_ipocurve(icu);
515 /* softbody & cloth exception */
516 if(ob->recalc & OB_RECALC_DATA)
518 ClothModifierData *clmd = NULL;
520 if(modifiers_isSoftbodyEnabled(ob)) {
521 ob->softflag |= OB_SB_REDO;
523 else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) {
524 cloth_free_modifier(clmd);
528 /* proxy exception */
530 ob->proxy->recalc |= ob->recalc;
532 group_tag_recalc(ob->proxy_group->dup_group);
537 for (td = t->data; td < t->data + t->total; td++) {
538 if(td->flag & TD_VERSE_VERT) {
540 send_versevert_pos((VerseVert*)td->verse);
542 else if(td->flag & TD_VERSE_OBJECT)
543 if(td->verse) b_verse_send_transformation((Object*)td->verse);
547 /* update shaded drawmode while transform */
548 if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
549 reshadeall_displist();
553 void drawLine(float *center, float *dir, char axis, short options)
555 extern void make_axis_color(char *col, char *col2, char axis); // drawview.c
556 float v1[3], v2[3], v3[3];
557 char col[3], col2[3];
559 //if(G.obedit) mymultmatrix(G.obedit->obmat); // sets opengl viewing
562 VecMulf(v3, G.vd->far);
564 VecSubf(v2, center, v3);
565 VecAddf(v1, center, v3);
567 if (options & DRAWLIGHT) {
568 col[0] = col[1] = col[2] = 220;
571 BIF_GetThemeColor3ubv(TH_GRID, col);
573 make_axis_color(col, col2, axis);
574 glColor3ubv((GLubyte *)col2);
577 glBegin(GL_LINE_STRIP);
582 myloadmatrix(G.vd->viewmat);
585 void initTrans (TransInfo *t)
587 /* moving: is shown in drawobject() (transform color) */
588 if(G.obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
589 else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE;
590 else G.moving= G_TRANSFORM_OBJ;
599 /* setting PET flag */
600 if ((t->context & CTX_NO_PET) == 0 && (G.scene->proportional)) {
601 t->flag |= T_PROP_EDIT;
602 if(G.scene->proportional==2) t->flag |= T_PROP_CONNECTED; // yes i know, has to become define
605 getmouseco_areawin(t->imval);
606 t->con.imval[0] = t->imval[0];
607 t->con.imval[1] = t->imval[1];
610 t->handleEvent = NULL;
611 t->customData = NULL;
624 t->num.val[2] = 0.0f;
636 t->spacetype = curarea->spacetype;
637 if(t->spacetype==SPACE_VIEW3D) {
638 if(G.vd->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
639 t->around = G.vd->around;
640 } else if(t->spacetype==SPACE_IMAGE) {
641 t->around = G.v2d->around;
644 t->around = V3D_CENTER;
646 setTransformViewMatrices(t);
649 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
650 void postTrans (TransInfo *t)
654 G.moving = 0; // Set moving flag off (display as usual)
657 for (td = t->data; td < t->data + t->total; td++) {
658 if(td->flag & TD_VERSE_VERT) {
659 if(td->verse) send_versevert_pos((VerseVert*)td->verse);
661 else if(td->flag & TD_VERSE_OBJECT) {
664 vnode = (VNode*)((Object*)td->verse)->vnode;
665 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
666 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
667 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
668 b_verse_send_transformation((Object*)td->verse);
676 /* postTrans can be called when nothing is selected, so data is NULL already */
680 /* since ipokeys are optional on objects, we mallocced them per trans-data */
681 for(a=0, td= t->data; a<t->total; a++, td++) {
682 if(td->tdi) MEM_freeN(td->tdi);
687 if (t->ext) MEM_freeN(t->ext);
689 MEM_freeN(t->data2d);
693 if ((t->flag & T_FREE_CUSTOMDATA) && t->customData != NULL) {
694 MEM_freeN(t->customData);
697 if(t->spacetype==SPACE_IMAGE) {
698 if (G.sima->flag & SI_LIVE_UNWRAP)
699 unwrap_lscm_live_end(t->state == TRANS_CANCEL);
703 void applyTransObjects(TransInfo *t)
707 for (td = t->data; td < t->data + t->total; td++) {
708 VECCOPY(td->iloc, td->loc);
710 VECCOPY(td->ext->irot, td->ext->rot);
713 VECCOPY(td->ext->isize, td->ext->size);
719 /* helper for below */
720 static void restore_ipokey(float *poin, float *old)
729 static void restoreElement(TransData *td) {
730 /* TransData for crease has no loc */
732 VECCOPY(td->loc, td->iloc);
737 if (td->ext && (td->flag&TD_NO_EXT)==0) {
739 VECCOPY(td->ext->rot, td->ext->irot);
742 VECCOPY(td->ext->size, td->ext->isize);
744 if(td->flag & TD_USEQUAT) {
746 QUATCOPY(td->ext->quat, td->ext->iquat);
751 TransDataIpokey *tdi= td->tdi;
753 restore_ipokey(tdi->locx, tdi->oldloc);
754 restore_ipokey(tdi->locy, tdi->oldloc+1);
755 restore_ipokey(tdi->locz, tdi->oldloc+2);
757 restore_ipokey(tdi->rotx, tdi->oldrot);
758 restore_ipokey(tdi->roty, tdi->oldrot+1);
759 restore_ipokey(tdi->rotz, tdi->oldrot+2);
761 restore_ipokey(tdi->sizex, tdi->oldsize);
762 restore_ipokey(tdi->sizey, tdi->oldsize+1);
763 restore_ipokey(tdi->sizez, tdi->oldsize+2);
767 void restoreTransObjects(TransInfo *t)
771 for (td = t->data; td < t->data + t->total; td++) {
774 /* position of vertexes and object transformation matrix is sent
775 * extra, becuase blender uses synchronous sending of vertexes
776 * position as well object trans. matrix and it isn't possible to
777 * send it in recalcData sometimes */
778 if(td->flag & TD_VERSE_VERT) {
780 ((VerseVert*)td->verse)->flag |= VERT_POS_OBSOLETE;
783 else if(td->flag & TD_VERSE_OBJECT)
786 vnode = (VNode*)((Object*)td->verse)->vnode;
787 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
788 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
789 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
796 void calculateCenter2D(TransInfo *t)
798 if (t->flag & (T_EDIT|T_POSE)) {
799 Object *ob= G.obedit?G.obedit:t->poseobj;
802 VECCOPY(vec, t->center);
803 Mat4MulVecfl(ob->obmat, vec);
804 projectIntView(t, vec, t->center2d);
807 projectIntView(t, t->center, t->center2d);
811 void calculateCenterCursor(TransInfo *t)
815 cursor = give_cursor();
816 VECCOPY(t->center, cursor);
818 /* If edit or pose mode, move cursor in local space */
819 if (t->flag & (T_EDIT|T_POSE)) {
820 Object *ob = G.obedit?G.obedit:t->poseobj;
821 float mat[3][3], imat[3][3];
823 VecSubf(t->center, t->center, ob->obmat[3]);
824 Mat3CpyMat4(mat, ob->obmat);
826 Mat3MulVecfl(imat, t->center);
829 calculateCenter2D(t);
832 void calculateCenterCursor2D(TransInfo *t)
834 float aspx=1.0, aspy=1.0;
836 if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */
837 transform_aspect_ratio_tface_uv(&aspx, &aspy);
839 t->center[0] = G.v2d->cursor[0] * aspx;
840 t->center[1] = G.v2d->cursor[1] * aspy;
842 calculateCenter2D(t);
845 void calculateCenterMedian(TransInfo *t)
847 float partial[3] = {0.0f, 0.0f, 0.0f};
850 for(i = 0; i < t->total; i++) {
851 if (t->data[i].flag & TD_SELECTED) {
852 if (!(t->data[i].flag & TD_NOCENTER))
853 VecAddf(partial, partial, t->data[i].center);
857 All the selected elements are at the head of the array
858 which means we can stop when it finds unselected data
864 VecMulf(partial, 1.0f / i);
865 VECCOPY(t->center, partial);
867 calculateCenter2D(t);
870 void calculateCenterBound(TransInfo *t)
875 for(i = 0; i < t->total; i++) {
877 if (t->data[i].flag & TD_SELECTED) {
878 if (!(t->data[i].flag & TD_NOCENTER))
879 MinMax3(min, max, t->data[i].center);
883 All the selected elements are at the head of the array
884 which means we can stop when it finds unselected data
890 VECCOPY(max, t->data[i].center);
891 VECCOPY(min, t->data[i].center);
894 VecAddf(t->center, min, max);
895 VecMulf(t->center, 0.5);
897 calculateCenter2D(t);
900 void calculateCenter(TransInfo *t)
904 calculateCenterBound(t);
907 calculateCenterMedian(t);
910 if(t->spacetype==SPACE_IMAGE)
911 calculateCenterCursor2D(t);
913 calculateCenterCursor(t);
916 /* Individual element center uses median center for helpline and such */
917 calculateCenterMedian(t);
920 /* set median, and if if if... do object center */
922 /* EDIT MODE ACTIVE EDITMODE ELEMENT */
923 if (G.obedit && G.obedit->type == OB_MESH && G.editMesh->selected.last) {
924 EM_editselection_center(t->center, G.editMesh->selected.last);
925 calculateCenter2D(t);
927 } /* END EDIT MODE ACTIVE ELEMENT */
929 calculateCenterMedian(t);
930 if((t->flag & (T_EDIT|T_POSE))==0) {
933 VECCOPY(t->center, ob->obmat[3]);
934 projectIntView(t, t->center, t->center2d);
939 /* setting constraint center */
940 VECCOPY(t->con.center, t->center);
941 if(t->flag & (T_EDIT|T_POSE)) {
942 Object *ob= G.obedit?G.obedit:t->poseobj;
943 Mat4MulVecfl(ob->obmat, t->con.center);
946 /* voor panning from cameraview */
947 if(t->flag & T_OBJECT) {
948 if( G.vd->camera==OBACT && G.vd->persp>1) {
950 /* persinv is nasty, use viewinv instead, always right */
951 VECCOPY(axis, t->viewinv[2]);
954 /* 6.0 = 6 grid units */
955 axis[0]= t->center[0]- 6.0f*axis[0];
956 axis[1]= t->center[1]- 6.0f*axis[1];
957 axis[2]= t->center[2]- 6.0f*axis[2];
959 projectIntView(t, axis, t->center2d);
961 /* rotate only needs correct 2d center, grab needs initgrabz() value */
962 if(t->mode==TFM_TRANSLATION) {
963 VECCOPY(t->center, axis);
964 VECCOPY(t->con.center, t->center);
969 if(t->spacetype==SPACE_VIEW3D)
970 initgrabz(t->center[0], t->center[1], t->center[2]);
973 void calculatePropRatio(TransInfo *t)
975 TransData *td = t->data;
978 short connected = t->flag & T_PROP_CONNECTED;
980 if (t->flag & T_PROP_EDIT) {
981 for(i = 0 ; i < t->total; i++, td++) {
982 if (td->flag & TD_SELECTED) {
985 else if ((connected &&
986 (td->flag & TD_NOTCONNECTED || td->dist > t->propsize))
989 td->rdist > t->propsize)) {
991 The elements are sorted according to their dist member in the array,
992 that means we can stop when it finds one element outside of the propsize.
994 td->flag |= TD_NOACTION;
999 /* Use rdist for falloff calculations, it is the real distance */
1000 td->flag &= ~TD_NOACTION;
1001 dist= (t->propsize-td->rdist)/t->propsize;
1004 * Clamp to positive numbers.
1005 * Certain corner cases with connectivity and individual centers
1006 * can give values of rdist larger than propsize.
1011 switch(G.scene->prop_mode) {
1013 td->factor= dist*dist;
1016 td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
1019 td->factor = (float)sqrt(dist);
1028 td->factor = (float)sqrt(2*dist - dist * dist);
1031 BLI_srand( BLI_rand() ); /* random seed */
1032 td->factor = BLI_frand()*dist;
1039 switch(G.scene->prop_mode) {
1041 strcpy(t->proptext, "(Sharp)");
1044 strcpy(t->proptext, "(Smooth)");
1047 strcpy(t->proptext, "(Root)");
1050 strcpy(t->proptext, "(Linear)");
1053 strcpy(t->proptext, "(Constant)");
1056 strcpy(t->proptext, "(Sphere)");
1059 strcpy(t->proptext, "(Random)");
1062 strcpy(t->proptext, "");
1066 for(i = 0 ; i < t->total; i++, td++) {
1069 strcpy(t->proptext, "");
1073 TransInfo * BIF_GetTransInfo() {