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_scene_types.h"
65 #include "DNA_screen_types.h"
66 #include "DNA_space_types.h"
67 #include "DNA_texture_types.h"
68 #include "DNA_view3d_types.h"
69 #include "DNA_world_types.h"
70 #include "DNA_userdef_types.h"
71 #include "DNA_property_types.h"
72 #include "DNA_vfont_types.h"
73 #include "DNA_constraint_types.h"
74 #include "DNA_listBase.h"
76 #include "BKE_action.h"
77 #include "BKE_armature.h"
78 #include "BKE_blender.h"
79 #include "BKE_cloth.h"
80 #include "BKE_curve.h"
81 #include "BKE_constraint.h"
82 #include "BKE_depsgraph.h"
83 #include "BKE_displist.h"
84 #include "BKE_DerivedMesh.h"
85 #include "BKE_effect.h"
87 #include "BKE_global.h"
89 #include "BKE_lattice.h"
92 #include "BKE_mball.h"
94 #include "BKE_modifier.h"
95 #include "BKE_object.h"
96 #include "BKE_softbody.h"
97 #include "BKE_utildefines.h"
99 #include "BIF_editaction.h"
100 #include "BIF_editview.h"
101 #include "BIF_editlattice.h"
102 #include "BIF_editconstraint.h"
103 #include "BIF_editarmature.h"
104 #include "BIF_editmesh.h"
105 #include "BIF_editnla.h"
106 #include "BIF_editsima.h"
108 #include "BIF_poseobject.h"
109 #include "BIF_meshtools.h"
110 #include "BIF_mywindow.h"
111 #include "BIF_resources.h"
112 #include "BIF_screen.h"
113 #include "BIF_space.h"
114 #include "BIF_toolbox.h"
116 #include "BSE_view.h"
117 #include "BSE_drawipo.h"
118 #include "BSE_edit.h"
119 #include "BSE_editipo.h"
120 #include "BSE_editipo_types.h"
121 #include "BSE_editaction_types.h"
123 #include "BDR_editobject.h" // reset_slowparents()
124 #include "BDR_unwrapper.h"
126 #include "BLI_arithb.h"
127 #include "BLI_blenlib.h"
128 #include "BLI_editVert.h"
130 #include "editmesh.h"
134 #include "mydevice.h"
136 extern ListBase editNurb;
137 extern ListBase editelems;
139 #include "transform.h"
141 /* local function prototype - for Object/Bone Constraints */
142 static short constraints_list_needinv(TransInfo *t, ListBase *list);
144 /* ************************** Functions *************************** */
146 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
147 TransData pivot = *head;
148 TransData *ihead = head;
149 TransData *itail = tail;
150 short connected = t->flag & T_PROP_CONNECTED;
155 while ((tail->dist >= pivot.dist) && (head < tail))
159 while ((tail->rdist >= pivot.rdist) && (head < tail))
170 while ((head->dist <= pivot.dist) && (head < tail))
174 while ((head->rdist <= pivot.rdist) && (head < tail))
187 qsort_trans_data(t, ihead, head-1);
190 qsort_trans_data(t, head+1, itail);
194 void sort_trans_data_dist(TransInfo *t) {
195 TransData *start = t->data;
198 while(i < t->total && start->flag & TD_SELECTED) {
202 qsort_trans_data(t, start, t->data + t->total - 1);
205 static void sort_trans_data(TransInfo *t)
207 TransData *sel, *unsel;
212 while (sel > unsel) {
213 while (unsel->flag & TD_SELECTED) {
219 while (!(sel->flag & TD_SELECTED)) {
233 /* distance calculated from not-selected vertex to nearest selected vertex
234 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
235 static void set_prop_dist(TransInfo *t, short with_dist)
240 for(a=0, tob= t->data; a<t->total; a++, tob++) {
242 tob->rdist= 0.0f; // init, it was mallocced
244 if((tob->flag & TD_SELECTED)==0) {
249 tob->rdist = -1.0f; // signal for next loop
251 for (i = 0, td= t->data; i < t->total; i++, td++) {
252 if(td->flag & TD_SELECTED) {
253 VecSubf(vec, tob->center, td->center);
254 Mat3MulVecfl(tob->mtx, vec);
255 dist = Normalize(vec);
256 if (tob->rdist == -1.0f) {
259 else if (dist < tob->rdist) {
263 else break; // by definition transdata has selected items in beginning
266 tob->dist = tob->rdist;
272 /* ************************** CONVERSIONS ************************* */
274 /* ********************* texture space ********* */
276 static void createTransTexspace(TransInfo *t)
284 if (ob==NULL) { // Shouldn't logically happen, but still...
290 if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
296 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
297 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
299 td->flag= TD_SELECTED;
300 VECCOPY(td->center, ob->obmat[3]);
303 Mat3CpyMat4(td->mtx, ob->obmat);
304 Mat3CpyMat4(td->axismtx, ob->obmat);
305 Mat3Ortho(td->axismtx);
306 Mat3Inv(td->smtx, td->mtx);
308 if( GS(id->name)==ID_ME) {
310 me->texflag &= ~AUTOSPACE;
312 td->ext->rot= me->rot;
313 td->ext->size= me->size;
315 else if( GS(id->name)==ID_CU) {
317 cu->texflag &= ~CU_AUTOSPACE;
319 td->ext->rot= cu->rot;
320 td->ext->size= cu->size;
322 else if( GS(id->name)==ID_MB) {
323 MetaBall *mb= ob->data;
324 mb->texflag &= ~MB_AUTOSPACE;
326 td->ext->rot= mb->rot;
327 td->ext->size= mb->size;
330 VECCOPY(td->iloc, td->loc);
331 VECCOPY(td->ext->irot, td->ext->rot);
332 VECCOPY(td->ext->isize, td->ext->size);
335 /* ********************* edge (for crease) ***** */
337 static void createTransEdge(TransInfo *t) {
338 TransData *td = NULL;
339 EditMesh *em = G.editMesh;
341 float mtx[3][3], smtx[3][3];
342 int count=0, countsel=0;
343 int propmode = t->flag & T_PROP_EDIT;
345 for(eed= em->edges.first; eed; eed= eed->next) {
347 if (eed->f & SELECT) countsel++;
348 if (propmode) count++;
362 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
364 Mat3CpyMat4(mtx, G.obedit->obmat);
367 for(eed= em->edges.first; eed; eed= eed->next) {
368 if(eed->h==0 && (eed->f & SELECT || propmode)) {
369 /* need to set center for center calculations */
370 VecAddf(td->center, eed->v1->co, eed->v2->co);
371 VecMulf(td->center, 0.5f);
375 td->flag= TD_SELECTED;
380 Mat3CpyMat3(td->smtx, smtx);
381 Mat3CpyMat3(td->mtx, mtx);
385 td->val = &(eed->crease);
386 td->ival = eed->crease;
393 /* ********************* pose mode ************* */
395 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
397 bConstraint *con= pchan->constraints.first;
399 for(;con; con= con->next) {
400 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
401 bKinematicConstraint *data= con->data;
405 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
412 static short apply_targetless_ik(Object *ob)
414 bPoseChannel *pchan, *parchan, *chanlist[256];
415 bKinematicConstraint *data;
416 int segcount, apply= 0;
418 /* now we got a difficult situation... we have to find the
419 target-less IK pchans, and apply transformation to the all
420 pchans that were in the chain */
422 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
423 data= has_targetless_ik(pchan);
424 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
426 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
429 /* exclude tip from chain? */
430 if(!(data->flag & CONSTRAINT_IK_TIP))
431 parchan= pchan->parent;
435 /* Find the chain's root & count the segments needed */
436 for (; parchan; parchan=parchan->parent){
437 chanlist[segcount]= parchan;
440 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
442 for(;segcount;segcount--) {
444 float rmat[4][4], tmat[4][4], imat[4][4];
446 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
447 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
448 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
449 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
451 parchan= chanlist[segcount-1];
453 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
455 if(parchan->parent) {
456 Bone *parbone= parchan->parent->bone;
457 float offs_bone[4][4];
459 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
460 Mat4CpyMat3(offs_bone, bone->bone_mat);
462 /* The bone's root offset (is in the parent's coordinate system) */
463 VECCOPY(offs_bone[3], bone->head);
465 /* Get the length translation of parent (length along y axis) */
466 offs_bone[3][1]+= parbone->length;
468 /* pose_mat(b-1) * offs_bone */
469 if(parchan->bone->flag & BONE_HINGE) {
470 /* the rotation of the parent restposition */
471 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
473 /* the location of actual parent transform */
474 VECCOPY(rmat[3], offs_bone[3]);
475 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
476 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
478 Mat4MulMat4(tmat, offs_bone, rmat);
481 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
483 Mat4Invert(imat, tmat);
486 Mat4CpyMat3(tmat, bone->bone_mat);
488 VECCOPY(tmat[3], bone->head);
489 Mat4Invert(imat, tmat);
492 Mat4MulMat4(rmat, parchan->pose_mat, imat);
494 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
496 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
498 Mat3CpyMat4(rmat3, rmat);
501 Mat3ToQuat(rmat3, parchan->quat);
503 /* for size, remove rotation */
504 QuatToMat3(parchan->quat, qmat);
506 Mat3MulMat3(smat, rmat3, imat);
507 Mat3ToSize(smat, parchan->size);
509 VECCOPY(parchan->loc, rmat[3]);
515 data->flag &= ~CONSTRAINT_IK_AUTO;
522 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
524 Bone *bone= pchan->bone;
525 float pmat[3][3], omat[3][3];
526 float cmat[3][3], tmat[3][3];
529 VECCOPY(vec, pchan->pose_mat[3]);
530 VECCOPY(td->center, vec);
533 td->flag= TD_SELECTED|TD_USEQUAT;
534 if(bone->flag & BONE_HINGE_CHILD_TRANSFORM)
535 td->flag |= TD_NOCENTER;
536 td->protectflag= pchan->protectflag;
538 td->loc = pchan->loc;
539 VECCOPY(td->iloc, pchan->loc);
542 td->ext->quat= pchan->quat;
543 td->ext->size= pchan->size;
545 QUATCOPY(td->ext->iquat, pchan->quat);
546 VECCOPY(td->ext->isize, pchan->size);
548 /* proper way to get parent transform + own transform + constraints transform */
549 Mat3CpyMat4(omat, ob->obmat);
552 if(pchan->bone->flag & BONE_HINGE)
553 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
555 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
557 if (constraints_list_needinv(t, &pchan->constraints)) {
558 Mat3CpyMat4(tmat, pchan->constinv);
560 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, cmat, omat, 0,0,0,0); // dang mulserie swaps args
563 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
566 if (constraints_list_needinv(t, &pchan->constraints)) {
567 Mat3CpyMat4(tmat, pchan->constinv);
569 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, cmat, omat, 0, 0,0,0,0); // dang mulserie swaps args
572 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
575 Mat3Inv(td->smtx, td->mtx);
577 /* for axismat we use bone's own transform */
578 Mat3CpyMat4(pmat, pchan->pose_mat);
579 Mat3MulMat3(td->axismtx, omat, pmat);
580 Mat3Ortho(td->axismtx);
582 if(t->mode==TFM_BONESIZE) {
583 bArmature *arm= t->poseobj->data;
585 if(arm->drawtype==ARM_ENVELOPE) {
587 td->val= &bone->dist;
588 td->ival= bone->dist;
591 // abusive storage of scale in the loc pointer :)
592 td->loc= &bone->xwidth;
593 VECCOPY (td->iloc, td->loc);
598 /* in this case we can do target-less IK grabbing */
599 if(t->mode==TFM_TRANSLATION) {
600 bKinematicConstraint *data= has_targetless_ik(pchan);
602 if(data->flag & CONSTRAINT_IK_TIP) {
603 VECCOPY(data->grabtarget, pchan->pose_tail);
606 VECCOPY(data->grabtarget, pchan->pose_head);
608 td->loc = data->grabtarget;
609 VECCOPY(td->iloc, td->loc);
610 data->flag |= CONSTRAINT_IK_AUTO;
612 /* only object matrix correction */
613 Mat3CpyMat3 (td->mtx, omat);
614 Mat3Inv (td->smtx, td->mtx);
619 static void bone_children_clear_transflag(ListBase *lb)
621 Bone *bone= lb->first;
623 for(;bone;bone= bone->next) {
624 if(bone->flag & BONE_HINGE)
625 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
627 bone->flag &= ~BONE_TRANSFORM;
629 bone_children_clear_transflag(&bone->childbase);
633 /* sets transform flags in the bones, returns total */
634 static void set_pose_transflags(TransInfo *t, Object *ob)
636 bArmature *arm= ob->data;
642 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
644 if(bone->layer & arm->layer) {
645 if(bone->flag & BONE_SELECTED)
646 bone->flag |= BONE_TRANSFORM;
648 bone->flag &= ~BONE_TRANSFORM;
650 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
654 /* make sure no bone can be transformed when a parent is transformed */
655 /* since pchans are depsgraph sorted, the parents are in beginning of list */
656 if(t->mode!=TFM_BONESIZE) {
657 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
659 if(bone->flag & BONE_TRANSFORM)
660 bone_children_clear_transflag(&bone->childbase);
663 /* now count, and check if we have autoIK or have to switch from translate to rotate */
664 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
666 if(bone->flag & BONE_TRANSFORM) {
669 if(t->mode==TFM_TRANSLATION) {
670 if( has_targetless_ik(pchan)==NULL ) {
671 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
672 if(!(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM))
673 t->mode= TFM_ROTATION;
675 else if((pchan->protectflag & OB_LOCK_LOC)==OB_LOCK_LOC)
676 t->mode= TFM_ROTATION;
683 /* frees temporal IKs */
684 static void pose_grab_with_ik_clear(Object *ob)
686 bKinematicConstraint *data;
690 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
691 for(con= pchan->constraints.first; con; con= con->next) {
692 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
694 if(data->flag & CONSTRAINT_IK_TEMP) {
695 BLI_remlink(&pchan->constraints, con);
696 MEM_freeN(con->data);
698 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
706 /* adds the IK to pchan */
707 static void pose_grab_with_ik_add(bPoseChannel *pchan)
709 bKinematicConstraint *data;
712 if (pchan == NULL) { // Sanity check
716 /* rule: not if there's already an IK on this channel */
717 for(con= pchan->constraints.first; con; con= con->next)
718 if(con->type==CONSTRAINT_TYPE_KINEMATIC)
722 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
723 data= has_targetless_ik(pchan);
725 data->flag |= CONSTRAINT_IK_AUTO;
729 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
730 BLI_addtail(&pchan->constraints, con);
731 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
733 data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
734 VECCOPY(data->grabtarget, pchan->pose_tail);
737 /* we include only a connected chain */
738 while(pchan && (pchan->bone->flag & BONE_CONNECTED)) {
740 pchan= pchan->parent;
744 /* bone is a canditate to get IK, but we don't do it if it has children connected */
745 static void pose_grab_with_ik_children(bPose *pose, Bone *bone)
750 /* go deeper if children & children are connected */
751 for(bonec= bone->childbase.first; bonec; bonec= bonec->next) {
752 if(bonec->flag & BONE_CONNECTED) {
754 pose_grab_with_ik_children(pose, bonec);
758 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
760 pose_grab_with_ik_add(pchan);
764 /* main call which adds temporal IK chains */
765 static void pose_grab_with_ik(Object *ob)
768 bPoseChannel *pchan, *pchansel= NULL;
771 if(ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0)
776 /* rule: only one Bone */
777 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
778 if(pchan->bone->layer & arm->layer) {
779 if(pchan->bone->flag & BONE_SELECTED) {
786 if(pchan || pchansel==NULL) return;
788 /* rule: no IK for solitary (unconnected) bone */
789 for(bonec=pchansel->bone->childbase.first; bonec; bonec=bonec->next) {
790 if(bonec->flag & BONE_CONNECTED) {
794 if ((pchansel->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL)) return;
796 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
797 if(pchansel->parent) {
798 /* only adds if there's no IK yet */
799 pose_grab_with_ik_add(pchansel);
802 /* rule: go over the children and add IK to the tips */
803 pose_grab_with_ik_children(ob->pose, pchansel->bone);
809 /* only called with pose mode active object now */
810 static void createTransPose(TransInfo *t, Object *ob)
815 TransDataExtension *tdx;
820 /* check validity of state */
821 arm=get_armature (ob);
822 if (arm==NULL || ob->pose==NULL) return;
824 if (arm->flag & ARM_RESTPOS) {
825 if(t->mode!=TFM_BONESIZE) {
826 notice ("Pose edit not possible while Rest Position is enabled");
830 if (!(ob->lay & G.vd->lay)) return;
832 /* do we need to add temporal IK chains? */
833 if((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION)
834 pose_grab_with_ik(ob);
836 /* set flags and count total (warning, can change transform to rotate) */
837 set_pose_transflags(t, ob);
839 if(t->total==0) return;
842 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
844 /* make sure the lock is set OK, unlock can be accidentally saved? */
845 ob->pose->flag |= POSE_LOCKED;
846 ob->pose->flag &= ~POSE_DO_UNLOCK;
848 /* init trans data */
849 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
850 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
851 for(i=0; i<t->total; i++, td++, tdx++) {
857 /* use pose channels to fill trans data */
859 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
860 if(pchan->bone->flag & BONE_TRANSFORM) {
861 add_pose_transdata(t, pchan, ob, td);
866 if(td != (t->data+t->total)) printf("Bone selection count error\n");
870 /* ********************* armature ************** */
872 static void createTransArmatureVerts(TransInfo *t)
875 bArmature *arm= G.obedit->data;
877 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
880 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
881 if(ebo->layer & arm->layer) {
882 if (t->mode==TFM_BONESIZE) {
883 if (ebo->flag & BONE_SELECTED)
886 else if (t->mode==TFM_BONE_ROLL) {
887 if (ebo->flag & BONE_SELECTED)
891 if (ebo->flag & BONE_TIPSEL)
893 if (ebo->flag & BONE_ROOTSEL)
899 if (!t->total) return;
901 Mat3CpyMat4(mtx, G.obedit->obmat);
904 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
906 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
907 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
909 if(ebo->layer & arm->layer) {
910 if (t->mode==TFM_BONE_ENVELOPE) {
912 if (ebo->flag & BONE_ROOTSEL){
913 td->val= &ebo->rad_head;
916 VECCOPY (td->center, ebo->head);
917 td->flag= TD_SELECTED;
919 Mat3CpyMat3(td->smtx, smtx);
920 Mat3CpyMat3(td->mtx, mtx);
928 if (ebo->flag & BONE_TIPSEL){
929 td->val= &ebo->rad_tail;
931 VECCOPY (td->center, ebo->tail);
932 td->flag= TD_SELECTED;
934 Mat3CpyMat3(td->smtx, smtx);
935 Mat3CpyMat3(td->mtx, mtx);
945 else if (t->mode==TFM_BONESIZE) {
946 if (ebo->flag & BONE_SELECTED) {
947 if(arm->drawtype==ARM_ENVELOPE) {
953 // abusive storage of scale in the loc pointer :)
954 td->loc= &ebo->xwidth;
955 VECCOPY (td->iloc, td->loc);
958 VECCOPY (td->center, ebo->head);
959 td->flag= TD_SELECTED;
961 /* use local bone matrix */
962 VecSubf(delta, ebo->tail, ebo->head);
963 vec_roll_to_mat3(delta, ebo->roll, bonemat);
964 Mat3MulMat3(td->mtx, mtx, bonemat);
965 Mat3Inv(td->smtx, td->mtx);
967 Mat3CpyMat3(td->axismtx, td->mtx);
968 Mat3Ortho(td->axismtx);
976 else if (t->mode==TFM_BONE_ROLL) {
977 if (ebo->flag & BONE_SELECTED) {
979 td->val= &(ebo->roll);
982 VECCOPY (td->center, ebo->head);
983 td->flag= TD_SELECTED;
992 if (ebo->flag & BONE_TIPSEL){
993 VECCOPY (td->iloc, ebo->tail);
994 VECCOPY (td->center, td->iloc);
996 td->flag= TD_SELECTED;
998 Mat3CpyMat3(td->smtx, smtx);
999 Mat3CpyMat3(td->mtx, mtx);
1007 if (ebo->flag & BONE_ROOTSEL){
1008 VECCOPY (td->iloc, ebo->head);
1009 VECCOPY (td->center, td->iloc);
1011 td->flag= TD_SELECTED;
1013 Mat3CpyMat3(td->smtx, smtx);
1014 Mat3CpyMat3(td->mtx, mtx);
1027 /* ********************* meta elements ********* */
1029 static void createTransMBallVerts(TransInfo *t)
1033 TransDataExtension *tx;
1034 float mtx[3][3], smtx[3][3];
1035 int count=0, countsel=0;
1036 int propmode = t->flag & T_PROP_EDIT;
1039 for(ml= editelems.first; ml; ml= ml->next) {
1040 if(ml->flag & SELECT) countsel++;
1041 if(propmode) count++;
1044 /* note: in prop mode we need at least 1 selected */
1045 if (countsel==0) return;
1047 if(propmode) t->total = count;
1048 else t->total = countsel;
1050 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1051 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1053 Mat3CpyMat4(mtx, G.obedit->obmat);
1056 for(ml= editelems.first; ml; ml= ml->next) {
1057 if(propmode || (ml->flag & SELECT)) {
1059 VECCOPY(td->iloc, td->loc);
1060 VECCOPY(td->center, td->loc);
1062 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1063 else td->flag= TD_USEQUAT;
1065 Mat3CpyMat3(td->smtx, smtx);
1066 Mat3CpyMat3(td->mtx, mtx);
1071 /* Radius of MetaElem (mass of MetaElem influence) */
1072 if(ml->flag & MB_SCALE_RAD){
1081 /* expx/expy/expz determine "shape" of some MetaElem types */
1082 tx->size = &ml->expx;
1083 tx->isize[0] = ml->expx;
1084 tx->isize[1] = ml->expy;
1085 tx->isize[2] = ml->expz;
1087 /* quat is used for rotation of MetaElem */
1088 tx->quat = ml->quat;
1089 QUATCOPY(tx->iquat, ml->quat);
1099 /* ********************* curve/surface ********* */
1101 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1102 TransData *td, *td_near = NULL;
1103 for (td = head; td<=tail; td++) {
1104 if (td->flag & TD_SELECTED) {
1110 dist = VecLenf(td_near->center, td->center);
1111 if (dist < (td-1)->dist) {
1112 td->dist = (td-1)->dist;
1119 td->dist = MAXFLOAT;
1120 td->flag |= TD_NOTCONNECTED;
1124 for (td = tail; td>=head; td--) {
1125 if (td->flag & TD_SELECTED) {
1131 dist = VecLenf(td_near->center, td->center);
1132 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1133 td->flag &= ~TD_NOTCONNECTED;
1134 if (dist < (td+1)->dist) {
1135 td->dist = (td+1)->dist;
1145 static void createTransCurveVerts(TransInfo *t)
1147 TransData *td = NULL;
1151 float mtx[3][3], smtx[3][3];
1153 int count=0, countsel=0;
1154 int propmode = t->flag & T_PROP_EDIT;
1156 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1157 for(nu= editNurb.first; nu; nu= nu->next) {
1158 if((nu->type & 7)==CU_BEZIER) {
1159 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1161 if (G.f & G_HIDDENHANDLES) {
1162 if(bezt->f2 & 1) countsel+=3;
1163 if(propmode) count+= 3;
1165 if(bezt->f1 & 1) countsel++;
1166 if(bezt->f2 & 1) countsel++;
1167 if(bezt->f3 & 1) countsel++;
1168 if(propmode) count+= 3;
1174 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1176 if(propmode) count++;
1177 if(bp->f1 & 1) countsel++;
1182 /* note: in prop mode we need at least 1 selected */
1183 if (countsel==0) return;
1185 if(propmode) t->total = count;
1186 else t->total = countsel;
1187 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1189 Mat3CpyMat4(mtx, G.obedit->obmat);
1193 for(nu= editNurb.first; nu; nu= nu->next) {
1194 if((nu->type & 7)==CU_BEZIER) {
1195 TransData *head, *tail;
1197 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1201 ((bezt->f2 & 1) && (G.f & G_HIDDENHANDLES)) ||
1202 ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)==0)
1204 VECCOPY(td->iloc, bezt->vec[0]);
1205 td->loc= bezt->vec[0];
1206 VECCOPY(td->center, bezt->vec[1]);
1207 if(bezt->f1 & 1 || G.f & G_HIDDENHANDLES) td->flag= TD_SELECTED;
1213 Mat3CpyMat3(td->smtx, smtx);
1214 Mat3CpyMat3(td->mtx, mtx);
1221 /* This is the Curve Point, the other two are handles */
1222 if(propmode || (bezt->f2 & 1)) {
1223 VECCOPY(td->iloc, bezt->vec[1]);
1224 td->loc= bezt->vec[1];
1225 VECCOPY(td->center, td->loc);
1226 if(bezt->f2 & 1) td->flag= TD_SELECTED;
1231 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1232 td->val = &(bezt->radius);
1233 td->ival = bezt->radius;
1234 } else if (t->mode==TFM_TILT) {
1235 td->val = &(bezt->alfa);
1236 td->ival = bezt->alfa;
1241 Mat3CpyMat3(td->smtx, smtx);
1242 Mat3CpyMat3(td->mtx, mtx);
1249 ((bezt->f1 & 1) && (G.f & G_HIDDENHANDLES)) ||
1250 ((bezt->f3 & 1) && (G.f & G_HIDDENHANDLES)==0)
1252 VECCOPY(td->iloc, bezt->vec[2]);
1253 td->loc= bezt->vec[2];
1254 VECCOPY(td->center, bezt->vec[1]);
1255 if(bezt->f3 & 1 || (G.f & G_HIDDENHANDLES)) td->flag= TD_SELECTED;
1261 Mat3CpyMat3(td->smtx, smtx);
1262 Mat3CpyMat3(td->mtx, mtx);
1269 else if (propmode && head != tail) {
1270 calc_distanceCurveVerts(head, tail-1);
1274 if (propmode && head != tail)
1275 calc_distanceCurveVerts(head, tail-1);
1278 TransData *head, *tail;
1280 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1282 if(propmode || (bp->f1 & 1)) {
1283 VECCOPY(td->iloc, bp->vec);
1285 VECCOPY(td->center, td->loc);
1286 if(bp->f1 & 1) td->flag= TD_SELECTED;
1291 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1292 td->val = &(bp->radius);
1293 td->ival = bp->radius;
1295 td->val = &(bp->alfa);
1296 td->ival = bp->alfa;
1299 Mat3CpyMat3(td->smtx, smtx);
1300 Mat3CpyMat3(td->mtx, mtx);
1307 else if (propmode && head != tail) {
1308 calc_distanceCurveVerts(head, tail-1);
1312 if (propmode && head != tail)
1313 calc_distanceCurveVerts(head, tail-1);
1318 /* ********************* lattice *************** */
1320 static void createTransLatticeVerts(TransInfo *t)
1322 TransData *td = NULL;
1324 float mtx[3][3], smtx[3][3];
1326 int count=0, countsel=0;
1327 int propmode = t->flag & T_PROP_EDIT;
1330 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1333 if(bp->f1 & 1) countsel++;
1334 if(propmode) count++;
1339 /* note: in prop mode we need at least 1 selected */
1340 if (countsel==0) return;
1342 if(propmode) t->total = count;
1343 else t->total = countsel;
1344 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1346 Mat3CpyMat4(mtx, G.obedit->obmat);
1351 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1353 if(propmode || (bp->f1 & 1)) {
1355 VECCOPY(td->iloc, bp->vec);
1357 VECCOPY(td->center, td->loc);
1358 if(bp->f1 & 1) td->flag= TD_SELECTED;
1360 Mat3CpyMat3(td->smtx, smtx);
1361 Mat3CpyMat3(td->mtx, mtx);
1375 /* ********************* mesh ****************** */
1377 /* proportional distance based on connectivity */
1378 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1379 #define E_NEAR(a) (nears[((a)->tmp.l)])
1380 #define THRESHOLD 0.0001f
1381 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1383 EditMesh *em = G.editMesh;
1388 /* f2 flag is used for 'selection' */
1389 /* tmp.l is offset on scratch array */
1390 for(eve= em->verts.first; eve; eve= eve->next) {
1394 if(eve->f & SELECT) {
1397 E_VEC(eve)[0] = 0.0f;
1398 E_VEC(eve)[1] = 0.0f;
1399 E_VEC(eve)[2] = 0.0f;
1408 /* Floodfill routine */
1410 At worst this is n*n of complexity where n is number of edges
1411 Best case would be n if the list is ordered perfectly.
1412 Estimate is n log n in average (so not too bad)
1417 for(eed= em->edges.first; eed; eed= eed->next) {
1419 EditVert *v1= eed->v1, *v2= eed->v2;
1420 float *vec2 = E_VEC(v2);
1421 float *vec1 = E_VEC(v1);
1423 if (v1->f2 + v2->f2 == 4)
1429 float len1 = VecLength(vec1);
1430 float len2 = VecLength(vec2);
1432 /* for v2 if not selected */
1434 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1435 lenn = VecLength(nvec);
1437 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1438 VECCOPY(vec2, nvec);
1439 E_NEAR(v2) = E_NEAR(v1);
1443 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1444 VECCOPY(vec2, vec1);
1445 E_NEAR(v2) = E_NEAR(v1);
1449 /* for v1 if not selected */
1451 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1452 lenn = VecLength(nvec);
1454 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1455 VECCOPY(vec1, nvec);
1456 E_NEAR(v1) = E_NEAR(v2);
1460 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1461 VECCOPY(vec1, vec2);
1462 E_NEAR(v1) = E_NEAR(v2);
1469 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1471 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1472 VECCOPY(vec2, vec1);
1474 E_NEAR(v2) = E_NEAR(v1);
1480 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1482 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1483 VECCOPY(vec1, vec2);
1485 E_NEAR(v1) = E_NEAR(v2);
1493 /* loop-in-a-loop I know, but we need it! (ton) */
1494 static void get_face_center(float *cent, EditVert *eve)
1496 EditMesh *em = G.editMesh;
1499 for(efa= em->faces.first; efa; efa= efa->next)
1501 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1504 VECCOPY(cent, efa->cent);
1508 static void VertsToTransData(TransData *td, EditVert *eve)
1513 VECCOPY(td->center, td->loc);
1514 if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1515 get_face_center(td->center, eve);
1516 VECCOPY(td->iloc, td->loc);
1519 VECCOPY(td->axismtx[2], eve->no);
1525 td->axismtx[1][2] = 0.0f;
1534 td->verse = (void*)eve->vvert;
1535 td->flag |= TD_VERSE_VERT;
1538 td->flag &= ~TD_VERSE_VERT;
1542 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1544 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1546 float *vec = userData;
1552 static int modifiers_disable_subsurf_temporary(Object *ob)
1557 for(md=ob->modifiers.first; md; md=md->next)
1558 if(md->type==eModifierType_Subsurf)
1559 if(md->mode & eModifierMode_OnCage) {
1560 md->mode ^= eModifierMode_DisableTemporary;
1567 /* disable subsurf temporal, get mapped cos, and enable it */
1568 static float *get_crazy_mapped_editverts(void)
1573 /* disable subsurf temporal, get mapped cos, and enable it */
1574 if(modifiers_disable_subsurf_temporary(G.obedit)) {
1575 /* need to make new derivemesh */
1576 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1579 /* now get the cage */
1580 dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1582 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1583 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1587 /* set back the flag, no new cage needs to be built, transform does it */
1588 modifiers_disable_subsurf_temporary(G.obedit);
1593 #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])
1594 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1596 float vecu[3], vecv[3];
1599 TAN_MAKE_VEC(vecu, v1, v2);
1600 TAN_MAKE_VEC(vecv, v1, v3);
1601 triatoquat(v1, vecu, vecv, q1);
1603 TAN_MAKE_VEC(vecu, def1, def2);
1604 TAN_MAKE_VEC(vecv, def1, def3);
1605 triatoquat(def1, vecu, vecv, q2);
1607 QuatSub(quat, q2, q1);
1611 static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
1613 EditMesh *em = G.editMesh;
1614 EditVert *eve, *prev;
1616 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
1619 /* two abused locations in vertices */
1620 for(eve= em->verts.first; eve; eve= eve->next, index++) {
1622 eve->prev= (EditVert *)index;
1625 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1626 for(efa= em->faces.first; efa; efa= efa->next) {
1628 /* retrieve mapped coordinates */
1629 v1= mappedcos + 3*(long)(efa->v1->prev);
1630 v2= mappedcos + 3*(long)(efa->v2->prev);
1631 v3= mappedcos + 3*(long)(efa->v3->prev);
1633 co1= (origcos)? origcos + 3*(long)(efa->v1->prev): efa->v1->co;
1634 co2= (origcos)? origcos + 3*(long)(efa->v2->prev): efa->v2->co;
1635 co3= (origcos)? origcos + 3*(long)(efa->v3->prev): efa->v3->co;
1637 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
1638 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
1639 efa->v2->tmp.p= (void*)quats;
1644 v4= mappedcos + 3*(long)(efa->v4->prev);
1645 co4= (origcos)? origcos + 3*(long)(efa->v4->prev): efa->v4->co;
1647 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1648 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
1649 efa->v1->tmp.p= (void*)quats;
1652 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1653 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
1654 efa->v3->tmp.p= (void*)quats;
1657 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
1658 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
1659 efa->v4->tmp.p= (void*)quats;
1664 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
1665 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
1666 efa->v1->tmp.p= (void*)quats;
1669 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
1670 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
1671 efa->v3->tmp.p= (void*)quats;
1677 /* restore abused prev pointer */
1678 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1683 static void createTransEditVerts(TransInfo *t)
1685 TransData *tob = NULL;
1686 EditMesh *em = G.editMesh;
1688 EditVert **nears = NULL;
1689 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1690 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
1691 int count=0, countsel=0, a, totleft;
1692 int propmode = t->flag & T_PROP_EDIT;
1693 int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR);
1695 // transform now requires awareness for select mode, so we tag the f1 flags in verts
1696 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1697 for(eve= em->verts.first; eve; eve= eve->next) {
1698 if(eve->h==0 && (eve->f & SELECT))
1704 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1706 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1707 for(eed= em->edges.first; eed; eed= eed->next) {
1708 if(eed->h==0 && (eed->f & SELECT))
1709 eed->v1->f1= eed->v2->f1= SELECT;
1714 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1715 for(efa= em->faces.first; efa; efa= efa->next) {
1716 if(efa->h==0 && (efa->f & SELECT)) {
1717 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1718 if(efa->v4) efa->v4->f1= SELECT;
1723 /* now we can count */
1724 for(eve= em->verts.first; eve; eve= eve->next) {
1726 if(eve->f1) countsel++;
1727 if(propmode) count++;
1731 /* note: in prop mode we need at least 1 selected */
1732 if (countsel==0) return;
1737 /* allocating scratch arrays */
1738 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1739 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1741 else t->total = countsel;
1742 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1744 Mat3CpyMat4(mtx, G.obedit->obmat);
1747 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1749 /* detect CrazySpace [tm] */
1751 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1752 if(modifiers_isDeformed(G.obedit)) {
1753 /* check if we can use deform matrices for modifier from the
1754 start up to stack, they are more accurate than quats */
1755 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
1757 /* if we still have more modifiers, also do crazyspace
1758 correction with quats, relative to the coordinates after
1759 the modifiers that support deform matrices (defcos) */
1761 mappedcos= get_crazy_mapped_editverts();
1762 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
1763 set_crazyspace_quats((float*)defcos, mappedcos, quats);
1765 MEM_freeN(mappedcos);
1774 /* find out which half we do */
1776 for (eve=em->verts.first; eve; eve=eve->next) {
1777 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1785 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
1787 if(propmode || eve->f1) {
1788 VertsToTransData(tob, eve);
1790 if(eve->f1) tob->flag |= TD_SELECTED;
1794 VECCOPY(vec, E_VEC(eve));
1795 Mat3MulVecfl(mtx, vec);
1796 tob->dist= VecLength(vec);
1799 tob->flag |= TD_NOTCONNECTED;
1800 tob->dist = MAXFLOAT;
1805 if(defmats || (quats && eve->tmp.p)) {
1806 float mat[3][3], imat[3][3], qmat[3][3];
1808 /* use both or either quat and defmat correction */
1809 if(quats && eve->tmp.f) {
1810 QuatToMat3(eve->tmp.p, qmat);
1813 Mat3MulSerie(mat, mtx, qmat, defmats[a],
1814 NULL, NULL, NULL, NULL, NULL);
1816 Mat3MulMat3(mat, mtx, qmat);
1819 Mat3MulMat3(mat, mtx, defmats[a]);
1823 Mat3CpyMat3(tob->smtx, imat);
1824 Mat3CpyMat3(tob->mtx, mat);
1827 Mat3CpyMat3(tob->smtx, smtx);
1828 Mat3CpyMat3(tob->mtx, mtx);
1832 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1833 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
1834 if(vmir!=eve) tob->tdmir= vmir;
1844 /* crazy space free */
1851 /* ********************* UV ****************** */
1853 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1857 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1859 /* uv coords are scaled by aspects. this is needed for rotations and
1860 proportional editing to be consistent with the stretchted uv coords
1861 that are displayed. this also means that for display and numinput,
1862 and when the the uv coords are flushed, these are converted each time */
1863 td2d->loc[0] = uv[0]*aspx;
1864 td2d->loc[1] = uv[1]*aspy;
1865 td2d->loc[2] = 0.0f;
1869 td->loc = td2d->loc;
1870 VECCOPY(td->center, td->loc);
1871 VECCOPY(td->iloc, td->loc);
1873 memset(td->axismtx, 0, sizeof(td->axismtx));
1874 td->axismtx[2][2] = 1.0f;
1876 td->ext= NULL; td->tdi= NULL; td->val= NULL;
1879 td->flag |= TD_SELECTED;
1889 static void createTransUVs(TransInfo *t)
1891 TransData *td = NULL;
1892 TransData2D *td2d = NULL;
1894 int count=0, countsel=0;
1895 int propmode = t->flag & T_PROP_EDIT;
1897 EditMesh *em = G.editMesh;
1900 if(is_uv_tface_editing_allowed()==0) return;
1903 for (efa= em->faces.first; efa; efa= efa->next) {
1904 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1905 if SIMA_FACEDRAW_CHECK(efa, tf) {
1906 if (SIMA_UVSEL_CHECK(efa, tf, 0)) countsel++;
1907 if (SIMA_UVSEL_CHECK(efa, tf, 1)) countsel++;
1908 if (SIMA_UVSEL_CHECK(efa, tf, 2)) countsel++;
1909 if (efa->v4 && SIMA_UVSEL_CHECK(efa, tf, 3)) countsel++;
1911 count += (efa->v4)? 4: 3;
1915 /* note: in prop mode we need at least 1 selected */
1916 if (countsel==0) return;
1918 t->total= (propmode)? count: countsel;
1919 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1920 /* for each 2d uv coord a 3d vector is allocated, so that they can be
1921 treated just as if they were 3d verts */
1922 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1924 if(G.sima->flag & SI_CLIP_UV)
1925 t->flag |= T_CLIP_UV;
1929 for (efa= em->faces.first; efa; efa= efa->next) {
1930 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
1931 if SIMA_FACEDRAW_CHECK(efa, tf) {
1932 if(propmode || SIMA_UVSEL_CHECK(efa, tf, 0))
1933 UVsToTransData(td++, td2d++, tf->uv[0], SIMA_UVSEL_CHECK(efa, tf, 0));
1934 if(propmode || SIMA_UVSEL_CHECK(efa, tf, 1))
1935 UVsToTransData(td++, td2d++, tf->uv[1], SIMA_UVSEL_CHECK(efa, tf, 1));
1936 if(propmode || SIMA_UVSEL_CHECK(efa, tf, 2))
1937 UVsToTransData(td++, td2d++, tf->uv[2], SIMA_UVSEL_CHECK(efa, tf, 2));
1939 if(efa->v4 && (propmode || SIMA_UVSEL_CHECK(efa, tf, 3)))
1940 UVsToTransData(td++, td2d++, tf->uv[3], SIMA_UVSEL_CHECK(efa, tf, 3));
1944 if (G.sima->flag & SI_LIVE_UNWRAP)
1945 unwrap_lscm_live_begin();
1948 void flushTransUVs(TransInfo *t)
1951 int a, width, height;
1953 EditMesh *em = G.editMesh;
1954 float aspx, aspy, invx, invy;
1956 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1957 transform_width_height_tface_uv(&width, &height);
1961 /* flush to 2d vector from internally used 3d vector */
1962 for(a=0, td= t->data2d; a<t->total; a++, td++) {
1963 td->loc2d[0]= td->loc[0]*invx;
1964 td->loc2d[1]= td->loc[1]*invy;
1966 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1967 td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
1968 td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
1972 /* always call this, also for cancel (it transforms non-selected vertices...) */
1973 if((G.sima->flag & SI_BE_SQUARE))
1974 be_square_tface_uv(em);
1976 /* this is overkill if G.sima->lock is not set, but still needed */
1977 object_uvs_changed(ob);
1980 int clipUVTransform(TransInfo *t, float *vec, int resize)
1983 int a, clipx=1, clipy=1;
1984 float aspx, aspy, min[2], max[2];
1986 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1987 min[0]= min[1]= 0.0f;
1988 max[0]= aspx; max[1]= aspy;
1990 for(a=0, td= t->data; a<t->total; a++, td++) {
1991 DO_MINMAX2(td->loc, min, max);
1995 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1996 vec[0] *= t->center[0]/(t->center[0] - min[0]);
1997 else if(max[0] > aspx && t->center[0] < aspx)
1998 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2002 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2003 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2004 else if(max[1] > aspy && t->center[1] < aspy)
2005 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2012 else if(max[0] > aspx)
2013 vec[0] -= max[0]-aspx;
2019 else if(max[1] > aspy)
2020 vec[1] -= max[1]-aspy;
2025 return (clipx || clipy);
2028 /* ********************* IPO EDITOR ************************* */
2030 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2031 * due to bad globals that would need to be imported specially for this
2033 static void createTransIpoData(TransInfo *t)
2035 /* in editipo.c due to some globals that are defined in that file... */
2036 make_ipo_transdata(t);
2039 /* this function is called on recalcData to apply the transforms applied
2040 * to the transdata on to the actual keyframe data
2042 void flushTransIpoData(TransInfo *t)
2047 /* flush to 2d vector from internally used 3d vector */
2048 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2049 /* we need to unapply the nla-scaling from the time in some situations */
2051 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2053 td->loc2d[0]= td->loc[0];
2055 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2056 if ((t->data[a].flag & TD_TIMEONLY)==0)
2057 td->loc2d[1]= td->loc[1];
2061 /* ********************* ACTION/NLA EDITOR ****************** */
2063 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
2064 static short FrameOnMouseSide(char side, float frame, float cframe)
2066 /* both sides, so it doesn't matter */
2067 if (side == 'B') return 1;
2069 /* only on the named side */
2071 return (frame >= cframe) ? 1 : 0;
2073 return (frame <= cframe) ? 1 : 0;
2076 /* fully select selected beztriples, but only include if it's on the right side of cfra */
2077 static int count_ipo_keys(Ipo *ipo, char side, float cfra)
2086 /* only include points that occur on the right side of cfra */
2087 for (icu= ipo->curve.first; icu; icu= icu->next) {
2088 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
2090 /* fully select the other two keys */
2094 /* increment by 3, as there are 3 points (3 * x-coordinates) that need transform */
2095 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra))
2104 /* This function assigns the information to transdata */
2105 static void TimeToTransData(TransData *td, float *time, Object *ob)
2107 /* memory is calloc'ed, so that should zero everything nicely for us */
2111 /* store the Object where this keyframe exists as a keyframe of the
2112 * active action as td->ob. Usually, this member is only used for constraints
2118 /* This function advances the address to which td points to, so it must return
2119 * the new address so that the next time new transform data is added, it doesn't
2120 * overwrite the existing ones... i.e. td = IpoToTransData(td, ipo, ob, side, cfra);
2122 * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data
2123 * on the named side are used.
2125 static TransData *IpoToTransData(TransData *td, Ipo *ipo, Object *ob, char side, float cfra)
2134 for (icu= ipo->curve.first; icu; icu= icu->next) {
2135 for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
2136 /* only add selected keyframes (for now, proportional edit is not enabled) */
2137 if (BEZSELECTED(bezt)) {
2138 /* only add if on the right 'side' of the current frame */
2139 if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) {
2140 /* each control point needs to be added separetely */
2141 TimeToTransData(td, bezt->vec[0], ob);
2144 TimeToTransData(td, bezt->vec[1], ob);
2147 TimeToTransData(td, bezt->vec[2], ob);
2157 static void createTransActionData(TransInfo *t)
2159 TransData *td = NULL;
2162 ListBase act_data = {NULL, NULL};
2172 /* determine what type of data we are operating on */
2173 data = get_action_context(&datatype);
2174 if (data == NULL) return;
2177 filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
2178 actdata_filter(&act_data, filter, data, datatype);
2180 /* is the action scaled? if so, the it should belong to the active object */
2181 if (NLA_ACTION_SCALED)
2184 /* which side of the current frame should be allowed */
2185 if (t->mode == TFM_TIME_EXTEND) {
2186 /* only side on which mouse is gets transformed */
2187 float xmouse, ymouse;
2189 areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
2190 side = (xmouse > CFRA) ? 'R' : 'L';
2193 /* normal transform - both sides of current frame are considered */
2197 /* convert current-frame to action-time (slightly less accurate, espcially under
2198 * higher scaling ratios, but is faster than converting all points)
2201 cfra = get_action_frame(ob, CFRA);
2205 /* loop 1: fully select ipo-keys and count how many BezTriples are selected */
2206 for (ale= act_data.first; ale; ale= ale->next)
2207 count += count_ipo_keys(ale->key_data, side, cfra);
2209 /* stop if trying to build list if nothing selected */
2211 /* cleanup temp list */
2212 BLI_freelistN(&act_data);
2216 /* allocate memory for data */
2218 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(Action Editor)");
2219 if (t->mode == TFM_TIME_SLIDE)
2220 t->customData= MEM_callocN(sizeof(float)*2, "TimeSlide Min/Max");
2223 /* loop 2: build transdata array */
2224 for (ale= act_data.first; ale; ale= ale->next) {
2225 Ipo *ipo= (Ipo *)ale->key_data;
2227 td= IpoToTransData(td, ipo, ob, side, cfra);
2230 /* check if we're supposed to be setting minx/maxx for TimeSlide */
2231 if (t->mode == TFM_TIME_SLIDE) {
2232 float min = 0, max = 0;
2236 for (i=1; i < count; i+=3, td+=3) {
2237 if (min > *(td->val)) min= *(td->val);
2238 if (max < *(td->val)) max= *(td->val);
2241 /* minx/maxx values used by TimeSlide are stored as a
2242 * calloced 2-float array in t->customData. This gets freed
2243 * in postTrans (T_FREE_CUSTOMDATA).
2245 *((float *)(t->customData)) = min;
2246 *((float *)(t->customData) + 1) = max;
2249 /* cleanup temp list */
2250 BLI_freelistN(&act_data);
2253 static void createTransNlaData(TransInfo *t)
2256 bActionStrip *strip;
2257 bActionChannel *achan;
2258 bConstraintChannel *conchan;
2260 TransData *td = NULL;
2265 /* which side of the current frame should be allowed */
2266 if (t->mode == TFM_TIME_EXTEND) {
2267 /* only side on which mouse is gets transformed */
2268 float xmouse, ymouse;
2270 areamouseco_to_ipoco(G.v2d, t->imval, &xmouse, &ymouse);
2271 side = (xmouse > CFRA) ? 'R' : 'L';
2274 /* normal transform - both sides of current frame are considered */
2278 /* Ensure that partial selections result in beztriple selections */
2279 for (base=G.scene->base.first; base; base=base->next) {
2280 /* Check object ipos */
2281 i= count_ipo_keys(base->object->ipo, side, CFRA);
2282 if (i) base->flag |= BA_HAS_RECALC_OB;
2285 /* Check object constraint ipos */
2286 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2287 count += count_ipo_keys(conchan->ipo, side, CFRA);
2289 /* skip actions and nlastrips if object is collapsed */
2290 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2293 /* Check action ipos */
2294 if (base->object->action) {
2295 /* exclude if strip is selected too */
2296 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2297 if (strip->flag & ACTSTRIP_SELECT)
2298 if (strip->act == base->object->action)
2302 cfra = get_action_frame(base->object, CFRA);
2304 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2305 if (EDITABLE_ACHAN(achan)) {
2306 i= count_ipo_keys(achan->ipo, side, cfra);
2307 if (i) base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2310 /* Check action constraint ipos */
2311 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2312 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2313 if (EDITABLE_CONCHAN(conchan))
2314 count += count_ipo_keys(conchan->ipo, side, cfra);
2322 /* Check nlastrips */
2323 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2324 if (strip->flag & ACTSTRIP_SELECT) {
2325 base->flag |= BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA;
2327 if (FrameOnMouseSide(side, strip->start, CFRA)) count++;
2328 if (FrameOnMouseSide(side, strip->end, CFRA)) count++;
2333 /* If nothing is selected, bail out */
2337 /* allocate memory for data */
2339 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData (NLA Editor)");
2341 /* build the transdata structure */
2343 for (base=G.scene->base.first; base; base=base->next) {
2344 /* Manipulate object ipos */
2345 /* - no scaling of keyframe times is allowed here */
2346 td= IpoToTransData(td, base->object->ipo, NULL, side, CFRA);
2348 /* Manipulate object constraint ipos */
2349 /* - no scaling of keyframe times is allowed here */
2350 for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
2351 td= IpoToTransData(td, conchan->ipo, NULL, side, CFRA);
2353 /* skip actions and nlastrips if object collapsed */
2354 if (base->object->nlaflag & OB_NLA_COLLAPSED)
2357 /* Manipulate action ipos */
2358 if (base->object->action) {
2359 /* exclude if strip that active action belongs to is selected too */
2360 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2361 if (strip->flag & ACTSTRIP_SELECT)
2362 if (strip->act == base->object->action)
2366 /* can include if no strip found */
2368 cfra = get_action_frame(base->object, CFRA);
2370 for (achan=base->object->action->chanbase.first; achan; achan=achan->next) {
2371 if (EDITABLE_ACHAN(achan)) {
2372 td= IpoToTransData(td, achan->ipo, base->object, side, cfra);
2374 /* Manipulate action constraint ipos */
2375 if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) {
2376 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
2377 if (EDITABLE_CONCHAN(conchan))
2378 td= IpoToTransData(td, conchan->ipo, base->object, side, cfra);
2386 /* Manipulate nlastrips */
2387 for (strip=base->object->nlastrips.first; strip; strip=strip->next) {
2388 if (strip->flag & ACTSTRIP_SELECT) {
2389 /* first TransData is the start, second is the end */
2390 if (FrameOnMouseSide(side, strip->start, CFRA)) {
2391 td->val = &strip->start;
2392 td->ival = strip->start;
2395 if (FrameOnMouseSide(side, strip->end, CFRA)) {
2396 td->val = &strip->end;
2397 td->ival = strip->end;
2405 /* **************** IpoKey stuff, for Object TransData ********** */
2407 /* storage of bezier triple. thats why -3 and +3! */
2408 static void set_tdi_old(float *old, float *poin)
2415 /* while transforming */
2416 void add_tdi_poin(float *poin, float *old, float delta)
2419 poin[0]= old[0]+delta;
2420 poin[-3]= old[3]+delta;
2421 poin[3]= old[6]+delta;
2425 /* fill ipokey transdata with old vals and pointers */
2426 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
2428 extern int ob_ar[]; // blenkernel ipo.c
2429 TransDataIpokey *tdi= td->tdi;
2433 td->val= NULL; // is read on ESC
2435 for(a=0; a<OB_TOTIPO; a++) {
2439 switch( ob_ar[a] ) {
2442 tdi->locx= &(bezt->vec[1][1]); break;
2445 tdi->locy= &(bezt->vec[1][1]); break;
2448 tdi->locz= &(bezt->vec[1][1]); break;
2453 tdi->rotx= &(bezt->vec[1][1]); break;
2457 tdi->roty= &(bezt->vec[1][1]); break;
2461 tdi->rotz= &(bezt->vec[1][1]); break;
2465 tdi->sizex= &(bezt->vec[1][1]); break;
2468 tdi->sizey= &(bezt->vec[1][1]); break;
2471 tdi->sizez= &(bezt->vec[1][1]); break;
2476 /* oldvals for e.g. undo */
2477 if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
2478 if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
2479 if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
2481 /* remember, for mapping curves ('1'=10 degrees) */
2482 if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
2483 if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
2484 if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
2486 /* this is not allowed to be dsize! */
2487 if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
2488 if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
2489 if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
2492 if(delta) tdi->flag |= TOB_IPODROT;
2496 /* *************************** Object Transform data ******************* */
2498 /* Little helper function for ObjectToTransData used to give certain
2499 * constraints (ChildOf, FollowPath, and others that may be added)
2500 * inverse corrections for transform, so that they aren't in CrazySpace.
2501 * These particular constraints benefit from this, but others don't, hence
2502 * this semi-hack ;-) - Aligorith
2504 static short constraints_list_needinv(TransInfo *t, ListBase *list)
2508 /* loop through constraints, checking if there's one of the mentioned
2509 * constraints needing special crazyspace corrections
2512 for (con= list->first; con; con=con->next) {
2513 /* only consider constraint if it is enabled, and has influence on result */
2514 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) {
2515 /* (affirmative) returns for specific constraints here... */
2516 /* constraints that require this regardless */
2517 if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1;
2518 if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1;
2519 if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1;
2521 /* constraints that require this only under special conditions */
2522 if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
2523 /* CopyRot constraint only does this when rotating, and offset is on */
2524 bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
2526 if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION))
2533 /* no appropriate candidates found */
2537 /* transcribe given object into TransData for Transforming */
2538 static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
2541 ListBase fakecons = {NULL, NULL};
2545 /* axismtx has the real orientation */
2546 Mat3CpyMat4(td->axismtx, ob->obmat);
2547 Mat3Ortho(td->axismtx);
2549 /* hack: tempolarily disable tracking and/or constraints when getting
2550 * object matrix, if tracking is on, or if constraints don't need
2551 * inverse correction to stop it from screwing up space conversion
2554 constinv= constraints_list_needinv(t, &ob->constraints);
2555 if (ob->track || constinv==0) {
2559 if (constinv == 0) {
2560 fakecons.first = ob->constraints.first;
2561 fakecons.last = ob->constraints.last;
2562 ob->constraints.first = ob->constraints.last = NULL;
2565 where_is_object(ob);
2567 if (constinv == 0) {
2568 ob->constraints.first = fakecons.first;
2569 ob->constraints.last = fakecons.last;
2575 where_is_object(ob);
2580 VECCOPY(td->iloc, td->loc);
2582 td->ext->rot = ob->rot;
2583 VECCOPY(td->ext->irot, ob->rot);
2584 VECCOPY(td->ext->drot, ob->drot);
2586 td->ext->size = ob->size;
2587 VECCOPY(td->ext->isize, ob->size);
2588 VECCOPY(td->ext->dsize, ob->dsize);
2590 VECCOPY(td->center, ob->obmat[3]);
2592 /* is there a need to set the global<->data space conversion matrices? */
2593 if (ob->parent || constinv) {
2594 float totmat[3][3], obinv[3][3];
2596 /* Get the effect of parenting, and/or certain constraints.
2597 * NOTE: some Constraints, and also Tracking should never get this
2598 * done, as it doesn't work well.
2600 object_to_mat3(ob, obmtx);
2601 Mat3CpyMat4(totmat, ob->obmat);
2602 Mat3Inv(obinv, totmat);
2603 Mat3MulMat3(td->smtx, obmtx, obinv);
2604 Mat3Inv(td->mtx, td->smtx);
2607 /* no conversion to/from dataspace */
2613 td->verse = (void*)ob;
2614 td->flag |= TD_VERSE_OBJECT;
2617 td->flag &= ~TD_VERSE_OBJECT;
2622 /* sets flags in Bases to define whether they take part in transform */
2623 /* it deselects Bases, so we have to call the clear function always after */
2624 static void set_trans_object_base_flags(TransInfo *t)
2627 if Base selected and has parent selected:
2628 base->flag= BA_WAS_SEL
2632 /* makes sure base flags and object flags are identical */
2635 /* handle pending update events, otherwise they got copied below */
2636 for (base= FIRSTBASE; base; base= base->next) {
2637 if(base->object->recalc)
2638 object_handle_update(base->object);
2641 for (base= FIRSTBASE; base; base= base->next) {
2642 base->flag &= ~BA_WAS_SEL;
2644 if(TESTBASELIB(base)) {
2645 Object *ob= base->object;
2646 Object *parsel= ob->parent;
2648 /* if parent selected, deselect */
2650 if(parsel->flag & SELECT) break;
2651 parsel= parsel->parent;
2655 base->flag &= ~SELECT;
2656 base->flag |= BA_WAS_SEL;
2658 /* used for flush, depgraph will change recalcs if needed :) */
2659 ob->recalc |= OB_RECALC_OB;
2662 /* all recalc flags get flushed to all layers, so a layer flip later on works fine */
2663 DAG_scene_flush_update(G.scene, -1);
2665 /* and we store them temporal in base (only used for transform code) */
2666 /* this because after doing updates, the object->recalc is cleared */
2667 for (base= FIRSTBASE; base; base= base->next) {
2668 if(base->object->recalc & OB_RECALC_OB)
2669 base->flag |= BA_HAS_RECALC_OB;
2670 if(base->object->recalc & OB_RECALC_DATA)
2671 base->flag |= BA_HAS_RECALC_DATA;
2675 static void clear_trans_object_base_flags(void)
2681 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2682 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2688 /* auto-keyframing feature - for objects
2689 * tmode: should be a transform mode
2691 void autokeyframe_ob_cb_func(Object *ob, int tmode)
2696 if (G.flags & G_RECORDKEYS) {
2697 if (ob->ipoflag & OB_ACTION_OB)
2700 if (U.uiflag & USER_KEYINSERTAVAI) {
2701 if (ob->ipo || ob->action) {
2705 icu= ob->ipo->curve.first;
2708 bActionChannel *achan;
2709 achan= get_action_channel(ob->action, actname);
2711 if (achan && achan->ipo)
2712 icu= achan->ipo->curve.first;
2718 icu->flag &= ~IPO_SELECT;
2719 if (U.uiflag & USER_KEYINSERTNEED)
2720 insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode);
2722 insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0);
2727 else if (U.uiflag & USER_KEYINSERTNEED) {
2728 short doLoc=0, doRot=0, doScale=0;
2730 /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */
2731 if (tmode == TFM_TRANSLATION) {
2734 else if (tmode == TFM_ROTATION) {
2735 if (G.vd->around == V3D_ACTIVE) {
2739 else if (G.vd->around == V3D_CURSOR)
2742 if ((G.vd->flag & V3D_ALIGN)==0)
2745 else if (tmode == TFM_RESIZE) {
2746 if (G.vd->around == V3D_ACTIVE) {
2750 else if (G.vd->around == V3D_CURSOR)
2753 if ((G.vd->flag & V3D_ALIGN)==0)
2758 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_X);
2759 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Y);
2760 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_LOC_Z);
2763 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_X);
2764 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Y);
2765 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_ROT_Z);
2768 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_X);
2769 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y);
2770 insertkey_smarter(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z);
2774 insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_X, 0);
2775 insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Y, 0);
2776 insertkey(&ob->id, ID_OB, actname, NULL, OB_ROT_Z, 0);
2778 insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_X, 0);
2779 insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Y, 0);
2780 insertkey(&ob->id, ID_OB, actname, NULL, OB_LOC_Z, 0);
2782 insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_X, 0);
2783 insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Y, 0);
2784 insertkey(&ob->id, ID_OB, actname, NULL, OB_SIZE_Z, 0);
2787 remake_object_ipos(ob);
2788 allqueue(REDRAWMARKER, 0);
2792 /* auto-keyframing feature - for poses/pose-channels
2793 * tmode: should be a transform mode
2794 * targetless_ik: has targetless ik been done on any channels?
2796 void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik)
2798 bArmature *arm= ob->data;
2801 bPoseChannel *pchan;
2807 if (G.flags & G_RECORDKEYS) {
2809 act= ob->action= add_empty_action("Action");
2811 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) {
2812 if (pchan->bone->flag & BONE_TRANSFORM) {
2813 /* clear any 'unkeyed' flag it may have */
2814 pchan->bone->flag &= ~BONE_UNKEYED;
2816 /* only insert into available channels? */
2817 if (U.uiflag & USER_KEYINSERTAVAI) {
2818 bActionChannel *achan;
2820 for (achan = act->chanbase.first; achan; achan=achan->next){
2821 if (achan->ipo && !strcmp (achan->name, pchan->name)){
2822 for (icu = achan->ipo->curve.first; icu; icu=icu->next){
2823 /* only insert keyframe if needed? */
2824 if (U.uiflag & USER_KEYINSERTNEED)
2825 insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);