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 *****
45 #include "MEM_guardedalloc.h"
47 #include "DNA_action_types.h"
48 #include "DNA_armature_types.h"
49 #include "DNA_camera_types.h"
50 #include "DNA_curve_types.h"
51 #include "DNA_effect_types.h"
52 #include "DNA_image_types.h"
53 #include "DNA_ipo_types.h"
54 #include "DNA_key_types.h"
55 #include "DNA_lamp_types.h"
56 #include "DNA_lattice_types.h"
57 #include "DNA_mesh_types.h"
58 #include "DNA_meshdata_types.h"
59 #include "DNA_meta_types.h"
60 #include "DNA_modifier_types.h"
61 #include "DNA_nla_types.h"
62 #include "DNA_object_types.h"
63 #include "DNA_object_force.h"
64 #include "DNA_particle_types.h"
65 #include "DNA_scene_types.h"
66 #include "DNA_screen_types.h"
67 #include "DNA_space_types.h"
68 #include "DNA_texture_types.h"
69 #include "DNA_view3d_types.h"
70 #include "DNA_world_types.h"
71 #include "DNA_userdef_types.h"
72 #include "DNA_property_types.h"
73 #include "DNA_vfont_types.h"
74 #include "DNA_constraint_types.h"
75 #include "DNA_listBase.h"
77 #include "BKE_action.h"
78 #include "BKE_armature.h"
79 #include "BKE_blender.h"
80 #include "BKE_cloth.h"
81 #include "BKE_curve.h"
82 #include "BKE_constraint.h"
83 #include "BKE_depsgraph.h"
84 #include "BKE_displist.h"
85 #include "BKE_DerivedMesh.h"
86 #include "BKE_effect.h"
88 #include "BKE_global.h"
90 #include "BKE_lattice.h"
93 #include "BKE_mball.h"
95 #include "BKE_modifier.h"
96 #include "BKE_object.h"
97 #include "BKE_particle.h"
98 #include "BKE_softbody.h"
99 #include "BKE_utildefines.h"
101 #include "BIF_editaction.h"
102 #include "BIF_editview.h"
103 #include "BIF_editlattice.h"
104 #include "BIF_editconstraint.h"
105 #include "BIF_editarmature.h"
106 #include "BIF_editmesh.h"
107 #include "BIF_editnla.h"
108 #include "BIF_editsima.h"
109 #include "BIF_editparticle.h"
111 #include "BIF_poseobject.h"
112 #include "BIF_meshtools.h"
113 #include "BIF_mywindow.h"
114 #include "BIF_resources.h"
115 #include "BIF_screen.h"
116 #include "BIF_space.h"
117 #include "BIF_toolbox.h"
119 #include "BSE_view.h"
120 #include "BSE_drawipo.h"
121 #include "BSE_edit.h"
122 #include "BSE_editipo.h"
123 #include "BSE_editipo_types.h"
124 #include "BSE_editaction_types.h"
126 #include "BDR_editobject.h" // reset_slowparents()
127 #include "BDR_unwrapper.h"
129 #include "BLI_arithb.h"
130 #include "BLI_blenlib.h"
131 #include "BLI_editVert.h"
133 #include "editmesh.h"
137 #include "mydevice.h"
139 extern ListBase editNurb;
140 extern ListBase editelems;
142 #include "transform.h"
144 /* local function prototype - for Object/Bone Constraints */
145 static short constraints_list_needinv(TransInfo *t, ListBase *list);
147 /* ************************** Functions *************************** */
149 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
150 TransData pivot = *head;
151 TransData *ihead = head;
152 TransData *itail = tail;
153 short connected = t->flag & T_PROP_CONNECTED;
158 while ((tail->dist >= pivot.dist) && (head < tail))
162 while ((tail->rdist >= pivot.rdist) && (head < tail))
173 while ((head->dist <= pivot.dist) && (head < tail))
177 while ((head->rdist <= pivot.rdist) && (head < tail))
190 qsort_trans_data(t, ihead, head-1);
193 qsort_trans_data(t, head+1, itail);
197 void sort_trans_data_dist(TransInfo *t) {
198 TransData *start = t->data;
201 while(i < t->total && start->flag & TD_SELECTED) {
205 qsort_trans_data(t, start, t->data + t->total - 1);
208 static void sort_trans_data(TransInfo *t)
210 TransData *sel, *unsel;
215 while (sel > unsel) {
216 while (unsel->flag & TD_SELECTED) {
222 while (!(sel->flag & TD_SELECTED)) {
236 /* distance calculated from not-selected vertex to nearest selected vertex
237 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
238 static void set_prop_dist(TransInfo *t, short with_dist)
243 for(a=0, tob= t->data; a<t->total; a++, tob++) {
245 tob->rdist= 0.0f; // init, it was mallocced
247 if((tob->flag & TD_SELECTED)==0) {
252 tob->rdist = -1.0f; // signal for next loop
254 for (i = 0, td= t->data; i < t->total; i++, td++) {
255 if(td->flag & TD_SELECTED) {
256 VecSubf(vec, tob->center, td->center);
257 Mat3MulVecfl(tob->mtx, vec);
258 dist = Normalize(vec);
259 if (tob->rdist == -1.0f) {
262 else if (dist < tob->rdist) {
266 else break; // by definition transdata has selected items in beginning
269 tob->dist = tob->rdist;
275 /* ************************** CONVERSIONS ************************* */
277 /* ********************* texture space ********* */
279 static void createTransTexspace(TransInfo *t)
287 if (ob==NULL) { // Shouldn't logically happen, but still...
293 if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
299 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
300 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
302 td->flag= TD_SELECTED;
303 VECCOPY(td->center, ob->obmat[3]);
306 Mat3CpyMat4(td->mtx, ob->obmat);
307 Mat3CpyMat4(td->axismtx, ob->obmat);
308 Mat3Ortho(td->axismtx);
309 Mat3Inv(td->smtx, td->mtx);
311 if( GS(id->name)==ID_ME) {
313 me->texflag &= ~AUTOSPACE;
315 td->ext->rot= me->rot;
316 td->ext->size= me->size;
318 else if( GS(id->name)==ID_CU) {
320 cu->texflag &= ~CU_AUTOSPACE;
322 td->ext->rot= cu->rot;
323 td->ext->size= cu->size;
325 else if( GS(id->name)==ID_MB) {
326 MetaBall *mb= ob->data;
327 mb->texflag &= ~MB_AUTOSPACE;
329 td->ext->rot= mb->rot;
330 td->ext->size= mb->size;
333 VECCOPY(td->iloc, td->loc);
334 VECCOPY(td->ext->irot, td->ext->rot);
335 VECCOPY(td->ext->isize, td->ext->size);
338 /* ********************* edge (for crease) ***** */
340 static void createTransEdge(TransInfo *t) {
341 TransData *td = NULL;
342 EditMesh *em = G.editMesh;
344 float mtx[3][3], smtx[3][3];
345 int count=0, countsel=0;
346 int propmode = t->flag & T_PROP_EDIT;
348 for(eed= em->edges.first; eed; eed= eed->next) {
350 if (eed->f & SELECT) countsel++;
351 if (propmode) count++;
365 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
367 Mat3CpyMat4(mtx, G.obedit->obmat);
370 for(eed= em->edges.first; eed; eed= eed->next) {
371 if(eed->h==0 && (eed->f & SELECT || propmode)) {
372 /* need to set center for center calculations */
373 VecAddf(td->center, eed->v1->co, eed->v2->co);
374 VecMulf(td->center, 0.5f);
378 td->flag= TD_SELECTED;
383 Mat3CpyMat3(td->smtx, smtx);
384 Mat3CpyMat3(td->mtx, mtx);
388 td->val = &(eed->crease);
389 td->ival = eed->crease;
396 /* ********************* pose mode ************* */
398 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
400 bConstraint *con= pchan->constraints.first;
402 for(;con; con= con->next) {
403 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
404 bKinematicConstraint *data= con->data;
408 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
415 static short apply_targetless_ik(Object *ob)
417 bPoseChannel *pchan, *parchan, *chanlist[256];
418 bKinematicConstraint *data;
419 int segcount, apply= 0;
421 /* now we got a difficult situation... we have to find the
422 target-less IK pchans, and apply transformation to the all
423 pchans that were in the chain */
425 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
426 data= has_targetless_ik(pchan);
427 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
429 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
432 /* exclude tip from chain? */
433 if(!(data->flag & CONSTRAINT_IK_TIP))
434 parchan= pchan->parent;
438 /* Find the chain's root & count the segments needed */
439 for (; parchan; parchan=parchan->parent){
440 chanlist[segcount]= parchan;
443 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
445 for(;segcount;segcount--) {
447 float rmat[4][4], tmat[4][4], imat[4][4];
449 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
450 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
451 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
452 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
454 parchan= chanlist[segcount-1];
456 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
458 if(parchan->parent) {
459 Bone *parbone= parchan->parent->bone;
460 float offs_bone[4][4];
462 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
463 Mat4CpyMat3(offs_bone, bone->bone_mat);
465 /* The bone's root offset (is in the parent's coordinate system) */
466 VECCOPY(offs_bone[3], bone->head);
468 /* Get the length translation of parent (length along y axis) */
469 offs_bone[3][1]+= parbone->length;
471 /* pose_mat(b-1) * offs_bone */
472 if(parchan->bone->flag & BONE_HINGE) {
473 /* the rotation of the parent restposition */
474 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
476 /* the location of actual parent transform */
477 VECCOPY(rmat[3], offs_bone[3]);
478 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
479 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
481 Mat4MulMat4(tmat, offs_bone, rmat);
484 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
486 Mat4Invert(imat, tmat);
489 Mat4CpyMat3(tmat, bone->bone_mat);
491 VECCOPY(tmat[3], bone->head);
492 Mat4Invert(imat, tmat);
495 Mat4MulMat4(rmat, parchan->pose_mat, imat);
497 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
499 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
501 Mat3CpyMat4(rmat3, rmat);
504 Mat3ToQuat(rmat3, parchan->quat);
506 /* for size, remove rotation */
507 QuatToMat3(parchan->quat, qmat);
509 Mat3MulMat3(smat, rmat3, imat);
510 Mat3ToSize(smat, parchan->size);
512 VECCOPY(parchan->loc, rmat[3]);
518 data->flag &= ~CONSTRAINT_IK_AUTO;
525 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
527 Bone *bone= pchan->bone;
528 float pmat[3][3], omat[3][3];
529 float cmat[3][3], tmat[3][3];
532 VECCOPY(vec, pchan->pose_mat[3]);
533 VECCOPY(td->center, vec);
536 td->flag= TD_SELECTED|TD_USEQUAT;
537 if(bone->flag & BONE_HINGE_CHILD_TRANSFORM)
538 td->flag |= TD_NOCENTER;
539 td->protectflag= pchan->protectflag;
541 td->loc = pchan->loc;
542 VECCOPY(td->iloc, pchan->loc);
545 td->ext->quat= pchan->quat;
546 td->ext->size= pchan->size;
548 QUATCOPY(td->ext->iquat, pchan->quat);
549 VECCOPY(td->ext->isize, pchan->size);
551 /* proper way to get parent transform + own transform + constraints transform */
552 Mat3CpyMat4(omat, ob->obmat);
555 if(pchan->bone->flag & BONE_HINGE)
556 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
558 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
560 if (constraints_list_needinv(t, &pchan->constraints)) {
561 Mat3CpyMat4(tmat, pchan->constinv);
563 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, cmat, omat, 0,0,0,0); // dang mulserie swaps args
566 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
569 if (constraints_list_needinv(t, &pchan->constraints)) {
570 Mat3CpyMat4(tmat, pchan->constinv);
572 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, cmat, omat, 0, 0,0,0,0); // dang mulserie swaps args
575 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
578 Mat3Inv(td->smtx, td->mtx);
580 /* for axismat we use bone's own transform */
581 Mat3CpyMat4(pmat, pchan->pose_mat);
582 Mat3MulMat3(td->axismtx, omat, pmat);
583 Mat3Ortho(td->axismtx);
585 if(t->mode==TFM_BONESIZE) {
586 bArmature *arm= t->poseobj->data;
588 if(arm->drawtype==ARM_ENVELOPE) {
590 td->val= &bone->dist;
591 td->ival= bone->dist;
594 // abusive storage of scale in the loc pointer :)
595 td->loc= &bone->xwidth;
596 VECCOPY (td->iloc, td->loc);
601 /* in this case we can do target-less IK grabbing */
602 if(t->mode==TFM_TRANSLATION) {
603 bKinematicConstraint *data= has_targetless_ik(pchan);
605 if(data->flag & CONSTRAINT_IK_TIP) {
606 VECCOPY(data->grabtarget, pchan->pose_tail);
609 VECCOPY(data->grabtarget, pchan->pose_head);
611 td->loc = data->grabtarget;
612 VECCOPY(td->iloc, td->loc);
613 data->flag |= CONSTRAINT_IK_AUTO;
615 /* only object matrix correction */
616 Mat3CpyMat3 (td->mtx, omat);
617 Mat3Inv (td->smtx, td->mtx);
622 static void bone_children_clear_transflag(ListBase *lb)
624 Bone *bone= lb->first;
626 for(;bone;bone= bone->next) {
627 if(bone->flag & BONE_HINGE)
628 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
630 bone->flag &= ~BONE_TRANSFORM;
632 bone_children_clear_transflag(&bone->childbase);
636 /* sets transform flags in the bones, returns total */
637 static void set_pose_transflags(TransInfo *t, Object *ob)
639 bArmature *arm= ob->data;
645 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
647 if(bone->layer & arm->layer) {
648 if(bone->flag & BONE_SELECTED)
649 bone->flag |= BONE_TRANSFORM;
651 bone->flag &= ~BONE_TRANSFORM;
653 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
657 /* make sure no bone can be transformed when a parent is transformed */
658 /* since pchans are depsgraph sorted, the parents are in beginning of list */
659 if(t->mode!=TFM_BONESIZE) {
660 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
662 if(bone->flag & BONE_TRANSFORM)
663 bone_children_clear_transflag(&bone->childbase);
666 /* now count, and check if we have autoIK or have to switch from translate to rotate */
667 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
669 if(bone->flag & BONE_TRANSFORM) {
672 if(t->mode==TFM_TRANSLATION) {
673 if( has_targetless_ik(pchan)==NULL ) {
674 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
675 if(!(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM))
676 t->mode= TFM_ROTATION;
678 else if((pchan->protectflag & OB_LOCK_LOC)==OB_LOCK_LOC)
679 t->mode= TFM_ROTATION;
686 /* frees temporal IKs */
687 static void pose_grab_with_ik_clear(Object *ob)
689 bKinematicConstraint *data;
693 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
694 for(con= pchan->constraints.first; con; con= con->next) {
695 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
697 if(data->flag & CONSTRAINT_IK_TEMP) {
698 BLI_remlink(&pchan->constraints, con);
699 MEM_freeN(con->data);
701 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
709 /* adds the IK to pchan */
710 static void pose_grab_with_ik_add(bPoseChannel *pchan)
712 bKinematicConstraint *data;
715 if (pchan == NULL) { // Sanity check
719 /* rule: not if there's already an IK on this channel */
720 for(con= pchan->constraints.first; con; con= con->next)
721 if(con->type==CONSTRAINT_TYPE_KINEMATIC)
725 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
726 data= has_targetless_ik(pchan);
728 data->flag |= CONSTRAINT_IK_AUTO;
732 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
733 BLI_addtail(&pchan->constraints, con);
734 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
736 data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
737 VECCOPY(data->grabtarget, pchan->pose_tail);
740 /* we include only a connected chain */
741 while(pchan && (pchan->bone->flag & BONE_CONNECTED)) {
743 pchan= pchan->parent;
747 /* bone is a canditate to get IK, but we don't do it if it has children connected */
748 static void pose_grab_with_ik_children(bPose *pose, Bone *bone)
753 /* go deeper if children & children are connected */
754 for(bonec= bone->childbase.first; bonec; bonec= bonec->next) {
755 if(bonec->flag & BONE_CONNECTED) {
757 pose_grab_with_ik_children(pose, bonec);
761 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
763 pose_grab_with_ik_add(pchan);
767 /* main call which adds temporal IK chains */
768 static void pose_grab_with_ik(Object *ob)
771 bPoseChannel *pchan, *pchansel= NULL;
774 if(ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0)
779 /* rule: only one Bone */
780 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
781 if(pchan->bone->layer & arm->layer) {
782 if(pchan->bone->flag & BONE_SELECTED) {
789 if(pchan || pchansel==NULL) return;
791 /* rule: no IK for solitary (unconnected) bone */
792 for(bonec=pchansel->bone->childbase.first; bonec; bonec=bonec->next) {
793 if(bonec->flag & BONE_CONNECTED) {
797 if ((pchansel->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) return;
799 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
800 if(pchansel->parent) {
801 /* only adds if there's no IK yet */
802 pose_grab_with_ik_add(pchansel);
805 /* rule: go over the children and add IK to the tips */
806 pose_grab_with_ik_children(ob->pose, pchansel->bone);
812 /* only called with pose mode active object now */
813 static void createTransPose(TransInfo *t, Object *ob)
818 TransDataExtension *tdx;
823 /* check validity of state */
824 arm=get_armature (ob);
825 if (arm==NULL || ob->pose==NULL) return;
827 if (arm->flag & ARM_RESTPOS) {
828 if(t->mode!=TFM_BONESIZE) {
829 notice ("Pose edit not possible while Rest Position is enabled");
833 if (!(ob->lay & G.vd->lay)) return;
835 /* do we need to add temporal IK chains? */
836 if((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION)
837 pose_grab_with_ik(ob);
839 /* set flags and count total (warning, can change transform to rotate) */
840 set_pose_transflags(t, ob);
842 if(t->total==0) return;
845 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
847 /* make sure the lock is set OK, unlock can be accidentally saved? */
848 ob->pose->flag |= POSE_LOCKED;
849 ob->pose->flag &= ~POSE_DO_UNLOCK;
851 /* init trans data */
852 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
853 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
854 for(i=0; i<t->total; i++, td++, tdx++) {
860 /* use pose channels to fill trans data */
862 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
863 if(pchan->bone->flag & BONE_TRANSFORM) {
864 add_pose_transdata(t, pchan, ob, td);
869 if(td != (t->data+t->total)) printf("Bone selection count error\n");
873 /* ********************* armature ************** */
875 static void createTransArmatureVerts(TransInfo *t)
878 bArmature *arm= G.obedit->data;
880 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
883 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
884 if(ebo->layer & arm->layer) {
885 if (t->mode==TFM_BONESIZE) {
886 if (ebo->flag & BONE_SELECTED)
889 else if (t->mode==TFM_BONE_ROLL) {
890 if (ebo->flag & BONE_SELECTED)
894 if (ebo->flag & BONE_TIPSEL)
896 if (ebo->flag & BONE_ROOTSEL)
902 if (!t->total) return;
904 Mat3CpyMat4(mtx, G.obedit->obmat);
907 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
909 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
910 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
912 if(ebo->layer & arm->layer) {
913 if (t->mode==TFM_BONE_ENVELOPE) {
915 if (ebo->flag & BONE_ROOTSEL){
916 td->val= &ebo->rad_head;
919 VECCOPY (td->center, ebo->head);
920 td->flag= TD_SELECTED;
922 Mat3CpyMat3(td->smtx, smtx);
923 Mat3CpyMat3(td->mtx, mtx);
931 if (ebo->flag & BONE_TIPSEL){
932 td->val= &ebo->rad_tail;
934 VECCOPY (td->center, ebo->tail);
935 td->flag= TD_SELECTED;
937 Mat3CpyMat3(td->smtx, smtx);
938 Mat3CpyMat3(td->mtx, mtx);
948 else if (t->mode==TFM_BONESIZE) {
949 if (ebo->flag & BONE_SELECTED) {
950 if(arm->drawtype==ARM_ENVELOPE) {
956 // abusive storage of scale in the loc pointer :)
957 td->loc= &ebo->xwidth;
958 VECCOPY (td->iloc, td->loc);
961 VECCOPY (td->center, ebo->head);
962 td->flag= TD_SELECTED;
964 /* use local bone matrix */
965 VecSubf(delta, ebo->tail, ebo->head);
966 vec_roll_to_mat3(delta, ebo->roll, bonemat);
967 Mat3MulMat3(td->mtx, mtx, bonemat);
968 Mat3Inv(td->smtx, td->mtx);
970 Mat3CpyMat3(td->axismtx, td->mtx);
971 Mat3Ortho(td->axismtx);
979 else if (t->mode==TFM_BONE_ROLL) {
980 if (ebo->flag & BONE_SELECTED) {
982 td->val= &(ebo->roll);
985 VECCOPY (td->center, ebo->head);
986 td->flag= TD_SELECTED;
995 if (ebo->flag & BONE_TIPSEL){
996 VECCOPY (td->iloc, ebo->tail);
997 VECCOPY (td->center, td->iloc);
999 td->flag= TD_SELECTED;
1001 Mat3CpyMat3(td->smtx, smtx);
1002 Mat3CpyMat3(td->mtx, mtx);
1010 if (ebo->flag & BONE_ROOTSEL){
1011 VECCOPY (td->iloc, ebo->head);
1012 VECCOPY (td->center, td->iloc);
1014 td->flag= TD_SELECTED;
1016 Mat3CpyMat3(td->smtx, smtx);
1017 Mat3CpyMat3(td->mtx, mtx);
1030 /* ********************* meta elements ********* */
1032 static void createTransMBallVerts(TransInfo *t)
1036 TransDataExtension *tx;
1037 float mtx[3][3], smtx[3][3];
1038 int count=0, countsel=0;
1039 int propmode = t->flag & T_PROP_EDIT;
1042 for(ml= editelems.first; ml; ml= ml->next) {
1043 if(ml->flag & SELECT) countsel++;
1044 if(propmode) count++;
1047 /* note: in prop mode we need at least 1 selected */
1048 if (countsel==0) return;
1050 if(propmode) t->total = count;
1051 else t->total = countsel;
1053 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1054 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1056 Mat3CpyMat4(mtx, G.obedit->obmat);
1059 for(ml= editelems.first; ml; ml= ml->next) {
1060 if(propmode || (ml->flag & SELECT)) {
1062 VECCOPY(td->iloc, td->loc);
1063 VECCOPY(td->center, td->loc);
1065 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1066 else td->flag= TD_USEQUAT;
1068 Mat3CpyMat3(td->smtx, smtx);
1069 Mat3CpyMat3(td->mtx, mtx);
1074 /* Radius of MetaElem (mass of MetaElem influence) */
1075 if(ml->flag & MB_SCALE_RAD){
1084 /* expx/expy/expz determine "shape" of some MetaElem types */
1085 tx->size = &ml->expx;
1086 tx->isize[0] = ml->expx;
1087 tx->isize[1] = ml->expy;
1088 tx->isize[2] = ml->expz;
1090 /* quat is used for rotation of MetaElem */
1091 tx->quat = ml->quat;
1092 QUATCOPY(tx->iquat, ml->quat);
1102 /* ********************* curve/surface ********* */
1104 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1105 TransData *td, *td_near = NULL;
1106 for (td = head; td<=tail; td++) {
1107 if (td->flag & TD_SELECTED) {
1113 dist = VecLenf(td_near->center, td->center);
1114 if (dist < (td-1)->dist) {
1115 td->dist = (td-1)->dist;
1122 td->dist = MAXFLOAT;
1123 td->flag |= TD_NOTCONNECTED;
1127 for (td = tail; td>=head; td--) {
1128 if (td->flag & TD_SELECTED) {
1134 dist = VecLenf(td_near->center, td->center);
1135 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1136 td->flag &= ~TD_NOTCONNECTED;
1137 if (dist < (td+1)->dist) {
1138 td->dist = (td+1)->dist;
1148 static void createTransCurveVerts(TransInfo *t)
1150 TransData *td = NULL;
1154 float mtx[3][3], smtx[3][3];
1156 int count=0, countsel=0;
1157 int propmode = t->flag & T_PROP_EDIT;
1159 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1160 for(nu= editNurb.first; nu; nu= nu->next) {
1161 if((nu->type & 7)==CU_BEZIER) {
1162 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1164 if (G.f & G_HIDDENHANDLES) {
1165 if(bezt->f2 & 1) countsel+=3;
1166 if(propmode) count+= 3;
1168 if(bezt->f1 & 1) countsel++;
1169 if(bezt->f2 & 1) countsel++;
1170 if(bezt->f3 & 1) countsel++;
1171 if(propmode) count+= 3;
1177 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1179 if(propmode) count++;
1180 if(bp->f1 & 1) countsel++;
1185 /* note: in prop mode we need at least 1 selected */
1186 if (countsel==0) return;
1188 if(propmode) t->total = count;
1189 else t->total = countsel;
1190 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1192 Mat3CpyMat4(mtx, G.obedit->obmat);
1196 for(nu= editNurb.first; nu; nu= nu->next) {
1197 if((nu->type & 7)==CU_BEZIER) {
1198 TransData *head, *tail;
1200 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1204 ((bezt->f2 & 1) && (G.f & G_HIDDENHANDLES)) ||
1205 ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)==0)
1207 VECCOPY(td->iloc, bezt->vec[0]);
1208 td->loc= bezt->vec[0];
1209 VECCOPY(td->center, bezt->vec[1]);
1210 if(bezt->f1 & 1 || G.f & G_HIDDENHANDLES) td->flag= TD_SELECTED;
1216 Mat3CpyMat3(td->smtx, smtx);
1217 Mat3CpyMat3(td->mtx, mtx);
1224 /* This is the Curve Point, the other two are handles */
1225 if(propmode || (bezt->f2 & 1)) {
1226 VECCOPY(td->iloc, bezt->vec[1]);
1227 td->loc= bezt->vec[1];
1228 VECCOPY(td->center, td->loc);
1229 if(bezt->f2 & 1) td->flag= TD_SELECTED;
1234 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1235 td->val = &(bezt->radius);
1236 td->ival = bezt->radius;
1237 } else if (t->mode==TFM_TILT) {
1238 td->val = &(bezt->alfa);
1239 td->ival = bezt->alfa;
1244 Mat3CpyMat3(td->smtx, smtx);
1245 Mat3CpyMat3(td->mtx, mtx);
1252 ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)) ||
1253 ((bezt->f3 & 1) && (G.f & G_HIDDENHANDLES)==0)
1255 VECCOPY(td->iloc, bezt->vec[2]);
1256 td->loc= bezt->vec[2];
1257 VECCOPY(td->center, bezt->vec[1]);
1258 if(bezt->f3 & 1 || (G.f & G_HIDDENHANDLES)) td->flag= TD_SELECTED;
1264 Mat3CpyMat3(td->smtx, smtx);
1265 Mat3CpyMat3(td->mtx, mtx);
1272 else if (propmode && head != tail) {
1273 calc_distanceCurveVerts(head, tail-1);
1277 if (propmode && head != tail)
1278 calc_distanceCurveVerts(head, tail-1);
1281 TransData *head, *tail;
1283 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1285 if(propmode || (bp->f1 & 1)) {
1286 VECCOPY(td->iloc, bp->vec);
1288 VECCOPY(td->center, td->loc);
1289 if(bp->f1 & 1) td->flag= TD_SELECTED;
1294 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1295 td->val = &(bp->radius);
1296 td->ival = bp->radius;
1298 td->val = &(bp->alfa);
1299 td->ival = bp->alfa;
1302 Mat3CpyMat3(td->smtx, smtx);
1303 Mat3CpyMat3(td->mtx, mtx);
1310 else if (propmode && head != tail) {
1311 calc_distanceCurveVerts(head, tail-1);
1315 if (propmode && head != tail)
1316 calc_distanceCurveVerts(head, tail-1);
1321 /* ********************* lattice *************** */
1323 static void createTransLatticeVerts(TransInfo *t)
1325 TransData *td = NULL;
1327 float mtx[3][3], smtx[3][3];
1329 int count=0, countsel=0;
1330 int propmode = t->flag & T_PROP_EDIT;
1333 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1336 if(bp->f1 & 1) countsel++;
1337 if(propmode) count++;
1342 /* note: in prop mode we need at least 1 selected */
1343 if (countsel==0) return;
1345 if(propmode) t->total = count;
1346 else t->total = countsel;
1347 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1349 Mat3CpyMat4(mtx, G.obedit->obmat);
1354 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1356 if(propmode || (bp->f1 & 1)) {
1358 VECCOPY(td->iloc, bp->vec);
1360 VECCOPY(td->center, td->loc);
1361 if(bp->f1 & 1) td->flag= TD_SELECTED;
1363 Mat3CpyMat3(td->smtx, smtx);
1364 Mat3CpyMat3(td->mtx, mtx);
1378 /* ******************* particle edit **************** */
1379 static void createTransParticleVerts(TransInfo *t)
1381 TransData *td = NULL;
1382 TransDataExtension *tx;
1383 Base *base = BASACT;
1385 ParticleSystem *psys = PE_get_current(ob);
1386 ParticleSystemModifierData *psmd = NULL;
1387 ParticleEditSettings *pset = PE_settings();
1388 ParticleData *pa = NULL;
1390 ParticleEditKey *key;
1392 int i,k, totpart, transformparticle;
1393 int count = 0, hasselected = 0;
1394 int propmode = t->flag & T_PROP_EDIT;
1396 if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1398 psmd = psys_get_modifier(ob,psys);
1401 totpart = psys->totpart;
1402 base->flag |= BA_HAS_RECALC_DATA;
1404 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1405 pa->flag &= ~PARS_TRANSFORM;
1406 transformparticle= 0;
1408 if((pa->flag & PARS_HIDE)==0) {
1409 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1410 if((key->flag&PEK_HIDE)==0) {
1411 if(key->flag&PEK_SELECT) {
1413 transformparticle= 1;
1416 transformparticle= 1;
1421 if(transformparticle) {
1422 count += pa->totkey;
1423 pa->flag |= PARS_TRANSFORM;
1427 /* note: in prop mode we need at least 1 selected */
1428 if (hasselected==0) return;
1431 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1433 if(t->mode == TFM_BAKE_TIME)
1434 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1440 Mat4Invert(ob->imat,ob->obmat);
1442 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1443 TransData *head, *tail;
1446 if(!(pa->flag & PARS_TRANSFORM)) continue;
1448 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1450 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1451 VECCOPY(key->world_co, key->co);
1452 Mat4MulVecfl(mat, key->world_co);
1453 td->loc = key->world_co;
1455 VECCOPY(td->iloc, td->loc);
1456 VECCOPY(td->center, td->loc);
1458 if(key->flag & PEK_SELECT)
1459 td->flag |= TD_SELECTED;
1461 td->flag |= TD_SKIP;
1466 /* don't allow moving roots */
1467 if(k==0 && pset->flag & PE_LOCK_FIRST)
1468 td->protectflag |= OB_LOCK_LOC;
1472 if(t->mode == TFM_BAKE_TIME) {
1473 td->val = key->time;
1474 td->ival = *(key->time);
1475 /* abuse size and quat for min/max values */
1476 td->flag |= TD_NO_EXT;
1477 if(k==0) tx->size = 0;
1478 else tx->size = (key - 1)->time;
1480 if(k == pa->totkey - 1) tx->quat = 0;
1481 else tx->quat = (key + 1)->time;
1489 if (propmode && head != tail)
1490 calc_distanceCurveVerts(head, tail - 1);
1494 void flushTransParticles(TransInfo *t)
1497 ParticleSystem *psys = PE_get_current(ob);
1498 ParticleSystemModifierData *psmd;
1500 ParticleEditKey *key;
1502 float mat[4][4], imat[4][4], co[3];
1503 int i, k, propmode = t->flag & T_PROP_EDIT;
1505 psmd = psys_get_modifier(ob, psys);
1507 /* we do transform in world space, so flush world space position
1508 * back to particle local space */
1510 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1511 if(!(pa->flag & PARS_TRANSFORM)) continue;
1513 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1514 Mat4Invert(imat,mat);
1516 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1517 VECCOPY(co, key->world_co);
1518 Mat4MulVecfl(imat, co);
1520 /* optimization for proportional edit */
1521 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1522 VECCOPY(key->co, co);
1523 pa->flag |= PARS_EDIT_RECALC;
1528 PE_update_object(OBACT, 1);
1531 /* ********************* mesh ****************** */
1533 /* proportional distance based on connectivity */
1534 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1535 #define E_NEAR(a) (nears[((a)->tmp.l)])
1536 #define THRESHOLD 0.0001f
1537 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1539 EditMesh *em = G.editMesh;
1544 /* f2 flag is used for 'selection' */
1545 /* tmp.l is offset on scratch array */
1546 for(eve= em->verts.first; eve; eve= eve->next) {
1550 if(eve->f & SELECT) {
1553 E_VEC(eve)[0] = 0.0f;
1554 E_VEC(eve)[1] = 0.0f;
1555 E_VEC(eve)[2] = 0.0f;
1564 /* Floodfill routine */
1566 At worst this is n*n of complexity where n is number of edges
1567 Best case would be n if the list is ordered perfectly.
1568 Estimate is n log n in average (so not too bad)
1573 for(eed= em->edges.first; eed; eed= eed->next) {
1575 EditVert *v1= eed->v1, *v2= eed->v2;
1576 float *vec2 = E_VEC(v2);
1577 float *vec1 = E_VEC(v1);
1579 if (v1->f2 + v2->f2 == 4)
1585 float len1 = VecLength(vec1);
1586 float len2 = VecLength(vec2);
1588 /* for v2 if not selected */
1590 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1591 lenn = VecLength(nvec);
1593 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1594 VECCOPY(vec2, nvec);
1595 E_NEAR(v2) = E_NEAR(v1);
1599 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1600 VECCOPY(vec2, vec1);
1601 E_NEAR(v2) = E_NEAR(v1);
1605 /* for v1 if not selected */
1607 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1608 lenn = VecLength(nvec);
1610 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1611 VECCOPY(vec1, nvec);
1612 E_NEAR(v1) = E_NEAR(v2);
1616 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1617 VECCOPY(vec1, vec2);
1618 E_NEAR(v1) = E_NEAR(v2);
1625 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1627 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1628 VECCOPY(vec2, vec1);
1630 E_NEAR(v2) = E_NEAR(v1);
1636 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1638 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1639 VECCOPY(vec1, vec2);
1641 E_NEAR(v1) = E_NEAR(v2);
1649 /* loop-in-a-loop I know, but we need it! (ton) */
1650 static void get_face_center(float *cent, EditVert *eve)
1652 EditMesh *em = G.editMesh;
1655 for(efa= em->faces.first; efa; efa= efa->next)
1657 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1660 VECCOPY(cent, efa->cent);
1664 //way to overwrite what data is edited with transform
1665 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1666 static void VertsToTransData(TransData *td, EditVert *eve)
1670 // td->loc = key->co;
1674 VECCOPY(td->center, td->loc);
1675 if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1676 get_face_center(td->center, eve);
1677 VECCOPY(td->iloc, td->loc);
1680 VECCOPY(td->axismtx[2], eve->no);
1686 td->axismtx[1][2] = 0.0f;
1695 td->verse = (void*)eve->vvert;
1696 td->flag |= TD_VERSE_VERT;
1699 td->flag &= ~TD_VERSE_VERT;
1703 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1705 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1707 float *vec = userData;
1713 static int modifiers_disable_subsurf_temporary(Object *ob)
1718 for(md=ob->modifiers.first; md; md=md->next)
1719 if(md->type==eModifierType_Subsurf)
1720 if(md->mode & eModifierMode_OnCage) {
1721 md->mode ^= eModifierMode_DisableTemporary;
1728 /* disable subsurf temporal, get mapped cos, and enable it */
1729 static float *get_crazy_mapped_editverts(void)
1734 /* disable subsurf temporal, get mapped cos, and enable it */
1735 if(modifiers_disable_subsurf_temporary(G.obedit)) {
1736 /* need to make new derivemesh */
1737 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1740 /* now get the cage */
1741 dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1743 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1744 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1748 /* set back the flag, no new cage needs to be built, transform does it */
1749 modifiers_disable_subsurf_temporary(G.obedit);
1754 #define TAN_MAKE_VEC(a, b, c) a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2])
1755 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1757 float vecu[3], vecv[3];
1760 TAN_MAKE_VEC(vecu, v1, v2);
1761 TAN_MAKE_VEC(vecv, v1, v3);
1762 triatoquat(v1, vecu, vecv, q1);
1764 TAN_MAKE_VEC(vecu, def1, def2);
1765 TAN_MAKE_VEC(vecv, def1, def3);
1766 triatoquat(def1, vecu, vecv, q2);
1768 QuatSub(quat, q2, q1);
1772 static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
1774 EditMesh *em = G.editMesh;
1775 EditVert *eve, *prev;
1777 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
1780 /* two abused locations in vertices */
1781 for(eve= em->verts.first; eve; eve= eve->next, index++) {
1783 eve->prev= (EditVert *)index;
1786 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1787 for(efa= em->faces.first; efa; efa= efa->next) {
1789 /* retrieve mapped coordinates */
1790 v1= mappedcos + 3*(long)(efa->v1->prev);
1791 v2= mappedcos + 3*(long)(efa->v2->prev);
1792 v3= mappedcos + 3*(long)(efa->v3->prev);
1794 co1= (origcos)? origcos + 3*(long)(efa->v1->prev): efa->v1->co;
1795 co2= (origcos)? origcos + 3*(long)(efa->v2->prev): efa->v2->co;
1796 co3= (origcos)? origcos + 3*(long)(efa->v3->prev): efa->v3->co;
1798 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
1799 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
1800 efa->v2->tmp.p= (void*)quats;
1805 v4= mappedcos + 3*(long)(efa->v4->prev);
1806 co4= (origcos)? origcos + 3*(long)(efa->v4->prev): efa->v4->co;
1808 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1809 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
1810 efa->v1->tmp.p= (void*)quats;
1813 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1814 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
1815 efa->v3->tmp.p= (void*)quats;
1818 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
1819 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
1820 efa->v4->tmp.p= (void*)quats;
1825 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1826 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
1827 efa->v1->tmp.p= (void*)quats;
1830 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1831 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
1832 efa->v3->tmp.p= (void*)quats;
1838 /* restore abused prev pointer */
1839 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1844 static void createTransEditVerts(TransInfo *t)
1846 TransData *tob = NULL;
1847 EditMesh *em = G.editMesh;
1849 EditVert **nears = NULL;
1850 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1851 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
1852 int count=0, countsel=0, a, totleft;
1853 int propmode = t->flag & T_PROP_EDIT;
1856 if ((t->context & CTX_NO_MIRROR) == 0 || (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
1861 // transform now requires awareness for select mode, so we tag the f1 flags in verts
1862 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1863 for(eve= em->verts.first; eve; eve= eve->next) {
1864 if(eve->h==0 && (eve->f & SELECT))
1870 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1872 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1873 for(eed= em->edges.first; eed; eed= eed->next) {
1874 if(eed->h==0 && (eed->f & SELECT))
1875 eed->v1->f1= eed->v2->f1= SELECT;
1880 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1881 for(efa= em->faces.first; efa; efa= efa->next) {
1882 if(efa->h==0 && (efa->f & SELECT)) {
1883 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1884 if(efa->v4) efa->v4->f1= SELECT;
1889 /* now we can count */
1890 for(eve= em->verts.first; eve; eve= eve->next) {
1892 if(eve->f1) countsel++;
1893 if(propmode) count++;
1897 /* note: in prop mode we need at least 1 selected */
1898 if (countsel==0) return;
1903 /* allocating scratch arrays */
1904 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1905 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1907 else t->total = countsel;
1908 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1910 Mat3CpyMat4(mtx, G.obedit->obmat);
1913 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1915 /* detect CrazySpace [tm] */
1917 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1918 if(modifiers_isDeformed(G.obedit)) {
1919 /* check if we can use deform matrices for modifier from the
1920 start up to stack, they are more accurate than quats */
1921 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
1923 /* if we still have more modifiers, also do crazyspace
1924 correction with quats, relative to the coordinates after
1925 the modifiers that support deform matrices (defcos) */
1927 mappedcos= get_crazy_mapped_editverts();
1928 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
1929 set_crazyspace_quats((float*)defcos, mappedcos, quats);
1931 MEM_freeN(mappedcos);
1940 /* find out which half we do */
1942 for (eve=em->verts.first; eve; eve=eve->next) {
1943 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1951 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
1953 if(propmode || eve->f1) {
1954 VertsToTransData(tob, eve);
1956 if(eve->f1) tob->flag |= TD_SELECTED;
1960 VECCOPY(vec, E_VEC(eve));
1961 Mat3MulVecfl(mtx, vec);
1962 tob->dist= VecLength(vec);
1965 tob->flag |= TD_NOTCONNECTED;
1966 tob->dist = MAXFLOAT;
1971 if(defmats || (quats && eve->tmp.p)) {
1972 float mat[3][3], imat[3][3], qmat[3][3];
1974 /* use both or either quat and defmat correction */
1975 if(quats && eve->tmp.f) {
1976 QuatToMat3(eve->tmp.p, qmat);
1979 Mat3MulSerie(mat, mtx, qmat, defmats[a],
1980 NULL, NULL, NULL, NULL, NULL);
1982 Mat3MulMat3(mat, mtx, qmat);
1985 Mat3MulMat3(mat, mtx, defmats[a]);
1989 Mat3CpyMat3(tob->smtx, imat);
1990 Mat3CpyMat3(tob->mtx, mat);
1993 Mat3CpyMat3(tob->smtx, smtx);
1994 Mat3CpyMat3(tob->mtx, mtx);
1998 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1999 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
2000 if(vmir!=eve) tob->tdmir= vmir;
2010 /* crazy space free */
2017 /* ********************* UV ****************** */
2019 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2023 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2025 /* uv coords are scaled by aspects. this is needed for rotations and
2026 proportional editing to be consistent with the stretchted uv coords
2027 that are displayed. this also means that for display and numinput,
2028 and when the the uv coords are flushed, these are converted each time */
2029 td2d->loc[0] = uv[0]*aspx;
2030 td2d->loc[1] = uv[1]*aspy;
2031 td2d->loc[2] = 0.0f;
2035 td->loc = td2d->loc;
2036 VECCOPY(td->center, td->loc);
2037 VECCOPY(td->iloc, td->loc);
2039 memset(td->axismtx, 0, sizeof(td->axismtx));
2040 td->axismtx[2][2] = 1.0f;
2042 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2045 td->flag |= TD_SELECTED;
2055 static void createTransUVs(TransInfo *t)
2057 TransData *td = NULL;
2058 TransData2D *td2d = NULL;
2060 int count=0, countsel=0;
2061 int propmode = t->flag & T_PROP_EDIT;
2063 EditMesh *em = G.editMesh;
2066 if(is_uv_tface_editing_allowed()==0) return;
2069 for (efa= em->faces.first; efa; efa= efa->next) {
2070 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2071 if (simaFaceDraw_Check(efa, tf)) {
2072 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2073 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2074 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2075 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2077 count += (efa->v4)? 4: 3;
2081 /* note: in prop mode we need at least 1 selected */
2082 if (countsel==0) return;
2084 t->total= (propmode)? count: countsel;
2085 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2086 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2087 treated just as if they were 3d verts */
2088 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2090 if(G.sima->flag & SI_CLIP_UV)
2091 t->flag |= T_CLIP_UV;
2095 for (efa= em->faces.first; efa; efa= efa->next) {
2096 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2097 if (simaFaceDraw_Check(efa, tf)) {
2098 if(propmode || simaUVSel_Check(efa, tf, 0))
2099 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2100 if(propmode || simaUVSel_Check(efa, tf, 1))
2101 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2102 if(propmode || simaUVSel_Check(efa, tf, 2))
2103 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2105 if(efa->v4 && (propmode || simaUVSel_Check(efa, tf, 3)))
2106 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2110 if (G.sima->flag & SI_LIVE_UNWRAP)
2111 unwrap_lscm_live_begin();
2114 void flushTransUVs(TransInfo *t)
2117 int a, width, height;
2119 EditMesh *em = G.editMesh;
2120 float aspx, aspy, invx, invy;
2122 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2123 transform_width_height_tface_uv(&width, &height);
2127 /* flush to 2d vector from internally used 3d vector */
2128 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2129 td->loc2d[0]= td->loc[0]*invx;
2130 td->loc2d[1]= td->loc[1]*invy;
2132 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2133 td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
2134 td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
2138 /* always call this, also for cancel (it transforms non-selected vertices...) */
2139 if((G.sima->flag & SI_BE_SQUARE))
2140 be_square_tface_uv(em);
2142 /* this is overkill if G.sima->lock is not set, but still needed */
2143 object_uvs_changed(ob);
2146 int clipUVTransform(TransInfo *t, float *vec, int resize)
2149 int a, clipx=1, clipy=1;
2150 float aspx, aspy, min[2], max[2];
2152 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2153 min[0]= min[1]= 0.0f;
2154 max[0]= aspx; max[1]= aspy;
2156 for(a=0, td= t->data; a<t->total; a++, td++) {
2157 DO_MINMAX2(td->loc, min, max);
2161 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2162 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2163 else if(max[0] > aspx && t->center[0] < aspx)
2164 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2168 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2169 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2170 else if(max[1] > aspy && t->center[1] < aspy)
2171 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2178 else if(max[0] > aspx)
2179 vec[0] -= max[0]-aspx;
2185 else if(max[1] > aspy)
2186 vec[1] -= max[1]-aspy;
2191 return (clipx || clipy);
2194 /* ********************* IPO EDITOR ************************* */
2196 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2197 * due to bad globals that would need to be imported specially for this
2199 static void createTransIpoData(TransInfo *t)
2201 /* in editipo.c due to some globals that are defined in that file... */
2202 make_ipo_transdata(t);
2205 /* this function is called on recalcData to apply the transforms applied
2206 * to the transdata on to the actual keyframe data
2208 void flushTransIpoData(TransInfo *t)
2213 /* flush to 2d vector from internally used 3d vector */
2214 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2215 /* we need to unapply the nla-scaling from the time in some situations */
2217 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2219 td->loc2d[0]= td->loc[0];
2221 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2222 if ((t->data[a].flag & TD_TIMEONLY)==0)
2223 td->loc2d[1]= td->loc[1];
2227 /* ********************* ACTION/NLA EDITOR ****************** */
2229 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
2230 static short FrameOnMouseSide(char side, float frame, float cframe)
2232 /* both sides, so it doesn't matter */
2233 if (side == 'B') return 1;
2235 /* only on the named side */
2237 return (frame >= cframe) ? 1 : 0;
2239 return (frame <= cframe) ? 1 : 0;
2242 /* fully select selected beztriples, but only include if it's on the right side of cfra */
2243 static int count_ipo_keys(Ipo *ipo, char side, float cfra)
2252 /* only include points that occur on the right side of cfra */
2253 for (icu= ipo->curve.first; icu; icu= icu->next) {
2254 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
2256 /* fully select the other two keys */
2260 /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
2261 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
2270 /* This function assigns the information to transdata */
2271 static void TimeToTransData(TransData *td, float *time, Object *ob)
2273 /* memory is calloc'ed, so that should zero everything nicely for us */
2277 /* store the Object where this keyframe exists as a keyframe of the
2278 * active action as td->ob. Usually, this member is only used for constraints
2284 /* This function advances the address to which td points to, so it must return
2285 * the new address so that the next time new transform data is added, it doesn't
2286 * overwrite the existing ones... i.e. td = IpoToTransData(td, ipo, ob, side, cfra);
2288 * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
2289 * on the named side are used.
2291 static TransData *IpoToTransData(TransData *td, Ipo *ipo, Object *ob, char side, float cfra)
2300 for (icu= ipo->curve.first; icu; icu= icu->next) {
2301 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
2302 /* only add selected keyframes (for now, proportional edit is not enabled) */
2303 if (BEZSELECTED(bezt)) {
2304 /* only add if on the right 'side' of the current frame */
2305 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
2306 /* each control point needs to be added separetely */
2307 TimeToTransData(td, bezt->vec[0], ob);
2310 TimeToTransData(td, bezt->vec[1], ob);
2313 TimeToTransData(td, bezt->vec[2], ob);
2323 static void createTransActionData(TransInfo *t)
2325 TransData *td = NULL;
2328 ListBase act_data = {NULL, NULL};
2338 /* determine what type of data we are operating on */
2339 data = get_action_context(&datatype);
2340 if (data == NULL) return;
2343 filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
2344 actdata_filter(&act_data, filter, data, datatype);
2346 /* is the action scaled? if so, the it should belong to the active object */
2347 if (NLA_ACTION_SCALED)
2350 /* which side of the current frame should be allowed */
2351 if (t->mode == TFM_TIME_EXTEND) {
2352 /* only side on which mouse is gets transformed */
2353 float xmouse, ymouse;
2355 areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
2356 side = (xmouse > CFRA) ? 'R' : 'L';
2359 /* normal transform - both sides of current frame are considered */
2363 /* convert current-frame to action-time (slightly less accurate, espcially under
2364 * higher scaling ratios, but is faster than converting all points)
2367 cfra = get_action_frame(ob, CFRA);
2371 /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
2372 for (ale= act_data.first; ale; ale= ale->next)
2373 count += count_ipo_keys(ale->key_data, side, cfra);
2375 /* stop if trying to build list if nothing selected */
2377 /* cleanup temp list */
2378 BLI_freelistN(&act_data);
2382 /* allocate memory for data */
2384 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
2385 if (t->mode == TFM_TIME_SLIDE)
2386 t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
2389 /* loop 2: build transdata array */
2390 for (ale= act_data.first; ale; ale= ale->next) {
2391 Ipo *ipo= (Ipo *)ale->key_data;
2393 td= IpoToTransData(td, ipo, ob, side, cfra);
2396 /* check if we're supposed to be setting minx/maxx for TimeSlide */
2397 if (t->mode == TFM_TIME_SLIDE) {
2398 float min = 0, max = 0;
2402 for (i=1; i < count; i+=3, td+=3) {
2403 if (min > *(td->val)) min= *(td->val);
2404 if (max < *(td->val)) max= *(td->val);
2407 /* minx/maxx values used by TimeSlide are stored as a
2408 * calloced 2-float array in t->customData. This gets freed
2409 * in postTrans (T_FREE_CUSTOMDATA).
2411 *((float *)(t->customData)) = min;
2412 *((float *)(t->customData) + 1) = max;
2415 /* cleanup temp list */
2416 BLI_freelistN(&act_data);
2419 static void createTransNlaData(TransInfo *t)
2422 bActionStrip *strip;
2423 bActionChannel *achan;
2424 bConstraintChannel *conchan;
2426 TransData *td = NULL;
2431 /* which side of the current frame should be allowed */
2432 if (t->mode == TFM_TIME_EXTEND) {
2433 /* only side on which mouse is gets transformed */
2434 float xmouse, ymouse;
2436 areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
2437 side = (xmouse > CFRA) ? 'R' : 'L';
2440 /* normal transform - both sides of current frame are considered */
2444 /* Ensure that partial selections result in beztriple selections */
2445 for (base=G.scene->base.first; base; base=base->next) {
2446 /* Check object ipos */
2447 i= count_ipo_keys(base->object->ipo, side, CFRA);
2448 if (i) base->flag |= BA_HAS_RECALC_OB;
2451 /* Check object constraint ipos */
2452 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2453 count += count_ipo_keys(conchan->ipo, side, CFRA);
2455 /* skip actions and nlastrips if object is collapsed */
2456 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2459 /* Check action ipos */
2460 if (base->object->action) {
2461 /* exclude if strip is selected too */
2462 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2463 if (strip->flag & ACTSTRIP_SELECT)
2464 if (strip->act == base->object->action)
2468 cfra = get_action_frame(base->object, CFRA);
2470 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2471 if (EDITABLE_ACHAN(achan)) {
2472 i= count_ipo_keys(achan->ipo, side, cfra);
2473 if (i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2476 /* Check action constraint ipos */
2477 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2478 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2479 if (EDITABLE_CONCHAN(conchan))
2480 count += count_ipo_keys(conchan->ipo, side, cfra);
2488 /* Check nlastrips */
2489 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2490 if (strip->flag & ACTSTRIP_SELECT) {
2491 base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2493 if (FrameOnMouseSide(side, strip->start, CFRA)) count++;
2494 if (FrameOnMouseSide(side, strip->end, CFRA)) count++;
2499 /* If nothing is selected, bail out */
2503 /* allocate memory for data */
2505 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (NLA Editor)");
2507 /* build the transdata structure */
2509 for (base=G.scene->base.first; base; base=base->next) {
2510 /* Manipulate object ipos */
2511 /* - no scaling of keyframe times is allowed here */
2512 td= IpoToTransData(td, base->object->ipo, NULL, side, CFRA);
2514 /* Manipulate object constraint ipos */
2515 /* - no scaling of keyframe times is allowed here */
2516 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2517 td= IpoToTransData(td, conchan->ipo, NULL, side, CFRA);
2519 /* skip actions and nlastrips if object collapsed */
2520 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2523 /* Manipulate action ipos */
2524 if (base->object->action) {
2525 /* exclude if strip that active action belongs to is selected too */
2526 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2527 if (strip->flag & ACTSTRIP_SELECT)
2528 if (strip->act == base->object->action)
2532 /* can include if no strip found */
2534 cfra = get_action_frame(base->object, CFRA);
2536 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2537 if (EDITABLE_ACHAN(achan)) {
2538 td= IpoToTransData(td, achan->ipo, base->object, side, cfra);
2540 /* Manipulate action constraint ipos */
2541 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2542 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2543 if (EDITABLE_CONCHAN(conchan))
2544 td= IpoToTransData(td, conchan->ipo, base->object, side, cfra);
2552 /* Manipulate nlastrips */
2553 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2554 if (strip->flag & ACTSTRIP_SELECT) {
2555 /* first TransData is the start, second is the end */
2556 if (FrameOnMouseSide(side, strip->start, CFRA)) {
2557 td->val = &strip->start;
2558 td->ival = strip->start;
2561 if (FrameOnMouseSide(side, strip->end, CFRA)) {
2562 td->val = &strip->end;
2563 td->ival = strip->end;
2571 /* **************** IpoKey stuff, for Object TransData ********** */
2573 /* storage of bezier triple. thats why -3 and +3! */
2574 static void set_tdi_old(float *old, float *poin)
2581 /* while transforming */
2582 void add_tdi_poin(float *poin, float *old, float delta)
2585 poin[0]= old[0]+delta;
2586 poin[-3]= old[3]+delta;
2587 poin[3]= old[6]+delta;
2591 /* fill ipokey transdata with old vals and pointers */
2592 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
2594 extern int ob_ar[]; // blenkernel ipo.c
2595 TransDataIpokey *tdi= td->tdi;
2599 td->val= NULL; // is read on ESC
2601 for(a=0; a<OB_TOTIPO; a++) {
2605 switch( ob_ar[a] ) {
2608 tdi->locx= &(bezt->vec[1][1]); break;
2611 tdi->locy= &(bezt->vec[1][1]); break;
2614 tdi->locz= &(bezt->vec[1][1]); break;
2619 tdi->rotx= &(bezt->vec[1][1]); break;
2623 tdi->roty= &(bezt->vec[1][1]); break;
2627 tdi->rotz= &(bezt->vec[1][1]); break;
2631 tdi->sizex= &(bezt->vec[1][1]); break;
2634 tdi->sizey= &(bezt->vec[1][1]); break;
2637 tdi->sizez= &(bezt->vec[1][1]); break;
2642 /* oldvals for e.g. undo */
2643 if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
2644 if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
2645 if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
2647 /* remember, for mapping curves ('1'=10 degrees) */
2648 if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
2649 if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
2650 if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
2652 /* this is not allowed to be dsize! */
2653 if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
2654 if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
2655 if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
2658 if(delta) tdi->flag |= TOB_IPODROT;
2662 /* *************************** Object Transform data ******************* */
2664 /* Little helper function for ObjectToTransData used to give certain
2665 * constraints (ChildOf, FollowPath, and others that may be added)
2666 * inverse corrections for transform, so that they aren't in CrazySpace.
2667 * These particular constraints benefit from this, but others don't, hence
2668 * this semi-hack ;-) - Aligorith
2670 static short constraints_list_needinv(TransInfo *t, ListBase *list)
2674 /* loop through constraints, checking if there's one of the mentioned
2675 * constraints needing special crazyspace corrections
2678 for (con= list->first; con; con=con->next) {
2679 /* only consider constraint if it is enabled, and has influence on result */
2680 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) {
2681 /* (affirmative) returns for specific constraints here... */
2682 /* constraints that require this regardless */
2683 if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
2684 if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
2685 if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
2687 /* constraints that require this only under special conditions */
2688 if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
2689 /* CopyRot constraint only does this when rotating, and offset is on */
2690 bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
2692 if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
2699 /* no appropriate candidates found */
2703 /* transcribe given object into TransData for Transforming */
2704 static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
2707 ListBase fakecons = {NULL, NULL};
2711 /* axismtx has the real orientation */
2712 Mat3CpyMat4(td->axismtx, ob->obmat);
2713 Mat3Ortho(td->axismtx);
2715 /* hack: tempolarily disable tracking and/or constraints when getting
2716 * object matrix, if tracking is on, or if constraints don't need
2717 * inverse correction to stop it from screwing up space conversion
2720 constinv= constraints_list_needinv(t, &ob->constraints);
2721 if (ob->track || constinv==0) {
2725 if (constinv == 0) {
2726 fakecons.first = ob->constraints.first;
2727 fakecons.last = ob->constraints.last;
2728 ob->constraints.first = ob->constraints.last = NULL;
2731 where_is_object(ob);
2733 if (constinv == 0) {
2734 ob->constraints.first = fakecons.first;
2735 ob->constraints.last = fakecons.last;
2741 where_is_object(ob);
2746 VECCOPY(td->iloc, td->loc);
2748 td->ext->rot = ob->rot;
2749 VECCOPY(td->ext->irot, ob->rot);
2750 VECCOPY(td->ext->drot, ob->drot);
2752 td->ext->size = ob->size;
2753 VECCOPY(td->ext->isize, ob->size);
2754 VECCOPY(td->ext->dsize, ob->dsize);
2756 VECCOPY(td->center, ob->obmat[3]);
2758 /* is there a need to set the global<->data space conversion matrices? */
2759 if (ob->parent || constinv) {
2760 float totmat[3][3], obinv[3][3];
2762 /* Get the effect of parenting, and/or certain constraints.
2763 * NOTE: some Constraints, and also Tracking should never get this
2764 * done, as it doesn't work well.
2766 object_to_mat3(ob, obmtx);
2767 Mat3CpyMat4(totmat, ob->obmat);
2768 Mat3Inv(obinv, totmat);
2769 Mat3MulMat3(td->smtx, obmtx, obinv);
2770 Mat3Inv(td->mtx, td->smtx);
2773 /* no conversion to/from dataspace */
2779 td->verse = (void*)ob;
2780 td->flag |= TD_VERSE_OBJECT;
2783 td->flag &= ~TD_VERSE_OBJECT;
2788 /* sets flags in Bases to define whether they take part in transform */
2789 /* it deselects Bases, so we have to call the clear function always after */
2790 static void set_trans_object_base_flags(TransInfo *t)
2793 if Base selected and has parent selected:
2794 base->flag= BA_WAS_SEL
2798 /* makes sure base flags and object flags are identical */
2801 /* handle pending update events, otherwise they got copied below */
2802 for (base= FIRSTBASE; base; base= base->next) {
2803 if(base->object->recalc)
2804 object_handle_update(base->object);
2807 for (base= FIRSTBASE; base; base= base->next) {
2808 base->flag &= ~BA_WAS_SEL;
2810 if(TESTBASELIB(base)) {
2811 Object *ob= base->object;
2812 Object *parsel= ob->parent;
2814 /* if parent selected, deselect */
2816 if(parsel->flag & SELECT) break;
2817 parsel= parsel->parent;
2821 base->flag &= ~SELECT;
2822 base->flag |= BA_WAS_SEL;
2824 /* used for flush, depgraph will change recalcs if needed :) */
2825 ob->recalc |= OB_RECALC_OB;
2828 /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
2829 DAG_scene_flush_update(G.scene, -1);
2831 /* and we store them temporal in base (only used for transform code) */
2832 /* this because after doing updates, the object->recalc is cleared */
2833 for (base= FIRSTBASE; base; base= base->next) {
2834 if(base->object->recalc & OB_RECALC_OB)
2835 base->flag |= BA_HAS_RECALC_OB;
2836 if(base->object->recalc & OB_RECALC_DATA)
2837 base->flag |= BA_HAS_RECALC_DATA;
2841 static void clear_trans_object_base_flags(void)
2847 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2848 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2854 /* auto-keyframing feature - for objects
2855 * tmode: should be a transform mode
2857 void autokeyframe_ob_cb_func(Object *ob, int tmode)
2862 if (G.flags & G_RECORDKEYS) {