4 * ***** BEGIN GPL 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.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
33 #include "MEM_guardedalloc.h"
35 #include "BLO_sys_types.h" // for intptr_t support
37 #include "DNA_action_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_constraint_types.h"
40 #include "DNA_curve_types.h"
41 #include "DNA_lattice_types.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_modifier_types.h"
44 #include "DNA_nla_types.h"
45 #include "DNA_node_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_object_force.h"
48 #include "DNA_particle_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_userdef_types.h"
53 #include "DNA_view3d_types.h"
55 //#include "BIF_screen.h"
56 //#include "BIF_resources.h"
57 //#include "BIF_mywindow.h"
59 //#include "BIF_editaction.h"
60 #include "BIF_editarmature.h"
61 //#include "BIF_editmesh.h"
62 //#include "BIF_editnla.h"
63 //#include "BIF_editsima.h"
64 //#include "BIF_editparticle.h"
65 //#include "BIF_meshtools.h"
66 #include "BIF_retopo.h"
68 //#include "BSE_editipo.h"
69 //#include "BSE_editipo_types.h"
72 #include "BIF_verse.h"
75 #include "BKE_action.h"
77 #include "BKE_armature.h"
78 #include "BKE_cloth.h"
79 #include "BKE_curve.h"
80 #include "BKE_depsgraph.h"
81 #include "BKE_displist.h"
82 #include "BKE_depsgraph.h"
83 #include "BKE_global.h"
84 #include "BKE_group.h"
86 #include "BKE_lattice.h"
89 #include "BKE_modifier.h"
90 #include "BKE_object.h"
91 #include "BKE_utildefines.h"
92 #include "BKE_context.h"
95 #include "BKE_verse.h"
98 #include "ED_view3d.h"
101 //#include "BSE_editaction_types.h"
102 //#include "BDR_unwrapper.h"
104 #include "BLI_arithb.h"
105 #include "BLI_blenlib.h"
106 #include "BLI_editVert.h"
107 #include "BLI_rand.h"
109 #include "WM_types.h"
111 //#include "blendef.h"
113 //#include "mydevice.h"
115 #include "transform.h"
117 extern ListBase editNurb;
118 extern ListBase editelems;
120 extern TransInfo Trans; /* From transform.c */
122 /* ************************** Functions *************************** */
124 void getViewVector(TransInfo *t, float coord[3], float vec[3])
126 if (t->persp != V3D_ORTHO)
134 Mat4MulVec4fl(t->viewmat, p2);
136 p2[0] = 2.0f * p2[0];
137 p2[1] = 2.0f * p2[1];
138 p2[2] = 2.0f * p2[2];
140 Mat4MulVec4fl(t->viewinv, p2);
142 VecSubf(vec, p1, p2);
145 VECCOPY(vec, t->viewinv[2]);
150 /* ************************** GENERICS **************************** */
152 static void clipMirrorModifier(TransInfo *t, Object *ob)
154 ModifierData *md= ob->modifiers.first;
155 float tolerance[3] = {0.0f, 0.0f, 0.0f};
158 for (; md; md=md->next) {
159 if (md->type==eModifierType_Mirror) {
160 MirrorModifierData *mmd = (MirrorModifierData*) md;
162 if(mmd->flag & MOD_MIR_CLIPPING) {
164 if(mmd->flag & MOD_MIR_AXIS_X) {
166 tolerance[0] = mmd->tolerance;
168 if(mmd->flag & MOD_MIR_AXIS_Y) {
170 tolerance[1] = mmd->tolerance;
172 if(mmd->flag & MOD_MIR_AXIS_Z) {
174 tolerance[2] = mmd->tolerance;
177 float mtx[4][4], imtx[4][4];
179 TransData *td = t->data;
181 if (mmd->mirror_ob) {
184 Mat4Invert(obinv, mmd->mirror_ob->obmat);
185 Mat4MulMat4(mtx, ob->obmat, obinv);
186 Mat4Invert(imtx, mtx);
189 for(i = 0 ; i < t->total; i++, td++) {
191 float loc[3], iloc[3];
193 if (td->flag & TD_NOACTION)
198 if (td->flag & TD_SKIP)
201 VecCopyf(loc, td->loc);
202 VecCopyf(iloc, td->iloc);
204 if (mmd->mirror_ob) {
205 VecMat4MulVecfl(loc, mtx, loc);
206 VecMat4MulVecfl(iloc, mtx, iloc);
211 if(fabs(iloc[0])<=tolerance[0] ||
212 loc[0]*iloc[0]<0.0f) {
219 if(fabs(iloc[1])<=tolerance[1] ||
220 loc[1]*iloc[1]<0.0f) {
226 if(fabs(iloc[2])<=tolerance[2] ||
227 loc[2]*iloc[2]<0.0f) {
233 if (mmd->mirror_ob) {
234 VecMat4MulVecfl(loc, imtx, loc);
236 VecCopyf(td->loc, loc);
246 /* assumes obedit set to mesh object */
247 static void editmesh_apply_to_mirror(TransInfo *t)
249 TransData *td = t->data;
253 for(i = 0 ; i < t->total; i++, td++) {
254 if (td->flag & TD_NOACTION)
258 if (td->flag & TD_SKIP)
263 eve->co[0]= -td->loc[0];
264 eve->co[1]= td->loc[1];
265 eve->co[2]= td->loc[2];
270 /* called for updating while transform acts, once per redraw */
271 void recalcData(TransInfo *t)
273 Scene *scene = t->scene;
276 struct TransData *td;
279 #if 0 // TRANSFORM_FIX_ME
280 if (t->spacetype == SPACE_ACTION) {
285 /* determine what type of data we are operating on */
286 data = get_action_context(&context);
287 if (data == NULL) return;
289 /* always flush data if gpencil context */
290 if (context == ACTCONT_GPENCIL) {
291 flushTransGPactionData(t);
294 if (G.saction->lock) {
295 if (context == ACTCONT_ACTION) {
297 ob->ctime= -1234567.0f;
298 if(ob->pose || ob_get_key(ob))
299 DAG_object_flush_update(G.scene, ob, OB_RECALC);
301 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
304 else if (context == ACTCONT_SHAPEKEY) {
305 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA);
309 else if (t->spacetype == SPACE_NLA) {
311 for (base=G.scene->base.first; base; base=base->next) {
312 if (base->flag & BA_HAS_RECALC_OB)
313 base->object->recalc |= OB_RECALC_OB;
314 if (base->flag & BA_HAS_RECALC_DATA)
315 base->object->recalc |= OB_RECALC_DATA;
317 if (base->object->recalc)
318 base->object->ctime= -1234567.0f; // eveil!
320 /* recalculate scale of selected nla-strips */
321 if (base->object->nlastrips.first) {
322 Object *bob= base->object;
325 for (strip= bob->nlastrips.first; strip; strip= strip->next) {
326 if (strip->flag & ACTSTRIP_SELECT) {
327 float actlen= strip->actend - strip->actstart;
328 float len= strip->end - strip->start;
330 strip->scale= len / (actlen * strip->repeat);
336 DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
339 for (base=G.scene->base.first; base; base=base->next) {
340 /* recalculate scale of selected nla-strips */
341 if (base->object && base->object->nlastrips.first) {
342 Object *bob= base->object;
345 for (strip= bob->nlastrips.first; strip; strip= strip->next) {
346 if (strip->flag & ACTSTRIP_SELECT) {
347 float actlen= strip->actend - strip->actstart;
348 float len= strip->end - strip->start;
350 /* prevent 'negative' scaling */
352 SWAP(float, strip->start, strip->end);
356 /* calculate new scale */
357 strip->scale= len / (actlen * strip->repeat);
364 else if (t->spacetype == SPACE_IPO) {
369 /* do the flush first */
370 flushTransIpoData(t);
372 /* now test if there is a need to re-sort */
374 for (a=0; a<G.sipo->totipo; a++, ei++) {
375 if (ISPOIN(ei, flag & IPO_VISIBLE, icu)) {
377 /* watch it: if the time is wrong: do not correct handles */
378 if (test_time_ipocurve(ei->icu)) {
381 calchandles_ipocurve(ei->icu);
386 /* do resort and other updates? */
387 if (dosort) remake_ipo_transdata(t);
388 if (G.sipo->showkey) update_ipokey_val();
390 calc_ipo(G.sipo->ipo, (float)CFRA);
392 /* update realtime - not working? */
394 if (G.sipo->blocktype==ID_MA || G.sipo->blocktype==ID_TE) {
397 else if(G.sipo->blocktype==ID_CA) {
400 else if(G.sipo->blocktype==ID_KE) {
403 ob->shapeflag &= ~OB_SHAPE_TEMPLOCK;
404 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
407 else if(G.sipo->blocktype==ID_PO) {
410 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
413 else if(G.sipo->blocktype==ID_OB) {
415 Base *base= FIRSTBASE;
417 /* only if this if active object has this ipo in an action (assumes that current ipo is in action) */
418 if ((ob) && (ob->ipoflag & OB_ACTION_OB) && (G.sipo->pin==0)) {
419 ob->ctime= -1234567.0f;
420 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
424 if(base->object->ipo==G.sipo->ipo) {
425 do_ob_ipo(base->object);
426 base->object->recalc |= OB_RECALC_OB;
430 DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0);
434 else if (t->obedit) {
435 if (t->obedit->type == OB_MESH) {
436 if(t->spacetype==SPACE_IMAGE) {
438 if (G.sima->flag & SI_LIVE_UNWRAP)
439 unwrap_lscm_live_re_solve();
441 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh
442 /* mirror modifier clipping? */
443 if(t->state != TRANS_CANCEL) {
444 if ((G.qual & LR_CTRLKEY)==0) {
445 /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */
448 clipMirrorModifier(t, t->obedit);
450 if((t->options & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
451 editmesh_apply_to_mirror(t);
453 DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
455 recalc_editnormals(em);
458 else if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
459 Nurb *nu= editNurb.first;
460 DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
462 if (t->state == TRANS_CANCEL) {
464 calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
468 /* Normal updating */
477 else if(t->obedit->type==OB_ARMATURE){ /* no recalc flag, does pose */
478 bArmature *arm= t->obedit->data;
480 TransData *td = t->data;
483 /* Ensure all bones are correctly adjusted */
484 for (ebo=G.edbo.first; ebo; ebo=ebo->next){
486 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
487 /* If this bone has a parent tip that has been moved */
488 if (ebo->parent->flag & BONE_TIPSEL){
489 VECCOPY (ebo->head, ebo->parent->tail);
490 if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
492 /* If this bone has a parent tip that has NOT been moved */
494 VECCOPY (ebo->parent->tail, ebo->head);
495 if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
499 /* on extrude bones, oldlength==0.0f, so we scale radius of points */
500 ebo->length= VecLenf(ebo->head, ebo->tail);
501 if(ebo->oldlength==0.0f) {
502 ebo->rad_head= 0.25f*ebo->length;
503 ebo->rad_tail= 0.10f*ebo->length;
504 ebo->dist= 0.25f*ebo->length;
506 if(ebo->rad_head > ebo->parent->rad_tail)
507 ebo->rad_head= ebo->parent->rad_tail;
510 else if(t->mode!=TFM_BONE_ENVELOPE) {
511 /* if bones change length, lets do that for the deform distance as well */
512 ebo->dist*= ebo->length/ebo->oldlength;
513 ebo->rad_head*= ebo->length/ebo->oldlength;
514 ebo->rad_tail*= ebo->length/ebo->oldlength;
515 ebo->oldlength= ebo->length;
520 if (t->mode != TFM_BONE_ROLL)
523 for(i = 0; i < t->total; i++, td++)
527 float vec[3], up_axis[3];
531 VECCOPY(up_axis, td->axismtx[2]);
533 if (t->mode != TFM_ROTATION)
535 VecSubf(vec, ebo->tail, ebo->head);
537 RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec);
538 QuatMulVecf(qrot, up_axis);
542 Mat3MulVecfl(t->mat, up_axis);
545 ebo->roll = rollBoneToVector(ebo, up_axis);
550 if(arm->flag & ARM_MIRROR_EDIT)
551 transform_armature_mirror_update();
554 else if(t->obedit->type==OB_LATTICE) {
555 DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
557 if(editLatt->flag & LT_OUTSIDE) outside_lattice(editLatt);
560 DAG_object_flush_update(G.scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
563 else if( (t->flag & T_POSE) && t->poseobj) {
564 Object *ob= t->poseobj;
565 bArmature *arm= ob->data;
567 /* old optimize trick... this enforces to bypass the depgraph */
568 if (!(arm->flag & ARM_DELAYDEFORM)) {
569 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* sets recalc flags */
574 else if(G.f & G_PARTICLEEDIT) {
575 flushTransParticles(t);
578 if (t->spacetype==SPACE_NODE) {
581 else if (t->obedit) {
582 if (t->obedit->type == OB_MESH) {
583 if(t->spacetype==SPACE_IMAGE) {
585 /* TRANSFORM_FIX_ME */
586 // if (G.sima->flag & SI_LIVE_UNWRAP)
587 // unwrap_lscm_live_re_solve();
589 EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
590 /* mirror modifier clipping? */
591 if(t->state != TRANS_CANCEL) {
592 /* TRANSFORM_FIX_ME */
593 // if ((G.qual & LR_CTRLKEY)==0) {
594 // /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */
597 clipMirrorModifier(t, t->obedit);
599 if((t->options & CTX_NO_MIRROR) == 0 && (t->scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
600 editmesh_apply_to_mirror(t);
602 DAG_object_flush_update(t->scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
604 recalc_editnormals(em);
609 for(base= FIRSTBASE; base; base= base->next) {
610 Object *ob= base->object;
612 /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */
613 if(base->flag & BA_HAS_RECALC_OB)
614 ob->recalc |= OB_RECALC_OB;
615 if(base->flag & BA_HAS_RECALC_DATA)
616 ob->recalc |= OB_RECALC_DATA;
618 /* thanks to ob->ctime usage, ipos are not called in where_is_object,
619 unless we edit ipokeys */
620 if(base->flag & BA_DO_IPO) {
624 ob->ctime= -1234567.0;
626 icu= ob->ipo->curve.first;
628 calchandles_ipocurve(icu);
634 /* proxy exception */
636 ob->proxy->recalc |= ob->recalc;
638 group_tag_recalc(ob->proxy_group->dup_group);
643 for (td = t->data; td < t->data + t->total; td++) {
644 if(td->flag & TD_VERSE_VERT) {
646 send_versevert_pos((VerseVert*)td->verse);
648 else if(td->flag & TD_VERSE_OBJECT)
649 if(td->verse) b_verse_send_transformation((Object*)td->verse);
653 /* update shaded drawmode while transform */
654 if(t->spacetype==SPACE_VIEW3D && ((View3D*)t->view)->drawtype == OB_SHADED)
655 reshadeall_displist();
658 void drawLine(float *center, float *dir, char axis, short options)
660 #if 0 // TRANSFORM_FIX_ME
661 extern void make_axis_color(char *col, char *col2, char axis); // drawview.c
662 float v1[3], v2[3], v3[3];
663 char col[3], col2[3];
665 //if(t->obedit) mymultmatrix(t->obedit->obmat); // sets opengl viewing
668 VecMulf(v3, G.vd->far);
670 VecSubf(v2, center, v3);
671 VecAddf(v1, center, v3);
673 if (options & DRAWLIGHT) {
674 col[0] = col[1] = col[2] = 220;
677 BIF_GetThemeColor3ubv(TH_GRID, col);
679 make_axis_color(col, col2, axis);
680 glColor3ubv((GLubyte *)col2);
683 glBegin(GL_LINE_STRIP);
688 myloadmatrix(G.vd->viewmat);
692 void resetTransRestrictions(TransInfo *t)
694 t->flag &= ~T_ALL_RESTRICTIONS;
697 void initTransInfo (bContext *C, TransInfo *t, wmEvent *event)
699 Scene *sce = CTX_data_scene(C);
700 ARegion *ar = CTX_wm_region(C);
701 ScrArea *sa = CTX_wm_area(C);
702 Object *obedit = CTX_data_edit_object(C);
704 /* moving: is shown in drawobject() (transform color) */
706 // if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
707 // else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE;
708 // else G.moving= G_TRANSFORM_OBJ;
720 t->redraw = 1; /* redraw first time */
722 t->propsize = 1.0f; /* TRANSFORM_FIX_ME this needs to be saved in scene or something */
724 /* setting PET flag */
725 if ((t->options & CTX_NO_PET) == 0 && (sce->proportional)) {
726 t->flag |= T_PROP_EDIT;
728 if(sce->proportional == 2)
729 t->flag |= T_PROP_CONNECTED; // yes i know, has to become define
734 t->imval[0] = event->x - t->ar->winrct.xmin;
735 t->imval[1] = event->y - t->ar->winrct.ymin;
743 t->con.imval[0] = t->imval[0];
744 t->con.imval[1] = t->imval[1];
746 t->mval[0] = t->imval[0];
747 t->mval[1] = t->imval[1];
750 t->handleEvent = NULL;
766 t->spacetype = sa->spacetype;
767 if(t->spacetype == SPACE_VIEW3D)
769 View3D *v3d = sa->spacedata.first;
773 if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
774 t->around = v3d->around;
776 else if(t->spacetype==SPACE_IMAGE || t->spacetype==SPACE_NODE)
778 View2D *v2d = sa->spacedata.first; // XXX no!
782 t->around = v2d->around;
786 // XXX for now, get View2D from the active region
789 t->around = V3D_CENTER;
792 setTransformViewMatrices(t);
793 initNumInput(&t->num);
794 initNDofInput(&t->ndof);
797 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
798 void postTrans (TransInfo *t)
802 G.moving = 0; // Set moving flag off (display as usual)
805 for (td = t->data; td < t->data + t->total; td++) {
806 if(td->flag & TD_VERSE_VERT) {
807 if(td->verse) send_versevert_pos((VerseVert*)td->verse);
809 else if(td->flag & TD_VERSE_OBJECT) {
812 vnode = (VNode*)((Object*)td->verse)->vnode;
813 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
814 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
815 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
816 b_verse_send_transformation((Object*)td->verse);
824 /* postTrans can be called when nothing is selected, so data is NULL already */
828 /* since ipokeys are optional on objects, we mallocced them per trans-data */
829 for(a=0, td= t->data; a<t->total; a++, td++) {
830 if(td->tdi) MEM_freeN(td->tdi);
831 if (td->flag & TD_BEZTRIPLE) MEM_freeN(td->hdata);
836 if (t->ext) MEM_freeN(t->ext);
838 MEM_freeN(t->data2d);
842 if(t->spacetype==SPACE_IMAGE) {
843 #if 0 // TRANSFORM_FIX_ME
844 if (G.sima->flag & SI_LIVE_UNWRAP)
845 unwrap_lscm_live_end(t->state == TRANS_CANCEL);
848 else if(t->spacetype==SPACE_ACTION) {
850 MEM_freeN(t->customData);
854 void applyTransObjects(TransInfo *t)
858 for (td = t->data; td < t->data + t->total; td++) {
859 VECCOPY(td->iloc, td->loc);
861 VECCOPY(td->ext->irot, td->ext->rot);
864 VECCOPY(td->ext->isize, td->ext->size);
870 /* helper for below */
871 static void restore_ipokey(float *poin, float *old)
880 static void restoreElement(TransData *td) {
881 /* TransData for crease has no loc */
883 VECCOPY(td->loc, td->iloc);
888 if (td->ext && (td->flag&TD_NO_EXT)==0) {
890 VECCOPY(td->ext->rot, td->ext->irot);
893 VECCOPY(td->ext->size, td->ext->isize);
895 if(td->flag & TD_USEQUAT) {
897 QUATCOPY(td->ext->quat, td->ext->iquat);
902 if (td->flag & TD_BEZTRIPLE) {
903 *(td->hdata->h1) = td->hdata->ih1;
904 *(td->hdata->h2) = td->hdata->ih2;
908 TransDataIpokey *tdi= td->tdi;
910 restore_ipokey(tdi->locx, tdi->oldloc);
911 restore_ipokey(tdi->locy, tdi->oldloc+1);
912 restore_ipokey(tdi->locz, tdi->oldloc+2);
914 restore_ipokey(tdi->rotx, tdi->oldrot);
915 restore_ipokey(tdi->roty, tdi->oldrot+1);
916 restore_ipokey(tdi->rotz, tdi->oldrot+2);
918 restore_ipokey(tdi->sizex, tdi->oldsize);
919 restore_ipokey(tdi->sizey, tdi->oldsize+1);
920 restore_ipokey(tdi->sizez, tdi->oldsize+2);
924 void restoreTransObjects(TransInfo *t)
928 for (td = t->data; td < t->data + t->total; td++) {
931 /* position of vertexes and object transformation matrix is sent
932 * extra, becuase blender uses synchronous sending of vertexes
933 * position as well object trans. matrix and it isn't possible to
934 * send it in recalcData sometimes */
935 if(td->flag & TD_VERSE_VERT) {
937 ((VerseVert*)td->verse)->flag |= VERT_POS_OBSOLETE;
940 else if(td->flag & TD_VERSE_OBJECT)
943 vnode = (VNode*)((Object*)td->verse)->vnode;
944 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
945 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
946 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
956 void calculateCenter2D(TransInfo *t)
958 if (t->flag & (T_EDIT|T_POSE)) {
959 Object *ob= t->obedit?t->obedit:t->poseobj;
962 VECCOPY(vec, t->center);
963 Mat4MulVecfl(ob->obmat, vec);
964 projectIntView(t, vec, t->center2d);
967 projectIntView(t, t->center, t->center2d);
971 void calculateCenterCursor(TransInfo *t)
975 cursor = give_cursor(t->scene, t->view);
976 VECCOPY(t->center, cursor);
978 /* If edit or pose mode, move cursor in local space */
979 if (t->flag & (T_EDIT|T_POSE)) {
980 Object *ob = t->obedit?t->obedit:t->poseobj;
981 float mat[3][3], imat[3][3];
983 VecSubf(t->center, t->center, ob->obmat[3]);
984 Mat3CpyMat4(mat, ob->obmat);
986 Mat3MulVecfl(imat, t->center);
989 calculateCenter2D(t);
992 void calculateCenterCursor2D(TransInfo *t)
994 #if 0 // TRANSFORM_FIX_ME
995 float aspx=1.0, aspy=1.0;
997 if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */
998 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1000 t->center[0] = G.v2d->cursor[0] * aspx;
1001 t->center[1] = G.v2d->cursor[1] * aspy;
1004 calculateCenter2D(t);
1007 void calculateCenterMedian(TransInfo *t)
1009 float partial[3] = {0.0f, 0.0f, 0.0f};
1013 for(i = 0; i < t->total; i++) {
1014 if (t->data[i].flag & TD_SELECTED) {
1015 if (!(t->data[i].flag & TD_NOCENTER))
1017 VecAddf(partial, partial, t->data[i].center);
1023 All the selected elements are at the head of the array
1024 which means we can stop when it finds unselected data
1030 VecMulf(partial, 1.0f / total);
1031 VECCOPY(t->center, partial);
1033 calculateCenter2D(t);
1036 void calculateCenterBound(TransInfo *t)
1041 for(i = 0; i < t->total; i++) {
1043 if (t->data[i].flag & TD_SELECTED) {
1044 if (!(t->data[i].flag & TD_NOCENTER))
1045 MinMax3(min, max, t->data[i].center);
1049 All the selected elements are at the head of the array
1050 which means we can stop when it finds unselected data
1056 VECCOPY(max, t->data[i].center);
1057 VECCOPY(min, t->data[i].center);
1060 VecAddf(t->center, min, max);
1061 VecMulf(t->center, 0.5);
1063 calculateCenter2D(t);
1066 void calculateCenter(TransInfo *t)
1070 calculateCenterBound(t);
1073 calculateCenterMedian(t);
1076 if(t->spacetype==SPACE_IMAGE)
1077 calculateCenterCursor2D(t);
1079 calculateCenterCursor(t);
1082 /* Individual element center uses median center for helpline and such */
1083 calculateCenterMedian(t);
1087 /* set median, and if if if... do object center */
1089 /* EDIT MODE ACTIVE EDITMODE ELEMENT */
1091 #if 0 // TRANSFORM_FIX_ME
1092 if (t->obedit && t->obedit->type == OB_MESH && EM_get_actSelection(&ese)) {
1093 EM_editselection_center(t->center, &ese);
1094 calculateCenter2D(t);
1096 } /* END EDIT MODE ACTIVE ELEMENT */
1099 calculateCenterMedian(t);
1100 if((t->flag & (T_EDIT|T_POSE))==0)
1102 Scene *scene = t->scene;
1106 VECCOPY(t->center, ob->obmat[3]);
1107 projectIntView(t, t->center, t->center2d);
1114 /* setting constraint center */
1115 VECCOPY(t->con.center, t->center);
1116 if(t->flag & (T_EDIT|T_POSE))
1118 Object *ob= t->obedit?t->obedit:t->poseobj;
1119 Mat4MulVecfl(ob->obmat, t->con.center);
1122 /* voor panning from cameraview */
1123 if(t->flag & T_OBJECT)
1125 if(t->spacetype==SPACE_VIEW3D)
1127 View3D *v3d = t->view;
1128 Scene *scene = t->scene;
1130 if(v3d->camera == OBACT && v3d->persp==V3D_CAMOB)
1133 /* persinv is nasty, use viewinv instead, always right */
1134 VECCOPY(axis, t->viewinv[2]);
1137 /* 6.0 = 6 grid units */
1138 axis[0]= t->center[0]- 6.0f*axis[0];
1139 axis[1]= t->center[1]- 6.0f*axis[1];
1140 axis[2]= t->center[2]- 6.0f*axis[2];
1142 projectIntView(t, axis, t->center2d);
1144 /* rotate only needs correct 2d center, grab needs initgrabz() value */
1145 if(t->mode==TFM_TRANSLATION)
1147 VECCOPY(t->center, axis);
1148 VECCOPY(t->con.center, t->center);
1154 if(t->spacetype==SPACE_VIEW3D)
1156 /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d() */
1157 if(t->flag & (T_EDIT|T_POSE)) {
1158 Object *ob= t->obedit?t->obedit:t->poseobj;
1161 VECCOPY(vec, t->center);
1162 Mat4MulVecfl(ob->obmat, vec);
1163 initgrabz(t->view, vec[0], vec[1], vec[2]);
1166 initgrabz(t->view, t->center[0], t->center[1], t->center[2]);
1171 void calculatePropRatio(TransInfo *t)
1173 TransData *td = t->data;
1176 short connected = t->flag & T_PROP_CONNECTED;
1178 if (t->flag & T_PROP_EDIT) {
1179 for(i = 0 ; i < t->total; i++, td++) {
1180 if (td->flag & TD_SELECTED) {
1183 else if ((connected &&
1184 (td->flag & TD_NOTCONNECTED || td->dist > t->propsize))
1187 td->rdist > t->propsize)) {
1189 The elements are sorted according to their dist member in the array,
1190 that means we can stop when it finds one element outside of the propsize.
1192 td->flag |= TD_NOACTION;
1197 /* Use rdist for falloff calculations, it is the real distance */
1198 td->flag &= ~TD_NOACTION;
1199 dist= (t->propsize-td->rdist)/t->propsize;
1202 * Clamp to positive numbers.
1203 * Certain corner cases with connectivity and individual centers
1204 * can give values of rdist larger than propsize.
1209 switch(G.scene->prop_mode) {
1211 td->factor= dist*dist;
1214 td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
1217 td->factor = (float)sqrt(dist);
1226 td->factor = (float)sqrt(2*dist - dist * dist);
1229 BLI_srand( BLI_rand() ); /* random seed */
1230 td->factor = BLI_frand()*dist;
1237 switch(G.scene->prop_mode) {
1239 strcpy(t->proptext, "(Sharp)");
1242 strcpy(t->proptext, "(Smooth)");
1245 strcpy(t->proptext, "(Root)");
1248 strcpy(t->proptext, "(Linear)");
1251 strcpy(t->proptext, "(Constant)");
1254 strcpy(t->proptext, "(Sphere)");
1257 strcpy(t->proptext, "(Random)");
1260 strcpy(t->proptext, "");
1264 for(i = 0 ; i < t->total; i++, td++) {
1267 strcpy(t->proptext, "");
1271 TransInfo *BIF_GetTransInfo()
1276 float get_drawsize(View3D *v3d, ScrArea *sa, float *co)
1278 float size, vec[3], len1, len2;
1280 /* size calculus, depending ortho/persp settings, like initgrabz() */
1281 size= v3d->persmat[0][3]*co[0]+ v3d->persmat[1][3]*co[1]+ v3d->persmat[2][3]*co[2]+ v3d->persmat[3][3];
1283 VECCOPY(vec, v3d->persinv[0]);
1284 len1= Normalize(vec);
1285 VECCOPY(vec, v3d->persinv[1]);
1286 len2= Normalize(vec);
1288 size*= 0.01f*(len1>len2?len1:len2);
1290 /* correct for window size to make widgets appear fixed size */
1291 if(sa->winx > sa->winy) size*= 1000.0f/(float)sa->winx;
1292 else size*= 1000.0f/(float)sa->winy;