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);
621 /* store reference to first constraint */
622 td->con= pchan->constraints.first;
625 static void bone_children_clear_transflag(ListBase *lb)
627 Bone *bone= lb->first;
629 for(;bone;bone= bone->next) {
630 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
631 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
633 bone->flag &= ~BONE_TRANSFORM;
635 bone_children_clear_transflag(&bone->childbase);
639 /* sets transform flags in the bones, returns total */
640 static void set_pose_transflags(TransInfo *t, Object *ob)
642 bArmature *arm= ob->data;
649 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
651 if(bone->layer & arm->layer) {
652 if(bone->flag & BONE_SELECTED)
653 bone->flag |= BONE_TRANSFORM;
655 bone->flag &= ~BONE_TRANSFORM;
657 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
661 /* make sure no bone can be transformed when a parent is transformed */
662 /* since pchans are depsgraph sorted, the parents are in beginning of list */
663 if(t->mode!=TFM_BONESIZE) {
664 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
666 if(bone->flag & BONE_TRANSFORM)
667 bone_children_clear_transflag(&bone->childbase);
670 /* now count, and check if we have autoIK or have to switch from translate to rotate */
673 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
675 if(bone->flag & BONE_TRANSFORM) {
679 if(t->mode==TFM_TRANSLATION) {
680 if( has_targetless_ik(pchan)==NULL ) {
681 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
682 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
685 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
694 /* if there are no translatable bones, do rotation */
695 if(t->mode==TFM_TRANSLATION && !hastranslation)
696 t->mode= TFM_ROTATION;
700 /* -------- Auto-IK ---------- */
702 /* adjust pose-channel's auto-ik chainlen */
703 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
707 /* don't bother to search if no valid constraints */
708 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
711 /* check if pchan has ik-constraint */
712 for (con= pchan->constraints.first; con; con= con->next) {
713 if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
714 bKinematicConstraint *data= con->data;
716 /* only accept if a temporary one (for auto-ik) */
717 if (data->flag & CONSTRAINT_IK_TEMP) {
718 /* chainlen is new chainlen, but is limited by maximum chainlen */
719 if ((chainlen==0) || (chainlen > data->max_rootbone))
720 data->rootbone= data->max_rootbone;
722 data->rootbone= chainlen;
728 /* change the chain-length of auto-ik */
729 void transform_autoik_update (TransInfo *t, short mode)
731 short *chainlen= &G.scene->toolsettings->autoik_chainlen;
734 /* mode determines what change to apply to chainlen */
736 /* mode=1 is from WHEELMOUSEDOWN... increases len */
739 else if (mode == -1) {
740 /* mode==-1 is from WHEELMOUSEUP... decreases len */
741 if (*chainlen > 0) (*chainlen)--;
744 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
745 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
748 /* apply to all pose-channels */
749 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
750 pchan_autoik_adjust(pchan, *chainlen);
754 /* frees temporal IKs */
755 static void pose_grab_with_ik_clear(Object *ob)
757 bKinematicConstraint *data;
761 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
762 /* clear all temporary lock flags */
763 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
765 /* remove all temporary IK-constraints added */
766 for (con= pchan->constraints.first; con; con= con->next) {
767 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
769 if (data->flag & CONSTRAINT_IK_TEMP) {
770 BLI_remlink(&pchan->constraints, con);
771 MEM_freeN(con->data);
773 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
781 /* adds the IK to pchan - returns if added */
782 static short pose_grab_with_ik_add(bPoseChannel *pchan)
784 bKinematicConstraint *data;
791 /* rule: not if there's already an IK on this channel */
792 for (con= pchan->constraints.first; con; con= con->next)
793 if (con->type==CONSTRAINT_TYPE_KINEMATIC)
797 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
798 data= has_targetless_ik(pchan);
800 data->flag |= CONSTRAINT_IK_AUTO;
804 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
805 BLI_addtail(&pchan->constraints, con);
806 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
808 data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
809 VECCOPY(data->grabtarget, pchan->pose_tail);
812 /* we include only a connected chain */
813 while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
814 /* here, we set ik-settings for bone from pchan->protectflag */
815 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
816 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
817 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
819 /* now we count this pchan as being included */
821 pchan= pchan->parent;
824 /* make a copy of maximum chain-length */
825 data->max_rootbone= data->rootbone;
830 /* bone is a canditate to get IK, but we don't do it if it has children connected */
831 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
834 short wentdeeper=0, added=0;
836 /* go deeper if children & children are connected */
837 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
838 if (bonec->flag & BONE_CONNECTED) {
840 added+= pose_grab_with_ik_children(pose, bonec);
844 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
846 added+= pose_grab_with_ik_add(pchan);
852 /* main call which adds temporal IK chains */
853 static short pose_grab_with_ik(Object *ob)
856 bPoseChannel *pchan, *pchansel= NULL;
859 if (ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0)
864 /* rule: only one Bone */
865 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
866 if (pchan->bone->layer & arm->layer) {
867 if (pchan->bone->flag & BONE_SELECTED) {
874 if (pchan || pchansel==NULL) return 0;
876 /* rule: no IK for solitary (unconnected) bone */
877 for (bonec=pchansel->bone->childbase.first; bonec; bonec=bonec->next) {
878 if (bonec->flag & BONE_CONNECTED) {
882 if ((pchansel->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) return 0;
884 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
885 if (pchansel->parent) {
886 /* only adds if there's no IK yet */
887 return pose_grab_with_ik_add(pchansel);
890 /* rule: go over the children and add IK to the tips */
891 return pose_grab_with_ik_children(ob->pose, pchansel->bone);
896 /* only called with pose mode active object now */
897 static void createTransPose(TransInfo *t, Object *ob)
902 TransDataExtension *tdx;
908 /* check validity of state */
909 arm=get_armature (ob);
910 if (arm==NULL || ob->pose==NULL) return;
912 if (arm->flag & ARM_RESTPOS) {
913 if(t->mode!=TFM_BONESIZE) {
914 notice ("Pose edit not possible while Rest Position is enabled");
918 if (!(ob->lay & G.vd->lay)) return;
920 /* do we need to add temporal IK chains? */
921 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
922 ik_on= pose_grab_with_ik(ob);
923 if (ik_on) t->flag |= T_AUTOIK;
926 /* set flags and count total (warning, can change transform to rotate) */
927 set_pose_transflags(t, ob);
929 if(t->total==0) return;
932 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
934 /* make sure the lock is set OK, unlock can be accidentally saved? */
935 ob->pose->flag |= POSE_LOCKED;
936 ob->pose->flag &= ~POSE_DO_UNLOCK;
938 /* init trans data */
939 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
940 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
941 for(i=0; i<t->total; i++, td++, tdx++) {
947 /* use pose channels to fill trans data */
949 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
950 if(pchan->bone->flag & BONE_TRANSFORM) {
951 add_pose_transdata(t, pchan, ob, td);
956 if(td != (t->data+t->total)) printf("Bone selection count error\n");
958 /* initialise initial auto=ik chainlen's? */
959 if (ik_on) transform_autoik_update(t, 0);
962 /* ********************* armature ************** */
964 static void createTransArmatureVerts(TransInfo *t)
967 bArmature *arm= G.obedit->data;
969 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
972 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
973 if(ebo->layer & arm->layer) {
974 if (t->mode==TFM_BONESIZE) {
975 if (ebo->flag & BONE_SELECTED)
978 else if (t->mode==TFM_BONE_ROLL) {
979 if (ebo->flag & BONE_SELECTED)
983 if (ebo->flag & BONE_TIPSEL)
985 if (ebo->flag & BONE_ROOTSEL)
991 if (!t->total) return;
993 Mat3CpyMat4(mtx, G.obedit->obmat);
996 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
998 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
999 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1001 if(ebo->layer & arm->layer) {
1002 if (t->mode==TFM_BONE_ENVELOPE) {
1004 if (ebo->flag & BONE_ROOTSEL){
1005 td->val= &ebo->rad_head;
1008 VECCOPY (td->center, ebo->head);
1009 td->flag= TD_SELECTED;
1011 Mat3CpyMat3(td->smtx, smtx);
1012 Mat3CpyMat3(td->mtx, mtx);
1020 if (ebo->flag & BONE_TIPSEL){
1021 td->val= &ebo->rad_tail;
1023 VECCOPY (td->center, ebo->tail);
1024 td->flag= TD_SELECTED;
1026 Mat3CpyMat3(td->smtx, smtx);
1027 Mat3CpyMat3(td->mtx, mtx);
1037 else if (t->mode==TFM_BONESIZE) {
1038 if (ebo->flag & BONE_SELECTED) {
1039 if(arm->drawtype==ARM_ENVELOPE) {
1041 td->val= &ebo->dist;
1042 td->ival= ebo->dist;
1045 // abusive storage of scale in the loc pointer :)
1046 td->loc= &ebo->xwidth;
1047 VECCOPY (td->iloc, td->loc);
1050 VECCOPY (td->center, ebo->head);
1051 td->flag= TD_SELECTED;
1053 /* use local bone matrix */
1054 VecSubf(delta, ebo->tail, ebo->head);
1055 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1056 Mat3MulMat3(td->mtx, mtx, bonemat);
1057 Mat3Inv(td->smtx, td->mtx);
1059 Mat3CpyMat3(td->axismtx, td->mtx);
1060 Mat3Ortho(td->axismtx);
1068 else if (t->mode==TFM_BONE_ROLL) {
1069 if (ebo->flag & BONE_SELECTED) {
1071 td->val= &(ebo->roll);
1072 td->ival= ebo->roll;
1074 VECCOPY (td->center, ebo->head);
1075 td->flag= TD_SELECTED;
1084 if (ebo->flag & BONE_TIPSEL){
1085 VECCOPY (td->iloc, ebo->tail);
1086 VECCOPY (td->center, td->iloc);
1088 td->flag= TD_SELECTED;
1090 Mat3CpyMat3(td->smtx, smtx);
1091 Mat3CpyMat3(td->mtx, mtx);
1099 if (ebo->flag & BONE_ROOTSEL){
1100 VECCOPY (td->iloc, ebo->head);
1101 VECCOPY (td->center, td->iloc);
1103 td->flag= TD_SELECTED;
1105 Mat3CpyMat3(td->smtx, smtx);
1106 Mat3CpyMat3(td->mtx, mtx);
1119 /* ********************* meta elements ********* */
1121 static void createTransMBallVerts(TransInfo *t)
1125 TransDataExtension *tx;
1126 float mtx[3][3], smtx[3][3];
1127 int count=0, countsel=0;
1128 int propmode = t->flag & T_PROP_EDIT;
1131 for(ml= editelems.first; ml; ml= ml->next) {
1132 if(ml->flag & SELECT) countsel++;
1133 if(propmode) count++;
1136 /* note: in prop mode we need at least 1 selected */
1137 if (countsel==0) return;
1139 if(propmode) t->total = count;
1140 else t->total = countsel;
1142 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1143 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1145 Mat3CpyMat4(mtx, G.obedit->obmat);
1148 for(ml= editelems.first; ml; ml= ml->next) {
1149 if(propmode || (ml->flag & SELECT)) {
1151 VECCOPY(td->iloc, td->loc);
1152 VECCOPY(td->center, td->loc);
1154 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1155 else td->flag= TD_USEQUAT;
1157 Mat3CpyMat3(td->smtx, smtx);
1158 Mat3CpyMat3(td->mtx, mtx);
1163 /* Radius of MetaElem (mass of MetaElem influence) */
1164 if(ml->flag & MB_SCALE_RAD){
1173 /* expx/expy/expz determine "shape" of some MetaElem types */
1174 tx->size = &ml->expx;
1175 tx->isize[0] = ml->expx;
1176 tx->isize[1] = ml->expy;
1177 tx->isize[2] = ml->expz;
1179 /* quat is used for rotation of MetaElem */
1180 tx->quat = ml->quat;
1181 QUATCOPY(tx->iquat, ml->quat);
1191 /* ********************* curve/surface ********* */
1193 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1194 TransData *td, *td_near = NULL;
1195 for (td = head; td<=tail; td++) {
1196 if (td->flag & TD_SELECTED) {
1202 dist = VecLenf(td_near->center, td->center);
1203 if (dist < (td-1)->dist) {
1204 td->dist = (td-1)->dist;
1211 td->dist = MAXFLOAT;
1212 td->flag |= TD_NOTCONNECTED;
1216 for (td = tail; td>=head; td--) {
1217 if (td->flag & TD_SELECTED) {
1223 dist = VecLenf(td_near->center, td->center);
1224 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1225 td->flag &= ~TD_NOTCONNECTED;
1226 if (dist < (td+1)->dist) {
1227 td->dist = (td+1)->dist;
1237 static void createTransCurveVerts(TransInfo *t)
1239 TransData *td = NULL;
1243 float mtx[3][3], smtx[3][3];
1245 int count=0, countsel=0;
1246 int propmode = t->flag & T_PROP_EDIT;
1248 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1249 for(nu= editNurb.first; nu; nu= nu->next) {
1250 if((nu->type & 7)==CU_BEZIER) {
1251 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1253 if (G.f & G_HIDDENHANDLES) {
1254 if(bezt->f2 & SELECT) countsel+=3;
1255 if(propmode) count+= 3;
1257 if(bezt->f1 & SELECT) countsel++;
1258 if(bezt->f2 & SELECT) countsel++;
1259 if(bezt->f3 & SELECT) countsel++;
1260 if(propmode) count+= 3;
1266 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1268 if(propmode) count++;
1269 if(bp->f1 & SELECT) countsel++;
1274 /* note: in prop mode we need at least 1 selected */
1275 if (countsel==0) return;
1277 if(propmode) t->total = count;
1278 else t->total = countsel;
1279 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1281 Mat3CpyMat4(mtx, G.obedit->obmat);
1285 for(nu= editNurb.first; nu; nu= nu->next) {
1286 if((nu->type & 7)==CU_BEZIER) {
1287 TransData *head, *tail;
1289 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1293 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1294 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1296 VECCOPY(td->iloc, bezt->vec[0]);
1297 td->loc= bezt->vec[0];
1298 VECCOPY(td->center, bezt->vec[1]);
1299 if (G.f & G_HIDDENHANDLES) {
1300 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1303 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1310 Mat3CpyMat3(td->smtx, smtx);
1311 Mat3CpyMat3(td->mtx, mtx);
1318 /* This is the Curve Point, the other two are handles */
1319 if(propmode || (bezt->f2 & SELECT)) {
1320 VECCOPY(td->iloc, bezt->vec[1]);
1321 td->loc= bezt->vec[1];
1322 VECCOPY(td->center, td->loc);
1323 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1328 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1329 td->val = &(bezt->radius);
1330 td->ival = bezt->radius;
1331 } else if (t->mode==TFM_TILT) {
1332 td->val = &(bezt->alfa);
1333 td->ival = bezt->alfa;
1338 Mat3CpyMat3(td->smtx, smtx);
1339 Mat3CpyMat3(td->mtx, mtx);
1346 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1347 ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1349 VECCOPY(td->iloc, bezt->vec[2]);
1350 td->loc= bezt->vec[2];
1351 VECCOPY(td->center, bezt->vec[1]);
1352 if (G.f & G_HIDDENHANDLES) {
1353 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1356 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1363 Mat3CpyMat3(td->smtx, smtx);
1364 Mat3CpyMat3(td->mtx, mtx);
1371 else if (propmode && head != tail) {
1372 calc_distanceCurveVerts(head, tail-1);
1376 if (propmode && head != tail)
1377 calc_distanceCurveVerts(head, tail-1);
1380 TransData *head, *tail;
1382 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1384 if(propmode || (bp->f1 & SELECT)) {
1385 VECCOPY(td->iloc, bp->vec);
1387 VECCOPY(td->center, td->loc);
1388 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1393 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1394 td->val = &(bp->radius);
1395 td->ival = bp->radius;
1397 td->val = &(bp->alfa);
1398 td->ival = bp->alfa;
1401 Mat3CpyMat3(td->smtx, smtx);
1402 Mat3CpyMat3(td->mtx, mtx);
1409 else if (propmode && head != tail) {
1410 calc_distanceCurveVerts(head, tail-1);
1414 if (propmode && head != tail)
1415 calc_distanceCurveVerts(head, tail-1);
1420 /* ********************* lattice *************** */
1422 static void createTransLatticeVerts(TransInfo *t)
1424 TransData *td = NULL;
1426 float mtx[3][3], smtx[3][3];
1428 int count=0, countsel=0;
1429 int propmode = t->flag & T_PROP_EDIT;
1432 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1435 if(bp->f1 & SELECT) countsel++;
1436 if(propmode) count++;
1441 /* note: in prop mode we need at least 1 selected */
1442 if (countsel==0) return;
1444 if(propmode) t->total = count;
1445 else t->total = countsel;
1446 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1448 Mat3CpyMat4(mtx, G.obedit->obmat);
1453 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1455 if(propmode || (bp->f1 & SELECT)) {
1457 VECCOPY(td->iloc, bp->vec);
1459 VECCOPY(td->center, td->loc);
1460 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1462 Mat3CpyMat3(td->smtx, smtx);
1463 Mat3CpyMat3(td->mtx, mtx);
1477 /* ******************* particle edit **************** */
1478 static void createTransParticleVerts(TransInfo *t)
1480 TransData *td = NULL;
1481 TransDataExtension *tx;
1482 Base *base = BASACT;
1484 ParticleSystem *psys = PE_get_current(ob);
1485 ParticleSystemModifierData *psmd = NULL;
1486 ParticleEditSettings *pset = PE_settings();
1487 ParticleData *pa = NULL;
1489 ParticleEditKey *key;
1491 int i,k, totpart, transformparticle;
1492 int count = 0, hasselected = 0;
1493 int propmode = t->flag & T_PROP_EDIT;
1495 if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1497 psmd = psys_get_modifier(ob,psys);
1500 totpart = psys->totpart;
1501 base->flag |= BA_HAS_RECALC_DATA;
1503 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1504 pa->flag &= ~PARS_TRANSFORM;
1505 transformparticle= 0;
1507 if((pa->flag & PARS_HIDE)==0) {
1508 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1509 if((key->flag&PEK_HIDE)==0) {
1510 if(key->flag&PEK_SELECT) {
1512 transformparticle= 1;
1515 transformparticle= 1;
1520 if(transformparticle) {
1521 count += pa->totkey;
1522 pa->flag |= PARS_TRANSFORM;
1526 /* note: in prop mode we need at least 1 selected */
1527 if (hasselected==0) return;
1530 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1532 if(t->mode == TFM_BAKE_TIME)
1533 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1539 Mat4Invert(ob->imat,ob->obmat);
1541 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1542 TransData *head, *tail;
1545 if(!(pa->flag & PARS_TRANSFORM)) continue;
1547 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1549 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1550 VECCOPY(key->world_co, key->co);
1551 Mat4MulVecfl(mat, key->world_co);
1552 td->loc = key->world_co;
1554 VECCOPY(td->iloc, td->loc);
1555 VECCOPY(td->center, td->loc);
1557 if(key->flag & PEK_SELECT)
1558 td->flag |= TD_SELECTED;
1560 td->flag |= TD_SKIP;
1565 /* don't allow moving roots */
1566 if(k==0 && pset->flag & PE_LOCK_FIRST)
1567 td->protectflag |= OB_LOCK_LOC;
1572 if(t->mode == TFM_BAKE_TIME) {
1573 td->val = key->time;
1574 td->ival = *(key->time);
1575 /* abuse size and quat for min/max values */
1576 td->flag |= TD_NO_EXT;
1577 if(k==0) tx->size = 0;
1578 else tx->size = (key - 1)->time;
1580 if(k == pa->totkey - 1) tx->quat = 0;
1581 else tx->quat = (key + 1)->time;
1589 if (propmode && head != tail)
1590 calc_distanceCurveVerts(head, tail - 1);
1594 void flushTransParticles(TransInfo *t)
1597 ParticleSystem *psys = PE_get_current(ob);
1598 ParticleSystemModifierData *psmd;
1600 ParticleEditKey *key;
1602 float mat[4][4], imat[4][4], co[3];
1603 int i, k, propmode = t->flag & T_PROP_EDIT;
1605 psmd = psys_get_modifier(ob, psys);
1607 /* we do transform in world space, so flush world space position
1608 * back to particle local space */
1610 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1611 if(!(pa->flag & PARS_TRANSFORM)) continue;
1613 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1614 Mat4Invert(imat,mat);
1616 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1617 VECCOPY(co, key->world_co);
1618 Mat4MulVecfl(imat, co);
1620 /* optimization for proportional edit */
1621 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1622 VECCOPY(key->co, co);
1623 pa->flag |= PARS_EDIT_RECALC;
1628 PE_update_object(OBACT, 1);
1631 /* ********************* mesh ****************** */
1633 /* proportional distance based on connectivity */
1634 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1635 #define E_NEAR(a) (nears[((a)->tmp.l)])
1636 #define THRESHOLD 0.0001f
1637 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1639 EditMesh *em = G.editMesh;
1644 /* f2 flag is used for 'selection' */
1645 /* tmp.l is offset on scratch array */
1646 for(eve= em->verts.first; eve; eve= eve->next) {
1650 if(eve->f & SELECT) {
1653 E_VEC(eve)[0] = 0.0f;
1654 E_VEC(eve)[1] = 0.0f;
1655 E_VEC(eve)[2] = 0.0f;
1664 /* Floodfill routine */
1666 At worst this is n*n of complexity where n is number of edges
1667 Best case would be n if the list is ordered perfectly.
1668 Estimate is n log n in average (so not too bad)
1673 for(eed= em->edges.first; eed; eed= eed->next) {
1675 EditVert *v1= eed->v1, *v2= eed->v2;
1676 float *vec2 = E_VEC(v2);
1677 float *vec1 = E_VEC(v1);
1679 if (v1->f2 + v2->f2 == 4)
1685 float len1 = VecLength(vec1);
1686 float len2 = VecLength(vec2);
1688 /* for v2 if not selected */
1690 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1691 lenn = VecLength(nvec);
1693 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1694 VECCOPY(vec2, nvec);
1695 E_NEAR(v2) = E_NEAR(v1);
1699 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1700 VECCOPY(vec2, vec1);
1701 E_NEAR(v2) = E_NEAR(v1);
1705 /* for v1 if not selected */
1707 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1708 lenn = VecLength(nvec);
1710 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1711 VECCOPY(vec1, nvec);
1712 E_NEAR(v1) = E_NEAR(v2);
1716 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1717 VECCOPY(vec1, vec2);
1718 E_NEAR(v1) = E_NEAR(v2);
1725 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1727 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1728 VECCOPY(vec2, vec1);
1730 E_NEAR(v2) = E_NEAR(v1);
1736 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1738 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1739 VECCOPY(vec1, vec2);
1741 E_NEAR(v1) = E_NEAR(v2);
1749 /* loop-in-a-loop I know, but we need it! (ton) */
1750 static void get_face_center(float *cent, EditVert *eve)
1752 EditMesh *em = G.editMesh;
1755 for(efa= em->faces.first; efa; efa= efa->next)
1757 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1760 VECCOPY(cent, efa->cent);
1764 //way to overwrite what data is edited with transform
1765 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1766 static void VertsToTransData(TransData *td, EditVert *eve)
1770 // td->loc = key->co;
1774 VECCOPY(td->center, td->loc);
1775 if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1776 get_face_center(td->center, eve);
1777 VECCOPY(td->iloc, td->loc);
1780 VECCOPY(td->axismtx[2], eve->no);
1786 td->axismtx[1][2] = 0.0f;
1795 td->verse = (void*)eve->vvert;
1796 td->flag |= TD_VERSE_VERT;
1799 td->flag &= ~TD_VERSE_VERT;
1803 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1805 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1807 float *vec = userData;
1813 static int modifiers_disable_subsurf_temporary(Object *ob)
1818 for(md=ob->modifiers.first; md; md=md->next)
1819 if(md->type==eModifierType_Subsurf)
1820 if(md->mode & eModifierMode_OnCage) {
1821 md->mode ^= eModifierMode_DisableTemporary;
1828 /* disable subsurf temporal, get mapped cos, and enable it */
1829 static float *get_crazy_mapped_editverts(void)
1834 /* disable subsurf temporal, get mapped cos, and enable it */
1835 if(modifiers_disable_subsurf_temporary(G.obedit)) {
1836 /* need to make new derivemesh */
1837 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1840 /* now get the cage */
1841 dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1843 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1844 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1848 /* set back the flag, no new cage needs to be built, transform does it */
1849 modifiers_disable_subsurf_temporary(G.obedit);
1854 #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])
1855 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1857 float vecu[3], vecv[3];
1860 TAN_MAKE_VEC(vecu, v1, v2);
1861 TAN_MAKE_VEC(vecv, v1, v3);
1862 triatoquat(v1, vecu, vecv, q1);
1864 TAN_MAKE_VEC(vecu, def1, def2);
1865 TAN_MAKE_VEC(vecv, def1, def3);
1866 triatoquat(def1, vecu, vecv, q2);
1868 QuatSub(quat, q2, q1);
1872 static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
1874 EditMesh *em = G.editMesh;
1875 EditVert *eve, *prev;
1877 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
1880 /* two abused locations in vertices */
1881 for(eve= em->verts.first; eve; eve= eve->next, index++) {
1883 eve->prev= (EditVert *)index;
1886 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1887 for(efa= em->faces.first; efa; efa= efa->next) {
1889 /* retrieve mapped coordinates */
1890 v1= mappedcos + 3*(long)(efa->v1->prev);
1891 v2= mappedcos + 3*(long)(efa->v2->prev);
1892 v3= mappedcos + 3*(long)(efa->v3->prev);
1894 co1= (origcos)? origcos + 3*(long)(efa->v1->prev): efa->v1->co;
1895 co2= (origcos)? origcos + 3*(long)(efa->v2->prev): efa->v2->co;
1896 co3= (origcos)? origcos + 3*(long)(efa->v3->prev): efa->v3->co;
1898 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
1899 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
1900 efa->v2->tmp.p= (void*)quats;
1905 v4= mappedcos + 3*(long)(efa->v4->prev);
1906 co4= (origcos)? origcos + 3*(long)(efa->v4->prev): efa->v4->co;
1908 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1909 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
1910 efa->v1->tmp.p= (void*)quats;
1913 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1914 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
1915 efa->v3->tmp.p= (void*)quats;
1918 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
1919 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
1920 efa->v4->tmp.p= (void*)quats;
1925 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1926 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
1927 efa->v1->tmp.p= (void*)quats;
1930 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1931 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
1932 efa->v3->tmp.p= (void*)quats;
1938 /* restore abused prev pointer */
1939 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1944 static void createTransEditVerts(TransInfo *t)
1946 TransData *tob = NULL;
1947 EditMesh *em = G.editMesh;
1949 EditVert **nears = NULL;
1950 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1951 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
1952 int count=0, countsel=0, a, totleft;
1953 int propmode = t->flag & T_PROP_EDIT;
1956 if ((t->context & CTX_NO_MIRROR) == 0 || (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
1961 // transform now requires awareness for select mode, so we tag the f1 flags in verts
1962 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1963 for(eve= em->verts.first; eve; eve= eve->next) {
1964 if(eve->h==0 && (eve->f & SELECT))
1970 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1972 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1973 for(eed= em->edges.first; eed; eed= eed->next) {
1974 if(eed->h==0 && (eed->f & SELECT))
1975 eed->v1->f1= eed->v2->f1= SELECT;
1980 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1981 for(efa= em->faces.first; efa; efa= efa->next) {
1982 if(efa->h==0 && (efa->f & SELECT)) {
1983 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1984 if(efa->v4) efa->v4->f1= SELECT;
1989 /* now we can count */
1990 for(eve= em->verts.first; eve; eve= eve->next) {
1992 if(eve->f1) countsel++;
1993 if(propmode) count++;
1997 /* note: in prop mode we need at least 1 selected */
1998 if (countsel==0) return;
2003 /* allocating scratch arrays */
2004 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2005 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2007 else t->total = countsel;
2008 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2010 Mat3CpyMat4(mtx, G.obedit->obmat);
2013 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
2015 /* detect CrazySpace [tm] */
2017 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
2018 if(modifiers_isDeformed(G.obedit)) {
2019 /* check if we can use deform matrices for modifier from the
2020 start up to stack, they are more accurate than quats */
2021 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
2023 /* if we still have more modifiers, also do crazyspace
2024 correction with quats, relative to the coordinates after
2025 the modifiers that support deform matrices (defcos) */
2027 mappedcos= get_crazy_mapped_editverts();
2028 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2029 set_crazyspace_quats((float*)defcos, mappedcos, quats);
2031 MEM_freeN(mappedcos);
2040 /* find out which half we do */
2042 for (eve=em->verts.first; eve; eve=eve->next) {
2043 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2051 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2053 if(propmode || eve->f1) {
2054 VertsToTransData(tob, eve);
2056 if(eve->f1) tob->flag |= TD_SELECTED;
2060 VECCOPY(vec, E_VEC(eve));
2061 Mat3MulVecfl(mtx, vec);
2062 tob->dist= VecLength(vec);
2065 tob->flag |= TD_NOTCONNECTED;
2066 tob->dist = MAXFLOAT;
2071 if(defmats || (quats && eve->tmp.p)) {
2072 float mat[3][3], imat[3][3], qmat[3][3];
2074 /* use both or either quat and defmat correction */
2075 if(quats && eve->tmp.f) {
2076 QuatToMat3(eve->tmp.p, qmat);
2079 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2080 NULL, NULL, NULL, NULL, NULL);
2082 Mat3MulMat3(mat, mtx, qmat);
2085 Mat3MulMat3(mat, mtx, defmats[a]);
2089 Mat3CpyMat3(tob->smtx, imat);
2090 Mat3CpyMat3(tob->mtx, mat);
2093 Mat3CpyMat3(tob->smtx, smtx);
2094 Mat3CpyMat3(tob->mtx, mtx);
2098 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2099 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
2100 if(vmir!=eve) tob->tdmir= vmir;
2110 /* crazy space free */
2117 /* ********************* UV ****************** */
2119 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2123 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2125 /* uv coords are scaled by aspects. this is needed for rotations and
2126 proportional editing to be consistent with the stretchted uv coords
2127 that are displayed. this also means that for display and numinput,
2128 and when the the uv coords are flushed, these are converted each time */
2129 td2d->loc[0] = uv[0]*aspx;
2130 td2d->loc[1] = uv[1]*aspy;
2131 td2d->loc[2] = 0.0f;
2135 td->loc = td2d->loc;
2136 VECCOPY(td->center, td->loc);
2137 VECCOPY(td->iloc, td->loc);
2139 memset(td->axismtx, 0, sizeof(td->axismtx));
2140 td->axismtx[2][2] = 1.0f;
2142 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2145 td->flag |= TD_SELECTED;
2155 static void createTransUVs(TransInfo *t)
2157 TransData *td = NULL;
2158 TransData2D *td2d = NULL;
2160 int count=0, countsel=0;
2161 int propmode = t->flag & T_PROP_EDIT;
2163 EditMesh *em = G.editMesh;
2166 if(is_uv_tface_editing_allowed()==0) return;
2169 for (efa= em->faces.first; efa; efa= efa->next) {
2170 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2171 if (simaFaceDraw_Check(efa, tf)) {
2172 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2173 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2174 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2175 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2177 count += (efa->v4)? 4: 3;
2181 /* note: in prop mode we need at least 1 selected */
2182 if (countsel==0) return;
2184 t->total= (propmode)? count: countsel;
2185 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2186 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2187 treated just as if they were 3d verts */
2188 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2190 if(G.sima->flag & SI_CLIP_UV)
2191 t->flag |= T_CLIP_UV;
2195 for (efa= em->faces.first; efa; efa= efa->next) {
2196 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2197 if (simaFaceDraw_Check(efa, tf)) {
2198 if(propmode || simaUVSel_Check(efa, tf, 0))
2199 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2200 if(propmode || simaUVSel_Check(efa, tf, 1))
2201 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2202 if(propmode || simaUVSel_Check(efa, tf, 2))
2203 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2205 if(efa->v4 && (propmode || simaUVSel_Check(efa, tf, 3)))
2206 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2210 if (G.sima->flag & SI_LIVE_UNWRAP)
2211 unwrap_lscm_live_begin();
2214 void flushTransUVs(TransInfo *t)
2217 int a, width, height;
2219 EditMesh *em = G.editMesh;
2220 float aspx, aspy, invx, invy;
2222 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2223 transform_width_height_tface_uv(&width, &height);
2227 /* flush to 2d vector from internally used 3d vector */
2228 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2229 td->loc2d[0]= td->loc[0]*invx;
2230 td->loc2d[1]= td->loc[1]*invy;
2232 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2233 td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
2234 td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
2238 /* always call this, also for cancel (it transforms non-selected vertices...) */
2239 if((G.sima->flag & SI_BE_SQUARE))
2240 be_square_tface_uv(em);
2242 /* this is overkill if G.sima->lock is not set, but still needed */
2243 object_uvs_changed(ob);
2246 int clipUVTransform(TransInfo *t, float *vec, int resize)
2249 int a, clipx=1, clipy=1;
2250 float aspx, aspy, min[2], max[2];
2252 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2253 min[0]= min[1]= 0.0f;
2254 max[0]= aspx; max[1]= aspy;
2256 for(a=0, td= t->data; a<t->total; a++, td++) {
2257 DO_MINMAX2(td->loc, min, max);
2261 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2262 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2263 else if(max[0] > aspx && t->center[0] < aspx)
2264 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2268 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2269 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2270 else if(max[1] > aspy && t->center[1] < aspy)
2271 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2278 else if(max[0] > aspx)
2279 vec[0] -= max[0]-aspx;
2285 else if(max[1] > aspy)
2286 vec[1] -= max[1]-aspy;
2291 return (clipx || clipy);
2294 /* ********************* IPO EDITOR ************************* */
2296 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2297 * due to bad globals that would need to be imported specially for this
2299 static void createTransIpoData(TransInfo *t)
2301 /* in editipo.c due to some globals that are defined in that file... */
2302 make_ipo_transdata(t);
2305 /* this function is called on recalcData to apply the transforms applied
2306 * to the transdata on to the actual keyframe data
2308 void flushTransIpoData(TransInfo *t)
2313 /* flush to 2d vector from internally used 3d vector */
2314 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2315 /* we need to unapply the nla-scaling from the time in some situations */
2317 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2319 td->loc2d[0]= td->loc[0];
2321 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2322 if ((t->data[a].flag & TD_TIMEONLY)==0)
2323 td->loc2d[1]= td->loc[1];
2327 /* ********************* ACTION/NLA EDITOR ****************** */
2329 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
2330 static short FrameOnMouseSide(char side, float frame, float cframe)
2332 /* both sides, so it doesn't matter */
2333 if (side == 'B') return 1;
2335 /* only on the named side */
2337 return (frame >= cframe) ? 1 : 0;
2339 return (frame <= cframe) ? 1 : 0;
2342 /* fully select selected beztriples, but only include if it's on the right side of cfra */
2343 static int count_ipo_keys(Ipo *ipo, char side, float cfra)
2352 /* only include points that occur on the right side of cfra */
2353 for (icu= ipo->curve.first; icu; icu= icu->next) {
2354 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
2355 if (bezt->f2 & SELECT) {
2356 /* fully select the other two keys */
2360 /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
2361 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
2370 /* This function assigns the information to transdata */
2371 static void TimeToTransData(TransData *td, float *time, Object *ob)
2373 /* memory is calloc'ed, so that should zero everything nicely for us */
2377 /* store the Object where this keyframe exists as a keyframe of the
2378 * active action as td->ob. Usually, this member is only used for constraints
2384 /* This function advances the address to which td points to, so it must return
2385 * the new address so that the next time new transform data is added, it doesn't
2386 * overwrite the existing ones... i.e. td = IpoToTransData(td, ipo, ob, side, cfra);
2388 * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
2389 * on the named side are used.
2391 static TransData *IpoToTransData(TransData *td, Ipo *ipo, Object *ob, char side, float cfra)
2400 for (icu= ipo->curve.first; icu; icu= icu->next) {
2401 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
2402 /* only add selected keyframes (for now, proportional edit is not enabled) */
2403 if (BEZSELECTED(bezt)) {
2404 /* only add if on the right 'side' of the current frame */
2405 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
2406 /* each control point needs to be added separetely */
2407 TimeToTransData(td, bezt->vec[0], ob);
2410 TimeToTransData(td, bezt->vec[1], ob);
2413 TimeToTransData(td, bezt->vec[2], ob);
2423 static void createTransActionData(TransInfo *t)
2425 TransData *td = NULL;
2428 ListBase act_data = {NULL, NULL};
2438 /* determine what type of data we are operating on */
2439 data = get_action_context(&datatype);
2440 if (data == NULL) return;
2443 filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
2444 actdata_filter(&act_data, filter, data, datatype);
2446 /* is the action scaled? if so, the it should belong to the active object */
2447 if (NLA_ACTION_SCALED)
2450 /* which side of the current frame should be allowed */
2451 if (t->mode == TFM_TIME_EXTEND) {
2452 /* only side on which mouse is gets transformed */
2453 float xmouse, ymouse;
2455 areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
2456 side = (xmouse > CFRA) ? 'R' : 'L';
2459 /* normal transform - both sides of current frame are considered */
2463 /* convert current-frame to action-time (slightly less accurate, espcially under
2464 * higher scaling ratios, but is faster than converting all points)
2467 cfra = get_action_frame(ob, CFRA);
2471 /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
2472 for (ale= act_data.first; ale; ale= ale->next)
2473 count += count_ipo_keys(ale->key_data, side, cfra);
2475 /* stop if trying to build list if nothing selected */
2477 /* cleanup temp list */
2478 BLI_freelistN(&act_data);
2482 /* allocate memory for data */
2484 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
2485 if (t->mode == TFM_TIME_SLIDE)
2486 t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
2489 /* loop 2: build transdata array */
2490 for (ale= act_data.first; ale; ale= ale->next) {
2491 Ipo *ipo= (Ipo *)ale->key_data;
2493 td= IpoToTransData(td, ipo, ob, side, cfra);
2496 /* check if we're supposed to be setting minx/maxx for TimeSlide */
2497 if (t->mode == TFM_TIME_SLIDE) {
2498 float min = 0, max = 0;
2502 for (i=1; i < count; i+=3, td+=3) {
2503 if (min > *(td->val)) min= *(td->val);
2504 if (max < *(td->val)) max= *(td->val);
2507 /* minx/maxx values used by TimeSlide are stored as a
2508 * calloced 2-float array in t->customData. This gets freed
2509 * in postTrans (T_FREE_CUSTOMDATA).
2511 *((float *)(t->customData)) = min;
2512 *((float *)(t->customData) + 1) = max;
2515 /* cleanup temp list */
2516 BLI_freelistN(&act_data);
2519 static void createTransNlaData(TransInfo *t)
2522 bActionStrip *strip;
2523 bActionChannel *achan;
2524 bConstraintChannel *conchan;
2526 TransData *td = NULL;
2531 /* which side of the current frame should be allowed */
2532 if (t->mode == TFM_TIME_EXTEND) {
2533 /* only side on which mouse is gets transformed */
2534 float xmouse, ymouse;
2536 areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
2537 side = (xmouse > CFRA) ? 'R' : 'L';
2540 /* normal transform - both sides of current frame are considered */
2544 /* Ensure that partial selections result in beztriple selections */
2545 for (base=G.scene->base.first; base; base=base->next) {
2546 /* Check object ipos */
2547 i= count_ipo_keys(base->object->ipo, side, CFRA);
2548 if (i) base->flag |= BA_HAS_RECALC_OB;
2551 /* Check object constraint ipos */
2552 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2553 count += count_ipo_keys(conchan->ipo, side, CFRA);
2555 /* skip actions and nlastrips if object is collapsed */
2556 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2559 /* Check action ipos */
2560 if (base->object->action) {
2561 /* exclude if strip is selected too */
2562 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2563 if (strip->flag & ACTSTRIP_SELECT)
2564 if (strip->act == base->object->action)
2568 cfra = get_action_frame(base->object, CFRA);
2570 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2571 if (EDITABLE_ACHAN(achan)) {
2572 i= count_ipo_keys(achan->ipo, side, cfra);
2573 if (i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2576 /* Check action constraint ipos */
2577 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2578 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2579 if (EDITABLE_CONCHAN(conchan))
2580 count += count_ipo_keys(conchan->ipo, side, cfra);
2588 /* Check nlastrips */
2589 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2590 if (strip->flag & ACTSTRIP_SELECT) {
2591 base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2593 if (FrameOnMouseSide(side, strip->start, CFRA)) count++;
2594 if (FrameOnMouseSide(side, strip->end, CFRA)) count++;
2599 /* If nothing is selected, bail out */
2603 /* allocate memory for data */
2605 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (NLA Editor)");
2607 /* build the transdata structure */
2609 for (base=G.scene->base.first; base; base=base->next) {
2610 /* Manipulate object ipos */
2611 /* - no scaling of keyframe times is allowed here */
2612 td= IpoToTransData(td, base->object->ipo, NULL, side, CFRA);
2614 /* Manipulate object constraint ipos */
2615 /* - no scaling of keyframe times is allowed here */
2616 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2617 td= IpoToTransData(td, conchan->ipo, NULL, side, CFRA);
2619 /* skip actions and nlastrips if object collapsed */
2620 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2623 /* Manipulate action ipos */
2624 if (base->object->action) {
2625 /* exclude if strip that active action belongs to is selected too */
2626 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2627 if (strip->flag & ACTSTRIP_SELECT)
2628 if (strip->act == base->object->action)
2632 /* can include if no strip found */
2634 cfra = get_action_frame(base->object, CFRA);
2636 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2637 if (EDITABLE_ACHAN(achan)) {
2638 td= IpoToTransData(td, achan->ipo, base->object, side, cfra);
2640 /* Manipulate action constraint ipos */
2641 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2642 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2643 if (EDITABLE_CONCHAN(conchan))
2644 td= IpoToTransData(td, conchan->ipo, base->object, side, cfra);
2652 /* Manipulate nlastrips */
2653 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2654 if (strip->flag & ACTSTRIP_SELECT) {
2655 /* first TransData is the start, second is the end */
2656 if (FrameOnMouseSide(side, strip->start, CFRA)) {
2657 td->val = &strip->start;
2658 td->ival = strip->start;
2661 if (FrameOnMouseSide(side, strip->end, CFRA)) {
2662 td->val = &strip->end;
2663 td->ival = strip->end;
2671 /* **************** IpoKey stuff, for Object TransData ********** */
2673 /* storage of bezier triple. thats why -3 and +3! */
2674 static void set_tdi_old(float *old, float *poin)
2681 /* while transforming */
2682 void add_tdi_poin(float *poin, float *old, float delta)
2685 poin[0]= old[0]+delta;
2686 poin[-3]= old[3]+delta;
2687 poin[3]= old[6]+delta;
2691 /* fill ipokey transdata with old vals and pointers */
2692 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
2694 extern int ob_ar[]; // blenkernel ipo.c
2695 TransDataIpokey *tdi= td->tdi;
2699 td->val= NULL; // is read on ESC
2701 for(a=0; a<OB_TOTIPO; a++) {
2705 switch( ob_ar[a] ) {
2708 tdi->locx= &(bezt->vec[1][1]); break;
2711 tdi->locy= &(bezt->vec[1][1]); break;
2714 tdi->locz= &(bezt->vec[1][1]); break;
2719 tdi->rotx= &(bezt->vec[1][1]); break;
2723 tdi->roty= &(bezt->vec[1][1]); break;
2727 tdi->rotz= &(bezt->vec[1][1]); break;
2731 tdi->sizex= &(bezt->vec[1][1]); break;
2734 tdi->sizey= &(bezt->vec[1][1]); break;
2737 tdi->sizez= &(bezt->vec[1][1]); break;
2742 /* oldvals for e.g. undo */
2743 if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
2744 if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
2745 if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
2747 /* remember, for mapping curves ('1'=10 degrees) */
2748 if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
2749 if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
2750 if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
2752 /* this is not allowed to be dsize! */
2753 if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
2754 if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
2755 if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
2758 if(delta) tdi->flag |= TOB_IPODROT;
2762 /* *************************** Object Transform data ******************* */
2764 /* Little helper function for ObjectToTransData used to give certain
2765 * constraints (ChildOf, FollowPath, and others that may be added)
2766 * inverse corrections for transform, so that they aren't in CrazySpace.
2767 * These particular constraints benefit from this, but others don't, hence
2768 * this semi-hack ;-) - Aligorith
2770 static short constraints_list_needinv(TransInfo *t, ListBase *list)
2774 /* loop through constraints, checking if there's one of the mentioned
2775 * constraints needing special crazyspace corrections
2778 for (con= list->first; con; con=con->next) {
2779 /* only consider constraint if it is enabled, and has influence on result */
2780 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) {
2781 /* (affirmative) returns for specific constraints here... */
2782 /* constraints that require this regardless */
2783 if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
2784 if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
2785 if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
2787 /* constraints that require this only under special conditions */
2788 if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
2789 /* CopyRot constraint only does this when rotating, and offset is on */
2790 bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
2792 if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
2799 /* no appropriate candidates found */
2803 /* transcribe given object into TransData for Transforming */
2804 static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
2807 ListBase fakecons = {NULL, NULL};
2811 /* axismtx has the real orientation */
2812 Mat3CpyMat4(td->axismtx, ob->obmat);
2813 Mat3Ortho(td->axismtx);
2815 td->con= ob->constraints.first;
2817 /* hack: tempolarily disable tracking and/or constraints when getting
2818 * object matrix, if tracking is on, or if constraints don't need
2819 * inverse correction to stop it from screwing up space conversion
2822 constinv= constraints_list_needinv(t, &ob->constraints);
2823 if (ob->track || constinv==0) {
2827 if (constinv == 0) {
2828 fakecons.first = ob->constraints.first;
2829 fakecons.last = ob->constraints.last;
2830 ob->constraints.first = ob->constraints.last = NULL;
2833 where_is_object(ob);
2835 if (constinv == 0) {
2836 ob->constraints.first = fakecons.first;
2837 ob->constraints.last = fakecons.last;
2843 where_is_object(ob);
2848 VECCOPY(td->iloc, td->loc);
2850 td->ext->rot = ob->rot;
2851 VECCOPY(td->ext->irot, ob->rot);