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);
579 if (t->obedit->type == OB_MESH) {
580 if(t->spacetype==SPACE_IMAGE) {
582 /* TRANSFORM_FIX_ME */
583 // if (G.sima->flag & SI_LIVE_UNWRAP)
584 // unwrap_lscm_live_re_solve();
586 EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
587 /* mirror modifier clipping? */
588 if(t->state != TRANS_CANCEL) {
589 /* TRANSFORM_FIX_ME */
590 // if ((G.qual & LR_CTRLKEY)==0) {
591 // /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */
594 clipMirrorModifier(t, t->obedit);
596 if((t->options & CTX_NO_MIRROR) == 0 && (t->scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
597 editmesh_apply_to_mirror(t);
599 DAG_object_flush_update(t->scene, t->obedit, OB_RECALC_DATA); /* sets recalc flags */
601 recalc_editnormals(em);
606 for(base= FIRSTBASE; base; base= base->next) {
607 Object *ob= base->object;
609 /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */
610 if(base->flag & BA_HAS_RECALC_OB)
611 ob->recalc |= OB_RECALC_OB;
612 if(base->flag & BA_HAS_RECALC_DATA)
613 ob->recalc |= OB_RECALC_DATA;
615 /* thanks to ob->ctime usage, ipos are not called in where_is_object,
616 unless we edit ipokeys */
617 if(base->flag & BA_DO_IPO) {
621 ob->ctime= -1234567.0;
623 icu= ob->ipo->curve.first;
625 calchandles_ipocurve(icu);
631 /* proxy exception */
633 ob->proxy->recalc |= ob->recalc;
635 group_tag_recalc(ob->proxy_group->dup_group);
640 for (td = t->data; td < t->data + t->total; td++) {
641 if(td->flag & TD_VERSE_VERT) {
643 send_versevert_pos((VerseVert*)td->verse);
645 else if(td->flag & TD_VERSE_OBJECT)
646 if(td->verse) b_verse_send_transformation((Object*)td->verse);
650 /* update shaded drawmode while transform */
651 if(t->spacetype==SPACE_VIEW3D && ((View3D*)t->view)->drawtype == OB_SHADED)
652 reshadeall_displist();
655 void drawLine(float *center, float *dir, char axis, short options)
657 #if 0 // TRANSFORM_FIX_ME
658 extern void make_axis_color(char *col, char *col2, char axis); // drawview.c
659 float v1[3], v2[3], v3[3];
660 char col[3], col2[3];
662 //if(t->obedit) mymultmatrix(t->obedit->obmat); // sets opengl viewing
665 VecMulf(v3, G.vd->far);
667 VecSubf(v2, center, v3);
668 VecAddf(v1, center, v3);
670 if (options & DRAWLIGHT) {
671 col[0] = col[1] = col[2] = 220;
674 BIF_GetThemeColor3ubv(TH_GRID, col);
676 make_axis_color(col, col2, axis);
677 glColor3ubv((GLubyte *)col2);
680 glBegin(GL_LINE_STRIP);
685 myloadmatrix(G.vd->viewmat);
689 void resetTransRestrictions(TransInfo *t)
691 t->flag &= ~T_ALL_RESTRICTIONS;
694 void initTransInfo (bContext *C, TransInfo *t, wmEvent *event)
696 Scene *sce = CTX_data_scene(C);
697 ARegion *ar = CTX_wm_region(C);
698 ScrArea *sa = CTX_wm_area(C);
699 Object *obedit = CTX_data_edit_object(C);
701 /* moving: is shown in drawobject() (transform color) */
703 // if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
704 // else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE;
705 // else G.moving= G_TRANSFORM_OBJ;
717 t->redraw = 1; /* redraw first time */
719 t->propsize = 1.0f; /* TRANSFORM_FIX_ME this needs to be saved in scene or something */
721 /* setting PET flag */
722 if ((t->options & CTX_NO_PET) == 0 && (sce->proportional)) {
723 t->flag |= T_PROP_EDIT;
725 if(sce->proportional == 2)
726 t->flag |= T_PROP_CONNECTED; // yes i know, has to become define
731 t->imval[0] = event->x - t->ar->winrct.xmin;
732 t->imval[1] = event->y - t->ar->winrct.ymin;
740 t->con.imval[0] = t->imval[0];
741 t->con.imval[1] = t->imval[1];
743 t->mval[0] = t->imval[0];
744 t->mval[1] = t->imval[1];
747 t->handleEvent = NULL;
763 t->spacetype = sa->spacetype;
764 if(t->spacetype == SPACE_VIEW3D)
766 View3D *v3d = sa->spacedata.first;
770 if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
771 t->around = v3d->around;
773 else if(t->spacetype==SPACE_IMAGE || t->spacetype==SPACE_NODE)
775 View2D *v2d = sa->spacedata.first; // XXX no!
779 t->around = v2d->around;
783 // XXX for now, get View2D from the active region
786 t->around = V3D_CENTER;
789 setTransformViewMatrices(t);
790 initNumInput(&t->num);
791 initNDofInput(&t->ndof);
794 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
795 void postTrans (TransInfo *t)
799 G.moving = 0; // Set moving flag off (display as usual)
802 for (td = t->data; td < t->data + t->total; td++) {
803 if(td->flag & TD_VERSE_VERT) {
804 if(td->verse) send_versevert_pos((VerseVert*)td->verse);
806 else if(td->flag & TD_VERSE_OBJECT) {
809 vnode = (VNode*)((Object*)td->verse)->vnode;
810 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
811 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
812 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
813 b_verse_send_transformation((Object*)td->verse);
821 /* postTrans can be called when nothing is selected, so data is NULL already */
825 /* since ipokeys are optional on objects, we mallocced them per trans-data */
826 for(a=0, td= t->data; a<t->total; a++, td++) {
827 if(td->tdi) MEM_freeN(td->tdi);
828 if (td->flag & TD_BEZTRIPLE) MEM_freeN(td->hdata);
833 if (t->ext) MEM_freeN(t->ext);
835 MEM_freeN(t->data2d);
839 if(t->spacetype==SPACE_IMAGE) {
840 #if 0 // TRANSFORM_FIX_ME
841 if (G.sima->flag & SI_LIVE_UNWRAP)
842 unwrap_lscm_live_end(t->state == TRANS_CANCEL);
845 else if(t->spacetype==SPACE_ACTION) {
847 MEM_freeN(t->customData);
851 void applyTransObjects(TransInfo *t)
855 for (td = t->data; td < t->data + t->total; td++) {
856 VECCOPY(td->iloc, td->loc);
858 VECCOPY(td->ext->irot, td->ext->rot);
861 VECCOPY(td->ext->isize, td->ext->size);
867 /* helper for below */
868 static void restore_ipokey(float *poin, float *old)
877 static void restoreElement(TransData *td) {
878 /* TransData for crease has no loc */
880 VECCOPY(td->loc, td->iloc);
885 if (td->ext && (td->flag&TD_NO_EXT)==0) {
887 VECCOPY(td->ext->rot, td->ext->irot);
890 VECCOPY(td->ext->size, td->ext->isize);
892 if(td->flag & TD_USEQUAT) {
894 QUATCOPY(td->ext->quat, td->ext->iquat);
899 if (td->flag & TD_BEZTRIPLE) {
900 *(td->hdata->h1) = td->hdata->ih1;
901 *(td->hdata->h2) = td->hdata->ih2;
905 TransDataIpokey *tdi= td->tdi;
907 restore_ipokey(tdi->locx, tdi->oldloc);
908 restore_ipokey(tdi->locy, tdi->oldloc+1);
909 restore_ipokey(tdi->locz, tdi->oldloc+2);
911 restore_ipokey(tdi->rotx, tdi->oldrot);
912 restore_ipokey(tdi->roty, tdi->oldrot+1);
913 restore_ipokey(tdi->rotz, tdi->oldrot+2);
915 restore_ipokey(tdi->sizex, tdi->oldsize);
916 restore_ipokey(tdi->sizey, tdi->oldsize+1);
917 restore_ipokey(tdi->sizez, tdi->oldsize+2);
921 static void restoreNode(TransData2D *td)
923 td->loc2d[0]= td->loc[0];
924 td->loc2d[1]= td->loc[1];
927 void restoreTransNodes(TransInfo *t)
930 for (td = t->data2d; td < t->data2d + t->total; td++) {
935 void restoreTransObjects(TransInfo *t)
939 for (td = t->data; td < t->data + t->total; td++) {
942 /* position of vertexes and object transformation matrix is sent
943 * extra, becuase blender uses synchronous sending of vertexes
944 * position as well object trans. matrix and it isn't possible to
945 * send it in recalcData sometimes */
946 if(td->flag & TD_VERSE_VERT) {
948 ((VerseVert*)td->verse)->flag |= VERT_POS_OBSOLETE;
951 else if(td->flag & TD_VERSE_OBJECT)
954 vnode = (VNode*)((Object*)td->verse)->vnode;
955 ((VObjectData*)vnode->data)->flag |= POS_SEND_READY;
956 ((VObjectData*)vnode->data)->flag |= ROT_SEND_READY;
957 ((VObjectData*)vnode->data)->flag |= SCALE_SEND_READY;
967 void calculateCenter2D(TransInfo *t)
969 if (t->flag & (T_EDIT|T_POSE)) {
970 Object *ob= t->obedit?t->obedit:t->poseobj;
973 VECCOPY(vec, t->center);
974 Mat4MulVecfl(ob->obmat, vec);
975 projectIntView(t, vec, t->center2d);
978 projectIntView(t, t->center, t->center2d);
982 void calculateCenterCursor(TransInfo *t)
986 cursor = give_cursor(t->scene, t->view);
987 VECCOPY(t->center, cursor);
989 /* If edit or pose mode, move cursor in local space */
990 if (t->flag & (T_EDIT|T_POSE)) {
991 Object *ob = t->obedit?t->obedit:t->poseobj;
992 float mat[3][3], imat[3][3];
994 VecSubf(t->center, t->center, ob->obmat[3]);
995 Mat3CpyMat4(mat, ob->obmat);
997 Mat3MulVecfl(imat, t->center);
1000 calculateCenter2D(t);
1003 void calculateCenterCursor2D(TransInfo *t)
1005 #if 0 // TRANSFORM_FIX_ME
1006 float aspx=1.0, aspy=1.0;
1008 if(t->spacetype==SPACE_IMAGE) /* only space supported right now but may change */
1009 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1011 t->center[0] = G.v2d->cursor[0] * aspx;
1012 t->center[1] = G.v2d->cursor[1] * aspy;
1015 calculateCenter2D(t);
1018 void calculateCenterMedian(TransInfo *t)
1020 float partial[3] = {0.0f, 0.0f, 0.0f};
1024 for(i = 0; i < t->total; i++) {
1025 if (t->data[i].flag & TD_SELECTED) {
1026 if (!(t->data[i].flag & TD_NOCENTER))
1028 VecAddf(partial, partial, t->data[i].center);
1034 All the selected elements are at the head of the array
1035 which means we can stop when it finds unselected data
1041 VecMulf(partial, 1.0f / total);
1042 VECCOPY(t->center, partial);
1044 calculateCenter2D(t);
1047 void calculateCenterBound(TransInfo *t)
1052 for(i = 0; i < t->total; i++) {
1054 if (t->data[i].flag & TD_SELECTED) {
1055 if (!(t->data[i].flag & TD_NOCENTER))
1056 MinMax3(min, max, t->data[i].center);
1060 All the selected elements are at the head of the array
1061 which means we can stop when it finds unselected data
1067 VECCOPY(max, t->data[i].center);
1068 VECCOPY(min, t->data[i].center);
1071 VecAddf(t->center, min, max);
1072 VecMulf(t->center, 0.5);
1074 calculateCenter2D(t);
1077 void calculateCenter(TransInfo *t)
1081 calculateCenterBound(t);
1084 calculateCenterMedian(t);
1087 if(t->spacetype==SPACE_IMAGE)
1088 calculateCenterCursor2D(t);
1090 calculateCenterCursor(t);
1093 /* Individual element center uses median center for helpline and such */
1094 calculateCenterMedian(t);
1098 /* set median, and if if if... do object center */
1100 /* EDIT MODE ACTIVE EDITMODE ELEMENT */
1102 #if 0 // TRANSFORM_FIX_ME
1103 if (t->obedit && t->obedit->type == OB_MESH && EM_get_actSelection(&ese)) {
1104 EM_editselection_center(t->center, &ese);
1105 calculateCenter2D(t);
1107 } /* END EDIT MODE ACTIVE ELEMENT */
1110 calculateCenterMedian(t);
1111 if((t->flag & (T_EDIT|T_POSE))==0)
1113 Scene *scene = t->scene;
1117 VECCOPY(t->center, ob->obmat[3]);
1118 projectIntView(t, t->center, t->center2d);
1125 /* setting constraint center */
1126 VECCOPY(t->con.center, t->center);
1127 if(t->flag & (T_EDIT|T_POSE))
1129 Object *ob= t->obedit?t->obedit:t->poseobj;
1130 Mat4MulVecfl(ob->obmat, t->con.center);
1133 /* voor panning from cameraview */
1134 if(t->flag & T_OBJECT)
1136 if(t->spacetype==SPACE_VIEW3D)
1138 View3D *v3d = t->view;
1139 Scene *scene = t->scene;
1141 if(v3d->camera == OBACT && v3d->persp==V3D_CAMOB)
1144 /* persinv is nasty, use viewinv instead, always right */
1145 VECCOPY(axis, t->viewinv[2]);
1148 /* 6.0 = 6 grid units */
1149 axis[0]= t->center[0]- 6.0f*axis[0];
1150 axis[1]= t->center[1]- 6.0f*axis[1];
1151 axis[2]= t->center[2]- 6.0f*axis[2];
1153 projectIntView(t, axis, t->center2d);
1155 /* rotate only needs correct 2d center, grab needs initgrabz() value */
1156 if(t->mode==TFM_TRANSLATION)
1158 VECCOPY(t->center, axis);
1159 VECCOPY(t->con.center, t->center);
1165 if(t->spacetype==SPACE_VIEW3D)
1167 /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d() */
1168 if(t->flag & (T_EDIT|T_POSE)) {
1169 Object *ob= t->obedit?t->obedit:t->poseobj;
1172 VECCOPY(vec, t->center);
1173 Mat4MulVecfl(ob->obmat, vec);
1174 initgrabz(t->view, vec[0], vec[1], vec[2]);
1177 initgrabz(t->view, t->center[0], t->center[1], t->center[2]);
1182 void calculatePropRatio(TransInfo *t)
1184 TransData *td = t->data;
1187 short connected = t->flag & T_PROP_CONNECTED;
1189 if (t->spacetype == SPACE_NODE) return;
1191 if (t->flag & T_PROP_EDIT) {
1192 for(i = 0 ; i < t->total; i++, td++) {
1193 if (td->flag & TD_SELECTED) {
1196 else if ((connected &&
1197 (td->flag & TD_NOTCONNECTED || td->dist > t->propsize))
1200 td->rdist > t->propsize)) {
1202 The elements are sorted according to their dist member in the array,
1203 that means we can stop when it finds one element outside of the propsize.
1205 td->flag |= TD_NOACTION;
1210 /* Use rdist for falloff calculations, it is the real distance */
1211 td->flag &= ~TD_NOACTION;
1212 dist= (t->propsize-td->rdist)/t->propsize;
1215 * Clamp to positive numbers.
1216 * Certain corner cases with connectivity and individual centers
1217 * can give values of rdist larger than propsize.
1222 switch(G.scene->prop_mode) {
1224 td->factor= dist*dist;
1227 td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
1230 td->factor = (float)sqrt(dist);
1239 td->factor = (float)sqrt(2*dist - dist * dist);
1242 BLI_srand( BLI_rand() ); /* random seed */
1243 td->factor = BLI_frand()*dist;
1250 switch(G.scene->prop_mode) {
1252 strcpy(t->proptext, "(Sharp)");
1255 strcpy(t->proptext, "(Smooth)");
1258 strcpy(t->proptext, "(Root)");
1261 strcpy(t->proptext, "(Linear)");
1264 strcpy(t->proptext, "(Constant)");
1267 strcpy(t->proptext, "(Sphere)");
1270 strcpy(t->proptext, "(Random)");
1273 strcpy(t->proptext, "");
1277 for(i = 0 ; i < t->total; i++, td++) {
1280 strcpy(t->proptext, "");
1284 TransInfo *BIF_GetTransInfo()
1289 float get_drawsize(View3D *v3d, ScrArea *sa, float *co)
1291 float size, vec[3], len1, len2;
1293 /* size calculus, depending ortho/persp settings, like initgrabz() */
1294 size= v3d->persmat[0][3]*co[0]+ v3d->persmat[1][3]*co[1]+ v3d->persmat[2][3]*co[2]+ v3d->persmat[3][3];
1296 VECCOPY(vec, v3d->persinv[0]);
1297 len1= Normalize(vec);
1298 VECCOPY(vec, v3d->persinv[1]);
1299 len2= Normalize(vec);
1301 size*= 0.01f*(len1>len2?len1:len2);
1303 /* correct for window size to make widgets appear fixed size */
1304 if(sa->winx > sa->winy) size*= 1000.0f/(float)sa->winx;
1305 else size*= 1000.0f/(float)sa->winy;