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_object_types.h"
62 #include "DNA_object_force.h"
63 #include "DNA_scene_types.h"
64 #include "DNA_screen_types.h"
65 #include "DNA_space_types.h"
66 #include "DNA_texture_types.h"
67 #include "DNA_view3d_types.h"
68 #include "DNA_world_types.h"
69 #include "DNA_userdef_types.h"
70 #include "DNA_property_types.h"
71 #include "DNA_vfont_types.h"
72 #include "DNA_constraint_types.h"
74 #include "BKE_action.h"
75 #include "BKE_armature.h"
76 #include "BKE_blender.h"
77 #include "BKE_curve.h"
78 #include "BKE_constraint.h"
79 #include "BKE_depsgraph.h"
80 #include "BKE_displist.h"
81 #include "BKE_DerivedMesh.h"
82 #include "BKE_effect.h"
84 #include "BKE_global.h"
86 #include "BKE_lattice.h"
87 #include "BKE_mball.h"
89 #include "BKE_modifier.h"
90 #include "BKE_object.h"
91 #include "BKE_softbody.h"
92 #include "BKE_utildefines.h"
94 #include "BIF_editaction.h"
95 #include "BIF_editview.h"
96 #include "BIF_editlattice.h"
97 #include "BIF_editconstraint.h"
98 #include "BIF_editarmature.h"
99 #include "BIF_editmesh.h"
100 #include "BIF_editsima.h"
102 #include "BIF_poseobject.h"
103 #include "BIF_meshtools.h"
104 #include "BIF_mywindow.h"
105 #include "BIF_resources.h"
106 #include "BIF_screen.h"
107 #include "BIF_space.h"
108 #include "BIF_toolbox.h"
110 #include "BSE_view.h"
111 #include "BSE_edit.h"
112 #include "BSE_editipo.h"
113 #include "BSE_editipo_types.h"
115 #include "BDR_editobject.h" // reset_slowparents()
117 #include "BLI_arithb.h"
118 #include "BLI_blenlib.h"
119 #include "BLI_editVert.h"
123 #include "mydevice.h"
125 extern ListBase editNurb;
126 extern ListBase editelems;
128 #include "transform.h"
131 /* ************************** Functions *************************** */
133 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
134 TransData pivot = *head;
135 TransData *ihead = head;
136 TransData *itail = tail;
137 short connected = t->flag & T_PROP_CONNECTED;
142 while ((tail->dist >= pivot.dist) && (head < tail))
146 while ((tail->rdist >= pivot.rdist) && (head < tail))
157 while ((head->dist <= pivot.dist) && (head < tail))
161 while ((head->rdist <= pivot.rdist) && (head < tail))
174 qsort_trans_data(t, ihead, head-1);
177 qsort_trans_data(t, head+1, itail);
181 void sort_trans_data_dist(TransInfo *t) {
182 TransData *start = t->data;
185 while(i < t->total && start->flag & TD_SELECTED) {
189 qsort_trans_data(t, start, t->data + t->total - 1);
192 static void sort_trans_data(TransInfo *t)
194 TransData *sel, *unsel;
199 while (sel > unsel) {
200 while (unsel->flag & TD_SELECTED) {
206 while (!(sel->flag & TD_SELECTED)) {
220 /* distance calculated from not-selected vertex to nearest selected vertex
221 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
222 static void set_prop_dist(TransInfo *t, short with_dist)
227 for(a=0, tob= t->data; a<t->total; a++, tob++) {
229 tob->rdist= 0.0f; // init, it was mallocced
231 if((tob->flag & TD_SELECTED)==0) {
236 tob->rdist = -1.0f; // signal for next loop
238 for (i = 0, td= t->data; i < t->total; i++, td++) {
239 if(td->flag & TD_SELECTED) {
240 VecSubf(vec, tob->center, td->center);
241 Mat3MulVecfl(tob->mtx, vec);
242 dist = Normalise(vec);
243 if (tob->rdist == -1.0f) {
246 else if (dist < tob->rdist) {
250 else break; // by definition transdata has selected items in beginning
253 tob->dist = tob->rdist;
259 /* ************************** CONVERSIONS ************************* */
261 /* ********************* texture space ********* */
263 static void createTransTexspace(TransInfo *t)
272 if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
278 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
279 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
281 td->flag= TD_SELECTED;
282 VECCOPY(td->center, ob->obmat[3]);
285 Mat3CpyMat4(td->mtx, ob->obmat);
286 Mat3Inv(td->smtx, td->mtx);
288 if( GS(id->name)==ID_ME) {
290 me->texflag &= ~AUTOSPACE;
292 td->ext->rot= me->rot;
293 td->ext->size= me->size;
295 else if( GS(id->name)==ID_CU) {
297 cu->texflag &= ~CU_AUTOSPACE;
299 td->ext->rot= cu->rot;
300 td->ext->size= cu->size;
302 else if( GS(id->name)==ID_MB) {
303 MetaBall *mb= ob->data;
304 mb->texflag &= ~MB_AUTOSPACE;
306 td->ext->rot= mb->rot;
307 td->ext->size= mb->size;
310 VECCOPY(td->iloc, td->loc);
311 VECCOPY(td->ext->irot, td->ext->rot);
312 VECCOPY(td->ext->isize, td->ext->size);
315 /* ********************* edge (for crease) ***** */
317 static void createTransEdge(TransInfo *t) {
318 TransData *td = NULL;
319 EditMesh *em = G.editMesh;
321 float mtx[3][3], smtx[3][3];
322 int count=0, countsel=0;
323 int propmode = t->flag & T_PROP_EDIT;
325 for(eed= em->edges.first; eed; eed= eed->next) {
327 if (eed->f & SELECT) countsel++;
328 if (propmode) count++;
342 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
344 Mat3CpyMat4(mtx, G.obedit->obmat);
347 for(eed= em->edges.first; eed; eed= eed->next) {
348 if(eed->h==0 && (eed->f & SELECT || propmode)) {
349 /* need to set center for center calculations */
350 VecAddf(td->center, eed->v1->co, eed->v2->co);
351 VecMulf(td->center, 0.5f);
355 td->flag= TD_SELECTED;
360 Mat3CpyMat3(td->smtx, smtx);
361 Mat3CpyMat3(td->mtx, mtx);
365 td->val = &(eed->crease);
366 td->ival = eed->crease;
373 /* ********************* pose mode ************* */
375 /* recursive, make sure it's identical structured as next one */
376 /* only counts the parent selection, and tags transform flag */
377 /* exported for manipulator */
378 void count_bone_select(TransInfo *t, ListBase *lb, int do_it)
383 for(bone= lb->first; bone; bone= bone->next) {
384 bone->flag &= ~BONE_TRANSFORM;
387 if (bone->flag & BONE_SELECTED) {
388 /* We don't let connected children get "grabbed" */
389 if ( (t->mode!=TFM_TRANSLATION) || (bone->flag & BONE_CONNECTED)==0 ) {
390 bone->flag |= BONE_TRANSFORM;
392 do_next= 0; // no transform on children if one parent bone is selected
396 count_bone_select(t, &bone->childbase, do_next);
400 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
402 bConstraint *con= pchan->constraints.first;
404 for(;con; con= con->next) {
405 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
406 bKinematicConstraint *data= con->data;
410 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
417 static void apply_targetless_ik(Object *ob)
419 bPoseChannel *pchan, *parchan, *chanlist[256];
420 bKinematicConstraint *data;
423 /* now we got a difficult situation... we have to find the
424 target-less IK pchans, and apply transformation to the all
425 pchans that were in the chain */
427 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
428 data= has_targetless_ik(pchan);
429 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
431 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
434 /* exclude tip from chain? */
435 if(!(data->flag & CONSTRAINT_IK_TIP))
436 parchan= pchan->parent;
440 /* Find the chain's root & count the segments needed */
441 for (; parchan; parchan=parchan->parent){
442 chanlist[segcount]= parchan;
445 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
447 for(;segcount;segcount--) {
449 float rmat[4][4], tmat[4][4], imat[4][4];
451 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
452 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
453 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
454 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
456 parchan= chanlist[segcount-1];
458 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
460 if(parchan->parent) {
461 Bone *parbone= parchan->parent->bone;
462 float offs_bone[4][4];
464 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
465 Mat4CpyMat3(offs_bone, bone->bone_mat);
467 /* The bone's root offset (is in the parent's coordinate system) */
468 VECCOPY(offs_bone[3], bone->head);
470 /* Get the length translation of parent (length along y axis) */
471 offs_bone[3][1]+= parbone->length;
473 /* pose_mat(b-1) * offs_bone */
474 if(parchan->bone->flag & BONE_HINGE) {
475 /* the rotation of the parent restposition */
476 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
478 /* the location of actual parent transform */
479 VECCOPY(rmat[3], offs_bone[3]);
480 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
481 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
483 Mat4MulMat4(tmat, offs_bone, rmat);
486 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
488 Mat4Invert(imat, tmat);
491 Mat4CpyMat3(tmat, bone->bone_mat);
493 VECCOPY(tmat[3], bone->head);
494 Mat4Invert(imat, tmat);
497 Mat4MulMat4(rmat, parchan->pose_mat, imat);
499 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
501 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
503 Mat3CpyMat4(rmat3, rmat);
506 Mat3ToQuat(rmat3, parchan->quat);
508 /* for size, remove rotation */
509 QuatToMat3(parchan->quat, qmat);
511 Mat3MulMat3(smat, rmat3, imat);
512 Mat3ToSize(smat, parchan->size);
514 VECCOPY(parchan->loc, rmat[3]);
519 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];
531 VECCOPY(vec, pchan->pose_mat[3]);
532 VECCOPY(td->center, vec);
535 td->flag= TD_SELECTED|TD_USEQUAT;
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 the parent transform + own transform */
549 Mat3CpyMat4(omat, ob->obmat);
551 if(pchan->bone->flag & BONE_HINGE)
552 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
554 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
556 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
559 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // huh, transposed?
562 Mat3Inv (td->smtx, td->mtx);
564 /* for axismat we use bone's own transform */
565 Mat3CpyMat4(pmat, pchan->pose_mat);
566 Mat3MulMat3(td->axismtx, omat, pmat);
567 Mat3Ortho(td->axismtx);
569 if(t->mode==TFM_BONESIZE) {
570 bArmature *arm= t->poseobj->data;
572 if(arm->drawtype==ARM_ENVELOPE) {
574 td->val= &bone->dist;
575 td->ival= bone->dist;
578 // abusive storage of scale in the loc pointer :)
579 td->loc= &bone->xwidth;
580 VECCOPY (td->iloc, td->loc);
585 /* in this case we can do target-less IK grabbing */
586 if(t->mode==TFM_TRANSLATION) {
587 bKinematicConstraint *data= has_targetless_ik(pchan);
589 if(data->flag & CONSTRAINT_IK_TIP) {
590 VECCOPY(data->grabtarget, pchan->pose_tail);
593 VECCOPY(data->grabtarget, pchan->pose_head);
595 td->loc = data->grabtarget;
596 VECCOPY(td->iloc, td->loc);
597 data->flag |= CONSTRAINT_IK_AUTO;
599 /* only object matrix correction */
600 Mat3CpyMat3 (td->mtx, omat);
601 Mat3Inv (td->smtx, td->mtx);
606 static void bone_children_clear_transflag(ListBase *lb)
608 Bone *bone= lb->first;
610 for(;bone;bone= bone->next) {
611 bone->flag &= ~BONE_TRANSFORM;
612 bone_children_clear_transflag(&bone->childbase);
616 /* sets transform flags in the bones, returns total */
617 static void set_pose_transflags(TransInfo *t, Object *ob)
624 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
626 if(bone->flag & BONE_SELECTED)
627 bone->flag |= BONE_TRANSFORM;
629 bone->flag &= ~BONE_TRANSFORM;
632 /* make sure no bone can be transformed when a parent is transformed */
633 /* since pchans are depsgraph sorted, the parents are in beginning of list */
634 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
636 if(bone->flag & BONE_TRANSFORM)
637 bone_children_clear_transflag(&bone->childbase);
640 /* now count, and check if we have autoIK or have to switch from translate to rotate */
641 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
643 if(bone->flag & BONE_TRANSFORM) {
646 if(t->mode==TFM_TRANSLATION) {
647 if( has_targetless_ik(pchan)==NULL ) {
648 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
649 t->mode= TFM_ROTATION;
650 else if((pchan->protectflag & OB_LOCK_LOC)==OB_LOCK_LOC)
651 t->mode= TFM_ROTATION;
658 /* frees temporal IKs */
659 static void pose_grab_with_ik_clear(Object *ob)
661 bKinematicConstraint *data;
665 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
666 for(con= pchan->constraints.first; con; con= con->next) {
667 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
669 if(data->flag & CONSTRAINT_IK_TEMP) {
670 BLI_remlink(&pchan->constraints, con);
671 MEM_freeN(con->data);
673 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
681 /* adds the IK to pchan */
682 static void pose_grab_with_ik_add(bPoseChannel *pchan)
684 bKinematicConstraint *data;
687 /* rule: not if there's already an IK on this channel */
688 for(con= pchan->constraints.first; con; con= con->next)
689 if(con->type==CONSTRAINT_TYPE_KINEMATIC)
693 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
694 data= has_targetless_ik(pchan);
696 data->flag |= CONSTRAINT_IK_AUTO;
700 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
701 BLI_addtail(&pchan->constraints, con);
702 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
704 data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
705 VECCOPY(data->grabtarget, pchan->pose_tail);
708 /* we include only a connected chain */
709 while(pchan && (pchan->bone->flag & BONE_CONNECTED)) {
711 pchan= pchan->parent;
715 /* bone is a canditate to get IK, but we don't do it if it has children connected */
716 static void pose_grab_with_ik_children(bPose *pose, Bone *bone)
721 /* go deeper if children & children are connected */
722 for(bonec= bone->childbase.first; bonec; bonec= bonec->next) {
723 if(bonec->flag & BONE_CONNECTED) {
725 pose_grab_with_ik_children(pose, bonec);
729 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
731 pose_grab_with_ik_add(pchan);
735 /* main call which adds temporal IK chains */
736 static void pose_grab_with_ik(Object *ob)
738 bPoseChannel *pchan, *pchansel= NULL;
740 if(ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0)
743 /* rule: only one Bone */
744 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
745 if(pchan->bone->flag & BONE_SELECTED) {
751 if(pchan || pchansel==NULL) return;
753 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
754 if(pchansel->parent) {
755 /* only adds if there's no IK yet */
756 pose_grab_with_ik_add(pchansel);
759 /* rule: go over the children and add IK to the tips */
760 pose_grab_with_ik_children(ob->pose, pchansel->bone);
766 /* only called with pose mode active object now */
767 static void createTransPose(TransInfo *t, Object *ob)
772 TransDataExtension *tdx;
777 /* check validity of state */
778 arm=get_armature (ob);
779 if (arm==NULL || ob->pose==NULL) return;
781 if (arm->flag & ARM_RESTPOS) {
782 if(t->mode!=TFM_BONESIZE) {
783 notice ("Pose edit not possible while Rest Position is enabled");
787 if (!(ob->lay & G.vd->lay)) return;
789 /* do we need to add temporal IK chains? */
790 if((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION)
791 pose_grab_with_ik(ob);
793 /* set flags and count total (warning, can change transform to rotate) */
794 set_pose_transflags(t, ob);
796 if(t->total==0) return;
799 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
801 /* make sure the lock is set OK, unlock can be accidentally saved? */
802 ob->pose->flag |= POSE_LOCKED;
803 ob->pose->flag &= ~POSE_DO_UNLOCK;
805 /* init trans data */
806 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
807 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
808 for(i=0; i<t->total; i++, td++, tdx++) {
814 /* use pose channels to fill trans data */
816 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
817 if(pchan->bone->flag & BONE_TRANSFORM) {
818 add_pose_transdata(t, pchan, ob, td);
823 if(td != (t->data+t->total)) printf("Bone selection count error\n");
827 /* ********************* armature ************** */
829 static void createTransArmatureVerts(TransInfo *t)
832 bArmature *arm= G.obedit->data;
834 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
837 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
838 if (t->mode==TFM_BONESIZE) {
839 if (ebo->flag & BONE_SELECTED)
843 if (ebo->flag & BONE_TIPSEL)
845 if (ebo->flag & BONE_ROOTSEL)
850 if (!t->total) return;
852 Mat3CpyMat4(mtx, G.obedit->obmat);
855 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
857 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
859 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
861 if (t->mode==TFM_BONE_ENVELOPE) {
863 if (ebo->flag & BONE_ROOTSEL){
864 td->val= &ebo->rad_head;
867 VECCOPY (td->center, ebo->head);
868 td->flag= TD_SELECTED;
870 Mat3CpyMat3(td->smtx, smtx);
871 Mat3CpyMat3(td->mtx, mtx);
879 if (ebo->flag & BONE_TIPSEL){
880 td->val= &ebo->rad_tail;
882 VECCOPY (td->center, ebo->tail);
883 td->flag= TD_SELECTED;
885 Mat3CpyMat3(td->smtx, smtx);
886 Mat3CpyMat3(td->mtx, mtx);
896 else if (t->mode==TFM_BONESIZE) {
897 if (ebo->flag & BONE_SELECTED) {
898 if(arm->drawtype==ARM_ENVELOPE) {
904 // abusive storage of scale in the loc pointer :)
905 td->loc= &ebo->xwidth;
906 VECCOPY (td->iloc, td->loc);
909 VECCOPY (td->center, ebo->head);
910 td->flag= TD_SELECTED;
912 /* use local bone matrix */
913 VecSubf(delta, ebo->tail, ebo->head);
914 vec_roll_to_mat3(delta, ebo->roll, bonemat);
915 Mat3MulMat3(td->mtx, mtx, bonemat);
916 Mat3Inv(td->smtx, td->mtx);
918 Mat3CpyMat3(td->axismtx, td->mtx);
919 Mat3Ortho(td->axismtx);
928 if (ebo->flag & BONE_TIPSEL){
929 VECCOPY (td->iloc, ebo->tail);
930 VECCOPY (td->center, td->iloc);
932 td->flag= TD_SELECTED;
934 Mat3CpyMat3(td->smtx, smtx);
935 Mat3CpyMat3(td->mtx, mtx);
943 if (ebo->flag & BONE_ROOTSEL){
944 VECCOPY (td->iloc, ebo->head);
945 VECCOPY (td->center, td->iloc);
947 td->flag= TD_SELECTED;
949 Mat3CpyMat3(td->smtx, smtx);
950 Mat3CpyMat3(td->mtx, mtx);
962 /* ********************* meta elements ********* */
964 static void createTransMBallVerts(TransInfo *t)
968 TransDataExtension *tx;
969 float mtx[3][3], smtx[3][3];
970 int count=0, countsel=0;
971 int propmode = t->flag & T_PROP_EDIT;
974 for(ml= editelems.first; ml; ml= ml->next) {
975 if(ml->flag & SELECT) countsel++;
976 if(propmode) count++;
979 /* note: in prop mode we need at least 1 selected */
980 if (countsel==0) return;
982 if(propmode) t->total = count;
983 else t->total = countsel;
985 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
986 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
988 Mat3CpyMat4(mtx, G.obedit->obmat);
991 for(ml= editelems.first; ml; ml= ml->next) {
992 if(propmode || (ml->flag & SELECT)) {
994 VECCOPY(td->iloc, td->loc);
995 VECCOPY(td->center, td->loc);
997 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
998 else td->flag= TD_USEQUAT;
1000 Mat3CpyMat3(td->smtx, smtx);
1001 Mat3CpyMat3(td->mtx, mtx);
1006 /* Radius of MetaElem (mass of MetaElem influence) */
1007 if(ml->flag & MB_SCALE_RAD){
1016 /* expx/expy/expz determine "shape" of some MetaElem types */
1017 tx->size = &ml->expx;
1018 tx->isize[0] = ml->expx;
1019 tx->isize[1] = ml->expy;
1020 tx->isize[2] = ml->expz;
1022 /* quat is used for rotation of MetaElem */
1023 tx->quat = ml->quat;
1024 QUATCOPY(tx->iquat, ml->quat);
1034 /* ********************* curve/surface ********* */
1036 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1037 TransData *td, *td_near = NULL;
1038 for (td = head; td<=tail; td++) {
1039 if (td->flag & TD_SELECTED) {
1045 dist = VecLenf(td_near->center, td->center);
1046 if (dist < (td-1)->dist) {
1047 td->dist = (td-1)->dist;
1054 td->dist = MAXFLOAT;
1055 td->flag |= TD_NOTCONNECTED;
1059 for (td = tail; td>=head; td--) {
1060 if (td->flag & TD_SELECTED) {
1066 dist = VecLenf(td_near->center, td->center);
1067 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1068 td->flag &= ~TD_NOTCONNECTED;
1069 if (dist < (td+1)->dist) {
1070 td->dist = (td+1)->dist;
1080 static void createTransCurveVerts(TransInfo *t)
1082 TransData *td = NULL;
1086 float mtx[3][3], smtx[3][3];
1088 int count=0, countsel=0;
1089 int propmode = t->flag & T_PROP_EDIT;
1091 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1092 for(nu= editNurb.first; nu; nu= nu->next) {
1093 if((nu->type & 7)==CU_BEZIER) {
1094 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1096 if(bezt->f1 & 1) countsel++;
1097 if(bezt->f2 & 1) countsel++;
1098 if(bezt->f3 & 1) countsel++;
1099 if(propmode) count+= 3;
1104 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1106 if(propmode) count++;
1107 if(bp->f1 & 1) countsel++;
1112 /* note: in prop mode we need at least 1 selected */
1113 if (countsel==0) return;
1115 if(propmode) t->total = count;
1116 else t->total = countsel;
1117 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1119 Mat3CpyMat4(mtx, G.obedit->obmat);
1123 for(nu= editNurb.first; nu; nu= nu->next) {
1124 if((nu->type & 7)==CU_BEZIER) {
1125 TransData *head, *tail;
1127 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1129 if(propmode || (bezt->f1 & 1)) {
1130 VECCOPY(td->iloc, bezt->vec[0]);
1131 td->loc= bezt->vec[0];
1132 VECCOPY(td->center, bezt->vec[1]);
1133 if(bezt->f1 & 1) td->flag= TD_SELECTED;
1139 Mat3CpyMat3(td->smtx, smtx);
1140 Mat3CpyMat3(td->mtx, mtx);
1146 /* THIS IS THE CV, the other two are handles */
1147 if(propmode || (bezt->f2 & 1)) {
1148 VECCOPY(td->iloc, bezt->vec[1]);
1149 td->loc= bezt->vec[1];
1150 VECCOPY(td->center, td->loc);
1151 if(bezt->f2 & 1) td->flag= TD_SELECTED;
1155 td->val = &(bezt->alfa);
1156 td->ival = bezt->alfa;
1158 Mat3CpyMat3(td->smtx, smtx);
1159 Mat3CpyMat3(td->mtx, mtx);
1165 if(propmode || (bezt->f3 & 1)) {
1166 VECCOPY(td->iloc, bezt->vec[2]);
1167 td->loc= bezt->vec[2];
1168 VECCOPY(td->center, bezt->vec[1]);
1169 if(bezt->f3 & 1) td->flag= TD_SELECTED;
1175 Mat3CpyMat3(td->smtx, smtx);
1176 Mat3CpyMat3(td->mtx, mtx);
1183 else if (propmode && head != tail) {
1184 calc_distanceCurveVerts(head, tail-1);
1188 if (propmode && head != tail)
1189 calc_distanceCurveVerts(head, tail-1);
1192 TransData *head, *tail;
1194 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1196 if(propmode || (bp->f1 & 1)) {
1197 VECCOPY(td->iloc, bp->vec);
1199 VECCOPY(td->center, td->loc);
1200 if(bp->f1 & 1) td->flag= TD_SELECTED;
1204 td->val = &(bp->alfa);
1205 td->ival = bp->alfa;
1207 Mat3CpyMat3(td->smtx, smtx);
1208 Mat3CpyMat3(td->mtx, mtx);
1215 else if (propmode && head != tail) {
1216 calc_distanceCurveVerts(head, tail-1);
1220 if (propmode && head != tail)
1221 calc_distanceCurveVerts(head, tail-1);
1226 /* ********************* lattice *************** */
1228 static void createTransLatticeVerts(TransInfo *t)
1230 TransData *td = NULL;
1232 float mtx[3][3], smtx[3][3];
1234 int count=0, countsel=0;
1235 int propmode = t->flag & T_PROP_EDIT;
1238 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1241 if(bp->f1 & 1) countsel++;
1242 if(propmode) count++;
1247 /* note: in prop mode we need at least 1 selected */
1248 if (countsel==0) return;
1250 if(propmode) t->total = count;
1251 else t->total = countsel;
1252 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1254 Mat3CpyMat4(mtx, G.obedit->obmat);
1259 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1261 if(propmode || (bp->f1 & 1)) {
1263 VECCOPY(td->iloc, bp->vec);
1265 VECCOPY(td->center, td->loc);
1266 if(bp->f1 & 1) td->flag= TD_SELECTED;
1268 Mat3CpyMat3(td->smtx, smtx);
1269 Mat3CpyMat3(td->mtx, mtx);
1283 /* ********************* mesh ****************** */
1285 /* proportional distance based on connectivity */
1286 #define E_VEC(a) (vectors + (3 * (int)(a)->vn))
1287 #define E_NEAR(a) (nears[((int)(a)->vn)])
1288 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1290 EditMesh *em = G.editMesh;
1295 /* f2 flag is used for 'selection' */
1296 /* vn is offset on scratch array */
1297 for(eve= em->verts.first; eve; eve= eve->next) {
1299 eve->vn = (EditVert *)(i++);
1301 if(eve->f & SELECT) {
1304 E_VEC(eve)[0] = 0.0f;
1305 E_VEC(eve)[1] = 0.0f;
1306 E_VEC(eve)[2] = 0.0f;
1315 /* Floodfill routine */
1317 At worst this is n*n of complexity where n is number of edges
1318 Best case would be n if the list is ordered perfectly.
1319 Estimate is n log n in average (so not too bad)
1324 for(eed= em->edges.first; eed; eed= eed->next) {
1326 EditVert *v1= eed->v1, *v2= eed->v2;
1327 float *vec2 = E_VEC(v2);
1328 float *vec1 = E_VEC(v1);
1330 if (v1->f2 + v2->f2 == 4)
1336 float len1 = VecLength(vec1);
1337 float len2 = VecLength(vec2);
1339 /* for v2 if not selected */
1341 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1342 lenn = VecLength(nvec);
1343 if (lenn - len1 > 0.00001f && len2 - lenn > 0.00001f) {
1344 VECCOPY(vec2, nvec);
1345 E_NEAR(v2) = E_NEAR(v1);
1348 else if (len2 - len1 > 0.00001f && len1 - lenn > 0.00001f) {
1349 VECCOPY(vec2, vec1);
1350 E_NEAR(v2) = E_NEAR(v1);
1354 /* for v1 if not selected */
1356 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1357 lenn = VecLength(nvec);
1358 if (lenn - len2 > 0.00001f && len1 - lenn > 0.00001f) {
1359 VECCOPY(vec1, nvec);
1360 E_NEAR(v1) = E_NEAR(v2);
1363 else if (len1 - len2 > 0.00001f && len2 - lenn > 0.00001f) {
1364 VECCOPY(vec1, vec2);
1365 E_NEAR(v1) = E_NEAR(v2);
1372 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1373 if (VecLength(vec1) - VecLength(vec2) > 0.00001f) {
1374 VECCOPY(vec2, vec1);
1376 E_NEAR(v2) = E_NEAR(v1);
1382 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1383 if (VecLength(vec2) - VecLength(vec1) > 0.00001f) {
1384 VECCOPY(vec1, vec2);
1386 E_NEAR(v1) = E_NEAR(v2);
1394 static void VertsToTransData(TransData *td, EditVert *eve)
1398 VECCOPY(td->center, td->loc);
1399 VECCOPY(td->iloc, td->loc);
1402 VECCOPY(td->axismtx[2], eve->no);
1408 td->axismtx[1][2] = 0.0f;
1416 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1418 float *vec = userData;
1424 static float *get_mapped_editverts(void)
1427 DerivedMesh *dm= editmesh_get_derived_cage(&needsFree);
1430 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1432 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1434 if (needsFree) dm->release(dm);
1438 /* helper for below, interpolates or assigns and increments */
1439 static float *crazy_quat_blend(EditVert *eve, float *quat)
1442 eve->vn= (EditVert *)quat;
1443 QUATCOPY(quat+4, quat);
1447 float *q1= (float *)eve->vn;
1448 QuatInterpol(q1, q1, quat, 0.5f);
1453 static void set_crazyspace_quats(float *mappedcos, float *quats)
1455 EditMesh *em = G.editMesh;
1456 EditVert *eve, *prev;
1459 float *v1, *v2, *v3, *quatp;
1462 /* 2 abused locations in vertices */
1463 for(eve= em->verts.first; eve; eve= eve->next, index++) {
1465 eve->prev= (EditVert *)index;
1469 for(efa= em->faces.first; efa; efa= efa->next) {
1470 /* vertex f1 flags were set for transform */
1472 if( (efa->v1->f1 && efa->v1->vn==NULL) || (efa->v2->f1 && efa->v2->vn==NULL)
1473 || (efa->v3->f1 && efa->v3->vn==NULL) || (efa->v4 && efa->v4->f1 && efa->v4->vn==NULL) ) {
1475 triatoquat(efa->v1->co, efa->v2->co, efa->v3->co, q1);
1477 /* retrieve mapped coordinates */
1478 v1= mappedcos + 3*( (int)(efa->v1->prev) );
1479 v2= mappedcos + 3*( (int)(efa->v2->prev) );
1480 v3= mappedcos + 3*( (int)(efa->v3->prev) );
1481 triatoquat(v1, v2, v3, q2);
1483 QuatSub(quatp, q2, q1);
1485 if(efa->v1->f1) quatp= crazy_quat_blend(efa->v1, quatp);
1486 if(efa->v2->f1) quatp= crazy_quat_blend(efa->v2, quatp);
1487 if(efa->v3->f1) quatp= crazy_quat_blend(efa->v3, quatp);
1488 if(efa->v4 && efa->v4->f1) quatp= crazy_quat_blend(efa->v4, quatp);
1492 /* restore abused prev pointer */
1493 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1498 static void createTransEditVerts(TransInfo *t)
1500 TransData *tob = NULL;
1501 EditMesh *em = G.editMesh;
1503 EditVert **nears = NULL;
1504 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1505 float mtx[3][3], smtx[3][3];
1506 int count=0, countsel=0;
1507 int propmode = t->flag & T_PROP_EDIT;
1508 int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR);
1510 // transform now requires awareness for select mode, so we tag the f1 flags in verts
1511 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1512 for(eve= em->verts.first; eve; eve= eve->next) {
1513 if(eve->h==0 && (eve->f & SELECT))
1519 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1521 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1522 for(eed= em->edges.first; eed; eed= eed->next) {
1523 if(eed->h==0 && (eed->f & SELECT))
1524 eed->v1->f1= eed->v2->f1= SELECT;
1529 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1530 for(efa= em->faces.first; efa; efa= efa->next) {
1531 if(efa->h==0 && (efa->f & SELECT)) {
1532 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1533 if(efa->v4) efa->v4->f1= SELECT;
1538 /* now we can count */
1539 for(eve= em->verts.first; eve; eve= eve->next) {
1541 if(eve->f1) countsel++;
1542 if(propmode) count++;
1546 /* note: in prop mode we need at least 1 selected */
1547 if (countsel==0) return;
1552 /* allocating scratch arrays */
1553 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1554 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1556 else t->total = countsel;
1557 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1559 Mat3CpyMat4(mtx, G.obedit->obmat);
1562 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1564 /* detect CrazySpace [tm] */
1566 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1567 if(modifiers_isDeformed(G.obedit)) {
1568 mappedcos= get_mapped_editverts();
1569 /* add one more quaternion, because of crazy_quat_blend */
1570 quats= MEM_mallocN( (t->total+1)*sizeof(float)*4, "crazy quats");
1571 set_crazyspace_quats(mappedcos, quats);
1576 /* find out which half we do */
1578 for (eve=em->verts.first; eve; eve=eve->next) {
1579 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1587 for (eve=em->verts.first; eve; eve=eve->next) {
1589 if(propmode || eve->f1) {
1590 VertsToTransData(tob, eve);
1592 if(eve->f1) tob->flag |= TD_SELECTED;
1596 VECCOPY(vec, E_VEC(eve));
1597 Mat3MulVecfl(mtx, vec);
1598 tob->dist= VecLength(vec);
1601 tob->flag |= TD_NOTCONNECTED;
1602 tob->dist = MAXFLOAT;
1607 if(quats && eve->vn) {
1608 float mat[3][3], imat[3][3], qmat[3][3];
1610 QuatToMat3((float *)eve->vn, qmat);
1611 Mat3MulMat3(mat, mtx, qmat);
1614 Mat3CpyMat3(tob->smtx, imat);
1615 Mat3CpyMat3(tob->mtx, mat);
1618 Mat3CpyMat3(tob->smtx, smtx);
1619 Mat3CpyMat3(tob->mtx, mtx);
1623 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1624 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
1625 if(vmir!=eve) tob->tdmir= vmir;
1635 /* crazy space free */
1637 MEM_freeN(mappedcos);
1642 /* ********************* UV ****************** */
1644 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1648 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1650 /* uv coords are scaled by aspects. this is needed for rotations and
1651 proportional editing to be consistent with the stretchted uv coords
1652 that are displayed. this also means that for display and numinput,
1653 and when the the uv coords are flushed, these are converted each time */
1654 td2d->loc[0] = uv[0]*aspx;
1655 td2d->loc[1] = uv[1]*aspy;
1656 td2d->loc[2] = 0.0f;
1660 td->loc = td2d->loc;
1661 VECCOPY(td->center, td->loc);
1662 VECCOPY(td->iloc, td->loc);
1664 memset(td->axismtx, 0, sizeof(td->axismtx));
1665 td->axismtx[2][2] = 1.0f;
1667 td->ext= NULL; td->tdi= NULL; td->val= NULL;
1670 td->flag |= TD_SELECTED;
1680 static void createTransUVs(TransInfo *t)
1682 TransData *td = NULL;
1683 TransData2D *td2d = NULL;
1687 int a, count=0, countsel=0;
1688 int propmode = t->flag & T_PROP_EDIT;
1690 if(is_uv_tface_editing_allowed()==0) return;
1691 me= get_mesh(OBACT);
1696 for(a=me->totface; a>0; a--, tf++, mf++) {
1697 if(mf->v3 && tf->flag & TF_SELECT) {
1698 if(tf->flag & TF_SEL1) countsel++;
1699 if(tf->flag & TF_SEL2) countsel++;
1700 if(tf->flag & TF_SEL3) countsel++;
1701 if(mf->v4 && (tf->flag & TF_SEL4)) countsel++;
1703 count += (mf->v4)? 4: 3;
1707 /* note: in prop mode we need at least 1 selected */
1708 if (countsel==0) return;
1710 t->total= (propmode)? count: countsel;
1711 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1712 /* for each 2d uv coord a 3d vector is allocated, so that they can be
1713 treated just as if they were 3d verts */
1714 t->data2d= MEM_mallocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1716 if(G.sima->flag & SI_CLIP_UV)
1717 t->flag |= T_CLIP_UV;
1723 for(a=me->totface; a>0; a--, tf++, mf++) {
1724 if(mf->v3 && tf->flag & TF_SELECT) {
1725 if(tf->flag & TF_SEL1 || propmode)
1726 UVsToTransData(td++, td2d++, tf->uv[0], (tf->flag & TF_SEL1));
1727 if(tf->flag & TF_SEL2 || propmode)
1728 UVsToTransData(td++, td2d++, tf->uv[1], (tf->flag & TF_SEL2));
1729 if(tf->flag & TF_SEL3 || propmode)
1730 UVsToTransData(td++, td2d++, tf->uv[2], (tf->flag & TF_SEL3));
1732 if(mf->v4 && (tf->flag & TF_SEL4 || propmode))
1733 UVsToTransData(td++, td2d++, tf->uv[3], (tf->flag & TF_SEL4));
1737 if (G.sima->flag & SI_LSCM_LIVE)
1738 unwrap_lscm_live_begin();
1741 void flushTransUVs(TransInfo *t)
1744 int a, width, height;
1746 Mesh *me= get_mesh(ob);
1747 float aspx, aspy, invx, invy;
1749 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1750 transform_width_height_tface_uv(&width, &height);
1754 /* flush to 2d vector from internally used 3d vector */
1755 for(a=0, td= t->data2d; a<t->total; a++, td++) {
1756 td->loc2d[0]= td->loc[0]*invx;
1757 td->loc2d[1]= td->loc[1]*invy;
1759 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1760 td->loc2d[0]= floor(width*td->loc2d[0])/width;
1761 td->loc2d[1]= floor(height*td->loc2d[1])/height;
1765 if((G.sima->flag & SI_BE_SQUARE) && (t->state != TRANS_CANCEL))
1766 be_square_tface_uv(me);
1768 /* this is overkill if G.sima->lock is not set, but still needed */
1769 object_uvs_changed(ob);
1772 int clipUVTransform(TransInfo *t, float *vec, int resize)
1775 int a, clipx=1, clipy=1;
1776 float aspx, aspy, min[2], max[2];
1778 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1779 min[0]= min[1]= 0.0f;
1780 max[0]= aspx; max[1]= aspy;
1782 for(a=0, td= t->data; a<t->total; a++, td++) {
1783 DO_MINMAX2(td->loc, min, max);
1787 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1788 vec[0] *= t->center[0]/(t->center[0] - min[0]);
1789 else if(max[0] > aspx && t->center[0] < aspx)
1790 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
1794 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
1795 vec[1] *= t->center[1]/(t->center[1] - min[1]);
1796 else if(max[1] > aspy && t->center[1] < aspy)
1797 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
1804 else if(max[0] > aspx)
1805 vec[0] -= max[0]-aspx;
1811 else if(max[1] > aspy)
1812 vec[1] -= max[1]-aspy;
1817 return (clipx || clipy);
1820 /* **************** IpoKey stuff, for Object TransData ********** */
1822 /* storage of bezier triple. thats why -3 and +3! */
1823 static void set_tdi_old(float *old, float *poin)
1830 /* while transforming */
1831 void add_tdi_poin(float *poin, float *old, float delta)
1834 poin[0]= old[0]+delta;
1835 poin[-3]= old[3]+delta;
1836 poin[3]= old[6]+delta;
1840 /* fill ipokey transdata with old vals and pointers */
1841 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1843 extern int ob_ar[]; // blenkernel ipo.c
1844 TransDataIpokey *tdi= td->tdi;
1848 td->val= NULL; // is read on ESC
1850 for(a=0; a<OB_TOTIPO; a++) {
1854 switch( ob_ar[a] ) {
1857 tdi->locx= &(bezt->vec[1][1]); break;
1860 tdi->locy= &(bezt->vec[1][1]); break;
1863 tdi->locz= &(bezt->vec[1][1]); break;
1868 tdi->rotx= &(bezt->vec[1][1]); break;
1872 tdi->roty= &(bezt->vec[1][1]); break;
1876 tdi->rotz= &(bezt->vec[1][1]); break;
1880 tdi->sizex= &(bezt->vec[1][1]); break;
1883 tdi->sizey= &(bezt->vec[1][1]); break;
1886 tdi->sizez= &(bezt->vec[1][1]); break;
1891 /* oldvals for e.g. undo */
1892 if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
1893 if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
1894 if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
1896 /* remember, for mapping curves ('1'=10 degrees) */
1897 if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
1898 if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
1899 if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
1901 /* this is not allowed to be dsize! */
1902 if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
1903 if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
1904 if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
1907 if(delta) tdi->flag |= TOB_IPODROT;
1911 /* *************************** Object Transform data ******************* */
1913 static void ObjectToTransData(TransData *td, Object *ob)
1917 void *cfirst, *clast;
1919 /* set axismtx BEFORE clearing constraints to have the real orientation */
1920 Mat3CpyMat4(td->axismtx, ob->obmat);
1921 Mat3Ortho(td->axismtx);
1923 /* then why are constraints and track disabled here?
1924 they dont alter loc/rot/size itself (ton) */
1925 cfirst = ob->constraints.first;
1926 clast = ob->constraints.last;
1927 ob->constraints.first=ob->constraints.last=NULL;
1932 where_is_object(ob);
1936 ob->constraints.first = cfirst;
1937 ob->constraints.last = clast;
1942 VECCOPY(td->iloc, td->loc);
1944 td->ext->rot = ob->rot;
1945 VECCOPY(td->ext->irot, ob->rot);
1946 VECCOPY(td->ext->drot, ob->drot);
1948 td->ext->size = ob->size;
1949 VECCOPY(td->ext->isize, ob->size);
1950 VECCOPY(td->ext->dsize, ob->dsize);
1952 VECCOPY(td->center, ob->obmat[3]);
1956 float totmat[3][3], obinv[3][3];
1958 /* we calculate smtx without obmat: so a parmat */
1959 object_to_mat3(ob, obmtx);
1960 Mat3CpyMat4(totmat, ob->obmat);
1961 Mat3Inv(obinv, totmat);
1962 Mat3MulMat3(td->smtx, obmtx, obinv);
1963 Mat3Inv(td->mtx, td->smtx);
1973 /* sets flags in Bases to define whether they take part in transform */
1974 /* it deselects Bases, so we have to call the clear function always after */
1975 static void set_trans_object_base_flags(TransInfo *t)
1978 if Base selected and has parent selected:
1979 base->flag= BA_WAS_SEL
1983 /* makes sure base flags and object flags are identical */
1986 /* handle pending update events, otherwise they got copied below */
1987 for (base= FIRSTBASE; base; base= base->next) {
1988 if(base->object->recalc)
1989 object_handle_update(base->object);
1992 for (base= FIRSTBASE; base; base= base->next) {
1993 base->flag &= ~BA_WAS_SEL;
1995 if(TESTBASELIB(base)) {
1996 Object *ob= base->object;
1997 Object *parsel= ob->parent;
1999 /* if parent selected, deselect */
2001 if(parsel->flag & SELECT) break;
2002 parsel= parsel->parent;
2006 base->flag &= ~SELECT;
2007 base->flag |= BA_WAS_SEL;
2009 /* used for flush, depgraph will change recalcs if needed :) */
2010 ob->recalc |= OB_RECALC_OB;
2013 /* all recalc flags get flushed */
2014 DAG_scene_flush_update(G.scene, screen_view3d_layers());
2016 /* and we store them temporal in base (only used for transform code) */
2017 /* this because after doing updates, the object->recalc is cleared */
2018 for (base= FIRSTBASE; base; base= base->next) {
2019 if(base->object->recalc & OB_RECALC_OB)
2020 base->flag |= BA_HAS_RECALC_OB;
2021 if(base->object->recalc & OB_RECALC_DATA)
2022 base->flag |= BA_HAS_RECALC_DATA;
2026 static void clear_trans_object_base_flags(void)
2032 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2033 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2039 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
2040 /* note; transdata has been freed already! */
2041 void special_aftertrans_update(TransInfo *t)
2046 int cancelled= (t->state == TRANS_CANCEL);
2049 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2050 allqueue(REDRAWBUTSEDIT, 0);
2052 /* table needs to be created for each edit command, since vertices can move etc */
2053 mesh_octree_table(G.obedit, NULL, 'e');
2055 else if( (t->flag & T_POSE) && t->poseobj) {
2059 bPoseChannel *pchan;
2065 /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
2066 pose->flag |= POSE_DO_UNLOCK;
2068 /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
2069 if(!cancelled && t->mode==TFM_TRANSLATION)
2070 apply_targetless_ik(ob);
2072 /* not forget to clear the auto flag */
2073 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
2074 bKinematicConstraint *data= has_targetless_ik(pchan);
2075 if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
2079 if(t->mode==TFM_TRANSLATION)
2080 pose_grab_with_ik_clear(ob);
2082 /* automatic inserting of keys */
2083 if((G.flags & G_RECORDKEYS) && (!cancelled)) {
2087 act= ob->action= add_empty_action(ID_PO);
2089 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
2090 if (pchan->bone->flag & BONE_TRANSFORM){
2092 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2093 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2094 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2096 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2097 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2098 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2099 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2101 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2102 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2103 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2107 remake_action_ipos (act);
2108 allspace(REMAKEIPO, 0);
2109 allqueue(REDRAWACTION, 0);
2110 allqueue(REDRAWIPO, 0);
2111 allqueue(REDRAWNLA, 0);
2113 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2115 else if(arm->flag & ARM_DELAYDEFORM) {
2116 /* old optimize trick... this enforces to bypass the depgraph */
2117 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2118 ob->recalc= 0; // is set on OK position already by recalcData()
2121 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2123 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2124 allqueue(REDRAWBUTSEDIT, 0);
2131 if(base->flag & BA_DO_IPO) redrawipo= 1;
2135 if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
2137 /* Set autokey if necessary */
2138 if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){
2141 if(ob->ipoflag & OB_ACTION_OB)
2144 insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_X);
2145 insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Y);
2146 insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Z);
2148 insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_X);
2149 insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Y);
2150 insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Z);
2152 insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_X);
2153 insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Y);
2154 insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Z);
2156 remake_object_ipos (ob);
2157 allqueue(REDRAWIPO, 0);
2158 allspace(REMAKEIPO, 0);
2159 allqueue(REDRAWVIEW3D, 0);
2160 allqueue(REDRAWNLA, 0);
2168 clear_trans_object_base_flags();
2171 allqueue(REDRAWNLA, 0);
2172 allqueue(REDRAWACTION, 0);
2173 allqueue(REDRAWIPO, 0);
2176 reset_slowparents();
2178 /* note; should actually only be done for all objects when a lamp is moved... (ton) */
2179 if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
2180 reshadeall_displist();
2183 static void createTransObject(TransInfo *t)
2185 TransData *td = NULL;
2186 TransDataExtension *tx;
2192 set_trans_object_base_flags(t);
2195 for(base= FIRSTBASE; base; base= base->next) {
2196 if TESTBASELIB(base) {
2199 /* store ipo keys? */
2200 if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2201 elems.first= elems.last= NULL;
2202 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
2204 pushdata(&elems, sizeof(ListBase));
2206 for(ik= elems.first; ik; ik= ik->next) t->total++;
2208 if(elems.first==NULL) t->total++;
2217 /* clear here, main transform function escapes too */
2218 clear_trans_object_base_flags();
2222 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
2223 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
2225 for(base= FIRSTBASE; base; base= base->next) {
2226 if TESTBASELIB(base) {
2229 td->flag= TD_SELECTED;
2230 td->protectflag= ob->protectflag;
2233 /* store ipo keys? */
2234 if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2236 popfirst(&elems); // bring back pushed listbase
2242 base->flag |= BA_DO_IPO+BA_WAS_SEL;
2243 base->flag &= ~SELECT;
2246 set_no_parent_ipo(1);
2247 ipoflag= ob->ipoflag;
2248 ob->ipoflag &= ~OB_OFFS_OB;
2250 pushdata(ob->loc, 7*3*4); // tsk! tsk!
2252 for(ik= elems.first; ik; ik= ik->next) {
2254 /* weak... this doesn't correct for floating values, giving small errors */
2255 CFRA= (short)(ik->val/G.scene->r.framelen);
2258 ObjectToTransData(td, ob); // does where_is_object()
2260 td->flag= TD_SELECTED;
2262 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
2263 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
2264 ipokey_to_transdata(ik, td);
2268 if(ik->next) td->ext= tx; // prevent corrupting mem!
2270 free_ipokey(&elems);
2273 set_no_parent_ipo(0);
2275 CFRA= (short)cfraont;
2276 ob->ipoflag= ipoflag;
2278 where_is_object(ob); // restore
2281 ObjectToTransData(td, ob);
2289 ObjectToTransData(td, ob);
2299 void createTransData(TransInfo *t)
2303 if (t->context == CTX_TEXTURE) {
2304 t->flag |= T_TEXTURE;
2305 createTransTexspace(t);
2307 else if (t->context == CTX_EDGE) {
2311 if(t->data && t->flag & T_PROP_EDIT) {
2312 sort_trans_data(t); // makes selected become first in array
2313 set_prop_dist(t, 1);
2314 sort_trans_data_dist(t);
2317 else if (t->spacetype == SPACE_IMAGE) {
2318 t->flag |= T_POINTS|T_2D_EDIT;
2320 if(t->data && (t->flag & T_PROP_EDIT)) {
2321 sort_trans_data(t); // makes selected become first in array
2322 set_prop_dist(t, 1);
2323 sort_trans_data_dist(t);
2326 else if (G.obedit) {
2328 if (G.obedit->type == OB_MESH) {
2329 createTransEditVerts(t);
2331 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
2332 createTransCurveVerts(t);
2334 else if (G.obedit->type==OB_LATTICE) {
2335 createTransLatticeVerts(t);
2337 else if (G.obedit->type==OB_MBALL) {
2338 createTransMBallVerts(t);
2340 else if (G.obedit->type==OB_ARMATURE) {
2341 createTransArmatureVerts(t);
2344 printf("not done yet! only have mesh surface curve\n");
2347 if(t->data && t->flag & T_PROP_EDIT) {
2348 if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
2349 sort_trans_data(t); // makes selected become first in array
2350 set_prop_dist(t, 0);
2351 sort_trans_data_dist(t);
2354 sort_trans_data(t); // makes selected become first in array
2355 set_prop_dist(t, 1);
2356 sort_trans_data_dist(t);
2360 t->flag |= T_EDIT|T_POINTS;
2362 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
2363 if(t->mode==TFM_BONESIZE) {
2364 t->flag &= ~(T_EDIT|T_POINTS);
2366 t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
2369 else if (ob && (ob->flag & OB_POSEMODE)) {
2370 createTransPose(t, OBACT);
2372 else if (G.f & G_WEIGHTPAINT) {
2373 /* exception, we look for the one selected armature */
2375 for(base=FIRSTBASE; base; base= base->next) {
2376 if(TESTBASELIB(base)) {
2377 if(base->object->type==OB_ARMATURE)
2378 if(base->object->flag & OB_POSEMODE)
2383 createTransPose(t, base->object);
2387 createTransObject(t);
2388 t->flag |= T_OBJECT;
2391 if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
2392 t->flag |= T_CAMERA;