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()
116 #include "BDR_unwrapper.h"
118 #include "BLI_arithb.h"
119 #include "BLI_blenlib.h"
120 #include "BLI_editVert.h"
124 #include "mydevice.h"
126 extern ListBase editNurb;
127 extern ListBase editelems;
129 #include "transform.h"
132 /* ************************** Functions *************************** */
134 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
135 TransData pivot = *head;
136 TransData *ihead = head;
137 TransData *itail = tail;
138 short connected = t->flag & T_PROP_CONNECTED;
143 while ((tail->dist >= pivot.dist) && (head < tail))
147 while ((tail->rdist >= pivot.rdist) && (head < tail))
158 while ((head->dist <= pivot.dist) && (head < tail))
162 while ((head->rdist <= pivot.rdist) && (head < tail))
175 qsort_trans_data(t, ihead, head-1);
178 qsort_trans_data(t, head+1, itail);
182 void sort_trans_data_dist(TransInfo *t) {
183 TransData *start = t->data;
186 while(i < t->total && start->flag & TD_SELECTED) {
190 qsort_trans_data(t, start, t->data + t->total - 1);
193 static void sort_trans_data(TransInfo *t)
195 TransData *sel, *unsel;
200 while (sel > unsel) {
201 while (unsel->flag & TD_SELECTED) {
207 while (!(sel->flag & TD_SELECTED)) {
221 /* distance calculated from not-selected vertex to nearest selected vertex
222 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
223 static void set_prop_dist(TransInfo *t, short with_dist)
228 for(a=0, tob= t->data; a<t->total; a++, tob++) {
230 tob->rdist= 0.0f; // init, it was mallocced
232 if((tob->flag & TD_SELECTED)==0) {
237 tob->rdist = -1.0f; // signal for next loop
239 for (i = 0, td= t->data; i < t->total; i++, td++) {
240 if(td->flag & TD_SELECTED) {
241 VecSubf(vec, tob->center, td->center);
242 Mat3MulVecfl(tob->mtx, vec);
243 dist = Normalise(vec);
244 if (tob->rdist == -1.0f) {
247 else if (dist < tob->rdist) {
251 else break; // by definition transdata has selected items in beginning
254 tob->dist = tob->rdist;
260 /* ************************** CONVERSIONS ************************* */
262 /* ********************* texture space ********* */
264 static void createTransTexspace(TransInfo *t)
273 if(id==NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
279 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
280 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
282 td->flag= TD_SELECTED;
283 VECCOPY(td->center, ob->obmat[3]);
286 Mat3CpyMat4(td->mtx, ob->obmat);
287 Mat3CpyMat4(td->axismtx, ob->obmat);
288 Mat3Ortho(td->axismtx);
289 Mat3Inv(td->smtx, td->mtx);
291 if( GS(id->name)==ID_ME) {
293 me->texflag &= ~AUTOSPACE;
295 td->ext->rot= me->rot;
296 td->ext->size= me->size;
298 else if( GS(id->name)==ID_CU) {
300 cu->texflag &= ~CU_AUTOSPACE;
302 td->ext->rot= cu->rot;
303 td->ext->size= cu->size;
305 else if( GS(id->name)==ID_MB) {
306 MetaBall *mb= ob->data;
307 mb->texflag &= ~MB_AUTOSPACE;
309 td->ext->rot= mb->rot;
310 td->ext->size= mb->size;
313 VECCOPY(td->iloc, td->loc);
314 VECCOPY(td->ext->irot, td->ext->rot);
315 VECCOPY(td->ext->isize, td->ext->size);
318 /* ********************* edge (for crease) ***** */
320 static void createTransEdge(TransInfo *t) {
321 TransData *td = NULL;
322 EditMesh *em = G.editMesh;
324 float mtx[3][3], smtx[3][3];
325 int count=0, countsel=0;
326 int propmode = t->flag & T_PROP_EDIT;
328 for(eed= em->edges.first; eed; eed= eed->next) {
330 if (eed->f & SELECT) countsel++;
331 if (propmode) count++;
345 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
347 Mat3CpyMat4(mtx, G.obedit->obmat);
350 for(eed= em->edges.first; eed; eed= eed->next) {
351 if(eed->h==0 && (eed->f & SELECT || propmode)) {
352 /* need to set center for center calculations */
353 VecAddf(td->center, eed->v1->co, eed->v2->co);
354 VecMulf(td->center, 0.5f);
358 td->flag= TD_SELECTED;
363 Mat3CpyMat3(td->smtx, smtx);
364 Mat3CpyMat3(td->mtx, mtx);
368 td->val = &(eed->crease);
369 td->ival = eed->crease;
376 /* ********************* pose mode ************* */
378 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
380 bConstraint *con= pchan->constraints.first;
382 for(;con; con= con->next) {
383 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
384 bKinematicConstraint *data= con->data;
388 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
395 static void apply_targetless_ik(Object *ob)
397 bPoseChannel *pchan, *parchan, *chanlist[256];
398 bKinematicConstraint *data;
401 /* now we got a difficult situation... we have to find the
402 target-less IK pchans, and apply transformation to the all
403 pchans that were in the chain */
405 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
406 data= has_targetless_ik(pchan);
407 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
409 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
412 /* exclude tip from chain? */
413 if(!(data->flag & CONSTRAINT_IK_TIP))
414 parchan= pchan->parent;
418 /* Find the chain's root & count the segments needed */
419 for (; parchan; parchan=parchan->parent){
420 chanlist[segcount]= parchan;
423 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
425 for(;segcount;segcount--) {
427 float rmat[4][4], tmat[4][4], imat[4][4];
429 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
430 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
431 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
432 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
434 parchan= chanlist[segcount-1];
436 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
438 if(parchan->parent) {
439 Bone *parbone= parchan->parent->bone;
440 float offs_bone[4][4];
442 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
443 Mat4CpyMat3(offs_bone, bone->bone_mat);
445 /* The bone's root offset (is in the parent's coordinate system) */
446 VECCOPY(offs_bone[3], bone->head);
448 /* Get the length translation of parent (length along y axis) */
449 offs_bone[3][1]+= parbone->length;
451 /* pose_mat(b-1) * offs_bone */
452 if(parchan->bone->flag & BONE_HINGE) {
453 /* the rotation of the parent restposition */
454 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
456 /* the location of actual parent transform */
457 VECCOPY(rmat[3], offs_bone[3]);
458 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
459 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
461 Mat4MulMat4(tmat, offs_bone, rmat);
464 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
466 Mat4Invert(imat, tmat);
469 Mat4CpyMat3(tmat, bone->bone_mat);
471 VECCOPY(tmat[3], bone->head);
472 Mat4Invert(imat, tmat);
475 Mat4MulMat4(rmat, parchan->pose_mat, imat);
477 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
479 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
481 Mat3CpyMat4(rmat3, rmat);
484 Mat3ToQuat(rmat3, parchan->quat);
486 /* for size, remove rotation */
487 QuatToMat3(parchan->quat, qmat);
489 Mat3MulMat3(smat, rmat3, imat);
490 Mat3ToSize(smat, parchan->size);
492 VECCOPY(parchan->loc, rmat[3]);
497 data->flag &= ~CONSTRAINT_IK_AUTO;
503 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
505 Bone *bone= pchan->bone;
506 float pmat[3][3], omat[3][3];
509 VECCOPY(vec, pchan->pose_mat[3]);
510 VECCOPY(td->center, vec);
513 td->flag= TD_SELECTED|TD_USEQUAT;
514 td->protectflag= pchan->protectflag;
516 td->loc = pchan->loc;
517 VECCOPY(td->iloc, pchan->loc);
520 td->ext->quat= pchan->quat;
521 td->ext->size= pchan->size;
523 QUATCOPY(td->ext->iquat, pchan->quat);
524 VECCOPY(td->ext->isize, pchan->size);
526 /* proper way to get the parent transform + own transform */
527 Mat3CpyMat4(omat, ob->obmat);
529 if(pchan->bone->flag & BONE_HINGE)
530 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
532 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
534 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
537 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // huh, transposed?
540 Mat3Inv (td->smtx, td->mtx);
542 /* for axismat we use bone's own transform */
543 Mat3CpyMat4(pmat, pchan->pose_mat);
544 Mat3MulMat3(td->axismtx, omat, pmat);
545 Mat3Ortho(td->axismtx);
547 if(t->mode==TFM_BONESIZE) {
548 bArmature *arm= t->poseobj->data;
550 if(arm->drawtype==ARM_ENVELOPE) {
552 td->val= &bone->dist;
553 td->ival= bone->dist;
556 // abusive storage of scale in the loc pointer :)
557 td->loc= &bone->xwidth;
558 VECCOPY (td->iloc, td->loc);
563 /* in this case we can do target-less IK grabbing */
564 if(t->mode==TFM_TRANSLATION) {
565 bKinematicConstraint *data= has_targetless_ik(pchan);
567 if(data->flag & CONSTRAINT_IK_TIP) {
568 VECCOPY(data->grabtarget, pchan->pose_tail);
571 VECCOPY(data->grabtarget, pchan->pose_head);
573 td->loc = data->grabtarget;
574 VECCOPY(td->iloc, td->loc);
575 data->flag |= CONSTRAINT_IK_AUTO;
577 /* only object matrix correction */
578 Mat3CpyMat3 (td->mtx, omat);
579 Mat3Inv (td->smtx, td->mtx);
584 static void bone_children_clear_transflag(ListBase *lb)
586 Bone *bone= lb->first;
588 for(;bone;bone= bone->next) {
589 bone->flag &= ~BONE_TRANSFORM;
590 bone_children_clear_transflag(&bone->childbase);
594 /* sets transform flags in the bones, returns total */
595 static void set_pose_transflags(TransInfo *t, Object *ob)
597 bArmature *arm= ob->data;
603 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
605 if(bone->layer & arm->layer) {
606 if(bone->flag & BONE_SELECTED)
607 bone->flag |= BONE_TRANSFORM;
609 bone->flag &= ~BONE_TRANSFORM;
613 /* make sure no bone can be transformed when a parent is transformed */
614 /* since pchans are depsgraph sorted, the parents are in beginning of list */
615 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
617 if(bone->flag & BONE_TRANSFORM)
618 bone_children_clear_transflag(&bone->childbase);
621 /* now count, and check if we have autoIK or have to switch from translate to rotate */
622 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
624 if(bone->flag & BONE_TRANSFORM) {
627 if(t->mode==TFM_TRANSLATION) {
628 if( has_targetless_ik(pchan)==NULL ) {
629 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
630 t->mode= TFM_ROTATION;
631 else if((pchan->protectflag & OB_LOCK_LOC)==OB_LOCK_LOC)
632 t->mode= TFM_ROTATION;
639 /* frees temporal IKs */
640 static void pose_grab_with_ik_clear(Object *ob)
642 bKinematicConstraint *data;
646 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
647 for(con= pchan->constraints.first; con; con= con->next) {
648 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
650 if(data->flag & CONSTRAINT_IK_TEMP) {
651 BLI_remlink(&pchan->constraints, con);
652 MEM_freeN(con->data);
654 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
662 /* adds the IK to pchan */
663 static void pose_grab_with_ik_add(bPoseChannel *pchan)
665 bKinematicConstraint *data;
668 /* rule: not if there's already an IK on this channel */
669 for(con= pchan->constraints.first; con; con= con->next)
670 if(con->type==CONSTRAINT_TYPE_KINEMATIC)
674 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
675 data= has_targetless_ik(pchan);
677 data->flag |= CONSTRAINT_IK_AUTO;
681 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
682 BLI_addtail(&pchan->constraints, con);
683 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
685 data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
686 VECCOPY(data->grabtarget, pchan->pose_tail);
689 /* we include only a connected chain */
690 while(pchan && (pchan->bone->flag & BONE_CONNECTED)) {
692 pchan= pchan->parent;
696 /* bone is a canditate to get IK, but we don't do it if it has children connected */
697 static void pose_grab_with_ik_children(bPose *pose, Bone *bone)
702 /* go deeper if children & children are connected */
703 for(bonec= bone->childbase.first; bonec; bonec= bonec->next) {
704 if(bonec->flag & BONE_CONNECTED) {
706 pose_grab_with_ik_children(pose, bonec);
710 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
712 pose_grab_with_ik_add(pchan);
716 /* main call which adds temporal IK chains */
717 static void pose_grab_with_ik(Object *ob)
719 bArmature *arm= ob->data;
720 bPoseChannel *pchan, *pchansel= NULL;
722 if(ob==NULL || ob->pose==NULL || (ob->flag & OB_POSEMODE)==0)
725 /* rule: only one Bone */
726 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
727 if(pchan->bone->layer & arm->layer) {
728 if(pchan->bone->flag & BONE_SELECTED) {
735 if(pchan || pchansel==NULL) return;
737 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
738 if(pchansel->parent) {
739 /* only adds if there's no IK yet */
740 pose_grab_with_ik_add(pchansel);
743 /* rule: go over the children and add IK to the tips */
744 pose_grab_with_ik_children(ob->pose, pchansel->bone);
750 /* only called with pose mode active object now */
751 static void createTransPose(TransInfo *t, Object *ob)
756 TransDataExtension *tdx;
761 /* check validity of state */
762 arm=get_armature (ob);
763 if (arm==NULL || ob->pose==NULL) return;
765 if (arm->flag & ARM_RESTPOS) {
766 if(t->mode!=TFM_BONESIZE) {
767 notice ("Pose edit not possible while Rest Position is enabled");
771 if (!(ob->lay & G.vd->lay)) return;
773 /* do we need to add temporal IK chains? */
774 if((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION)
775 pose_grab_with_ik(ob);
777 /* set flags and count total (warning, can change transform to rotate) */
778 set_pose_transflags(t, ob);
780 if(t->total==0) return;
783 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
785 /* make sure the lock is set OK, unlock can be accidentally saved? */
786 ob->pose->flag |= POSE_LOCKED;
787 ob->pose->flag &= ~POSE_DO_UNLOCK;
789 /* init trans data */
790 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
791 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
792 for(i=0; i<t->total; i++, td++, tdx++) {
798 /* use pose channels to fill trans data */
800 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
801 if(pchan->bone->flag & BONE_TRANSFORM) {
802 add_pose_transdata(t, pchan, ob, td);
807 if(td != (t->data+t->total)) printf("Bone selection count error\n");
811 /* ********************* armature ************** */
813 static void createTransArmatureVerts(TransInfo *t)
816 bArmature *arm= G.obedit->data;
818 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
821 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
822 if(ebo->layer & arm->layer) {
823 if (t->mode==TFM_BONESIZE) {
824 if (ebo->flag & BONE_SELECTED)
828 if (ebo->flag & BONE_TIPSEL)
830 if (ebo->flag & BONE_ROOTSEL)
836 if (!t->total) return;
838 Mat3CpyMat4(mtx, G.obedit->obmat);
841 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
843 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
844 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
846 if(ebo->layer & arm->layer) {
847 if (t->mode==TFM_BONE_ENVELOPE) {
849 if (ebo->flag & BONE_ROOTSEL){
850 td->val= &ebo->rad_head;
853 VECCOPY (td->center, ebo->head);
854 td->flag= TD_SELECTED;
856 Mat3CpyMat3(td->smtx, smtx);
857 Mat3CpyMat3(td->mtx, mtx);
865 if (ebo->flag & BONE_TIPSEL){
866 td->val= &ebo->rad_tail;
868 VECCOPY (td->center, ebo->tail);
869 td->flag= TD_SELECTED;
871 Mat3CpyMat3(td->smtx, smtx);
872 Mat3CpyMat3(td->mtx, mtx);
882 else if (t->mode==TFM_BONESIZE) {
883 if (ebo->flag & BONE_SELECTED) {
884 if(arm->drawtype==ARM_ENVELOPE) {
890 // abusive storage of scale in the loc pointer :)
891 td->loc= &ebo->xwidth;
892 VECCOPY (td->iloc, td->loc);
895 VECCOPY (td->center, ebo->head);
896 td->flag= TD_SELECTED;
898 /* use local bone matrix */
899 VecSubf(delta, ebo->tail, ebo->head);
900 vec_roll_to_mat3(delta, ebo->roll, bonemat);
901 Mat3MulMat3(td->mtx, mtx, bonemat);
902 Mat3Inv(td->smtx, td->mtx);
904 Mat3CpyMat3(td->axismtx, td->mtx);
905 Mat3Ortho(td->axismtx);
914 if (ebo->flag & BONE_TIPSEL){
915 VECCOPY (td->iloc, ebo->tail);
916 VECCOPY (td->center, td->iloc);
918 td->flag= TD_SELECTED;
920 Mat3CpyMat3(td->smtx, smtx);
921 Mat3CpyMat3(td->mtx, mtx);
929 if (ebo->flag & BONE_ROOTSEL){
930 VECCOPY (td->iloc, ebo->head);
931 VECCOPY (td->center, td->iloc);
933 td->flag= TD_SELECTED;
935 Mat3CpyMat3(td->smtx, smtx);
936 Mat3CpyMat3(td->mtx, mtx);
949 /* ********************* meta elements ********* */
951 static void createTransMBallVerts(TransInfo *t)
955 TransDataExtension *tx;
956 float mtx[3][3], smtx[3][3];
957 int count=0, countsel=0;
958 int propmode = t->flag & T_PROP_EDIT;
961 for(ml= editelems.first; ml; ml= ml->next) {
962 if(ml->flag & SELECT) countsel++;
963 if(propmode) count++;
966 /* note: in prop mode we need at least 1 selected */
967 if (countsel==0) return;
969 if(propmode) t->total = count;
970 else t->total = countsel;
972 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
973 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
975 Mat3CpyMat4(mtx, G.obedit->obmat);
978 for(ml= editelems.first; ml; ml= ml->next) {
979 if(propmode || (ml->flag & SELECT)) {
981 VECCOPY(td->iloc, td->loc);
982 VECCOPY(td->center, td->loc);
984 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
985 else td->flag= TD_USEQUAT;
987 Mat3CpyMat3(td->smtx, smtx);
988 Mat3CpyMat3(td->mtx, mtx);
993 /* Radius of MetaElem (mass of MetaElem influence) */
994 if(ml->flag & MB_SCALE_RAD){
1003 /* expx/expy/expz determine "shape" of some MetaElem types */
1004 tx->size = &ml->expx;
1005 tx->isize[0] = ml->expx;
1006 tx->isize[1] = ml->expy;
1007 tx->isize[2] = ml->expz;
1009 /* quat is used for rotation of MetaElem */
1010 tx->quat = ml->quat;
1011 QUATCOPY(tx->iquat, ml->quat);
1021 /* ********************* curve/surface ********* */
1023 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1024 TransData *td, *td_near = NULL;
1025 for (td = head; td<=tail; td++) {
1026 if (td->flag & TD_SELECTED) {
1032 dist = VecLenf(td_near->center, td->center);
1033 if (dist < (td-1)->dist) {
1034 td->dist = (td-1)->dist;
1041 td->dist = MAXFLOAT;
1042 td->flag |= TD_NOTCONNECTED;
1046 for (td = tail; td>=head; td--) {
1047 if (td->flag & TD_SELECTED) {
1053 dist = VecLenf(td_near->center, td->center);
1054 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1055 td->flag &= ~TD_NOTCONNECTED;
1056 if (dist < (td+1)->dist) {
1057 td->dist = (td+1)->dist;
1067 static void createTransCurveVerts(TransInfo *t)
1069 TransData *td = NULL;
1073 float mtx[3][3], smtx[3][3];
1075 int count=0, countsel=0;
1076 int propmode = t->flag & T_PROP_EDIT;
1078 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1079 for(nu= editNurb.first; nu; nu= nu->next) {
1080 if((nu->type & 7)==CU_BEZIER) {
1081 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1083 if(bezt->f1 & 1) countsel++;
1084 if(bezt->f2 & 1) countsel++;
1085 if(bezt->f3 & 1) countsel++;
1086 if(propmode) count+= 3;
1091 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1093 if(propmode) count++;
1094 if(bp->f1 & 1) countsel++;
1099 /* note: in prop mode we need at least 1 selected */
1100 if (countsel==0) return;
1102 if(propmode) t->total = count;
1103 else t->total = countsel;
1104 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1106 Mat3CpyMat4(mtx, G.obedit->obmat);
1110 for(nu= editNurb.first; nu; nu= nu->next) {
1111 if((nu->type & 7)==CU_BEZIER) {
1112 TransData *head, *tail;
1114 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1116 if(propmode || (bezt->f1 & 1)) {
1117 VECCOPY(td->iloc, bezt->vec[0]);
1118 td->loc= bezt->vec[0];
1119 VECCOPY(td->center, bezt->vec[1]);
1120 if(bezt->f1 & 1) td->flag= TD_SELECTED;
1126 Mat3CpyMat3(td->smtx, smtx);
1127 Mat3CpyMat3(td->mtx, mtx);
1133 /* THIS IS THE CV, the other two are handles */
1134 if(propmode || (bezt->f2 & 1)) {
1135 VECCOPY(td->iloc, bezt->vec[1]);
1136 td->loc= bezt->vec[1];
1137 VECCOPY(td->center, td->loc);
1138 if(bezt->f2 & 1) td->flag= TD_SELECTED;
1143 if (t->mode==TFM_CURVE_SHRINKFATTEN) {
1144 td->val = &(bezt->radius);
1145 td->ival = bezt->radius;
1147 td->val = &(bezt->alfa);
1148 td->ival = bezt->alfa;
1151 Mat3CpyMat3(td->smtx, smtx);
1152 Mat3CpyMat3(td->mtx, mtx);
1158 if(propmode || (bezt->f3 & 1)) {
1159 VECCOPY(td->iloc, bezt->vec[2]);
1160 td->loc= bezt->vec[2];
1161 VECCOPY(td->center, bezt->vec[1]);
1162 if(bezt->f3 & 1) td->flag= TD_SELECTED;
1168 Mat3CpyMat3(td->smtx, smtx);
1169 Mat3CpyMat3(td->mtx, mtx);
1176 else if (propmode && head != tail) {
1177 calc_distanceCurveVerts(head, tail-1);
1181 if (propmode && head != tail)
1182 calc_distanceCurveVerts(head, tail-1);
1185 TransData *head, *tail;
1187 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1189 if(propmode || (bp->f1 & 1)) {
1190 VECCOPY(td->iloc, bp->vec);
1192 VECCOPY(td->center, td->loc);
1193 if(bp->f1 & 1) td->flag= TD_SELECTED;
1198 if (t->mode==TFM_CURVE_SHRINKFATTEN) {
1199 td->val = &(bp->radius);
1200 td->ival = bp->radius;
1202 td->val = &(bp->alfa);
1203 td->ival = bp->alfa;
1206 Mat3CpyMat3(td->smtx, smtx);
1207 Mat3CpyMat3(td->mtx, mtx);
1214 else if (propmode && head != tail) {
1215 calc_distanceCurveVerts(head, tail-1);
1219 if (propmode && head != tail)
1220 calc_distanceCurveVerts(head, tail-1);
1225 /* ********************* lattice *************** */
1227 static void createTransLatticeVerts(TransInfo *t)
1229 TransData *td = NULL;
1231 float mtx[3][3], smtx[3][3];
1233 int count=0, countsel=0;
1234 int propmode = t->flag & T_PROP_EDIT;
1237 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1240 if(bp->f1 & 1) countsel++;
1241 if(propmode) count++;
1246 /* note: in prop mode we need at least 1 selected */
1247 if (countsel==0) return;
1249 if(propmode) t->total = count;
1250 else t->total = countsel;
1251 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1253 Mat3CpyMat4(mtx, G.obedit->obmat);
1258 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1260 if(propmode || (bp->f1 & 1)) {
1262 VECCOPY(td->iloc, bp->vec);
1264 VECCOPY(td->center, td->loc);
1265 if(bp->f1 & 1) td->flag= TD_SELECTED;
1267 Mat3CpyMat3(td->smtx, smtx);
1268 Mat3CpyMat3(td->mtx, mtx);
1282 /* ********************* mesh ****************** */
1284 /* proportional distance based on connectivity */
1285 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1286 #define E_NEAR(a) (nears[((a)->tmp.l)])
1287 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1289 EditMesh *em = G.editMesh;
1294 /* f2 flag is used for 'selection' */
1295 /* tmp.l is offset on scratch array */
1296 for(eve= em->verts.first; eve; eve= eve->next) {
1300 if(eve->f & SELECT) {
1303 E_VEC(eve)[0] = 0.0f;
1304 E_VEC(eve)[1] = 0.0f;
1305 E_VEC(eve)[2] = 0.0f;
1314 /* Floodfill routine */
1316 At worst this is n*n of complexity where n is number of edges
1317 Best case would be n if the list is ordered perfectly.
1318 Estimate is n log n in average (so not too bad)
1323 for(eed= em->edges.first; eed; eed= eed->next) {
1325 EditVert *v1= eed->v1, *v2= eed->v2;
1326 float *vec2 = E_VEC(v2);
1327 float *vec1 = E_VEC(v1);
1329 if (v1->f2 + v2->f2 == 4)
1335 float len1 = VecLength(vec1);
1336 float len2 = VecLength(vec2);
1338 /* for v2 if not selected */
1340 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1341 lenn = VecLength(nvec);
1342 if (lenn - len1 > 0.00001f && len2 - lenn > 0.00001f) {
1343 VECCOPY(vec2, nvec);
1344 E_NEAR(v2) = E_NEAR(v1);
1347 else if (len2 - len1 > 0.00001f && len1 - lenn > 0.00001f) {
1348 VECCOPY(vec2, vec1);
1349 E_NEAR(v2) = E_NEAR(v1);
1353 /* for v1 if not selected */
1355 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1356 lenn = VecLength(nvec);
1357 if (lenn - len2 > 0.00001f && len1 - lenn > 0.00001f) {
1358 VECCOPY(vec1, nvec);
1359 E_NEAR(v1) = E_NEAR(v2);
1362 else if (len1 - len2 > 0.00001f && len2 - lenn > 0.00001f) {
1363 VECCOPY(vec1, vec2);
1364 E_NEAR(v1) = E_NEAR(v2);
1371 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1372 if (VecLength(vec1) - VecLength(vec2) > 0.00001f) {
1373 VECCOPY(vec2, vec1);
1375 E_NEAR(v2) = E_NEAR(v1);
1381 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1382 if (VecLength(vec2) - VecLength(vec1) > 0.00001f) {
1383 VECCOPY(vec1, vec2);
1385 E_NEAR(v1) = E_NEAR(v2);
1393 /* loop-in-a-loop I know, but we need it! (ton) */
1394 static void get_face_center(float *cent, EditVert *eve)
1396 EditMesh *em = G.editMesh;
1399 for(efa= em->faces.first; efa; efa= efa->next)
1401 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1404 VECCOPY(cent, efa->cent);
1408 static void VertsToTransData(TransData *td, EditVert *eve)
1413 VECCOPY(td->center, td->loc);
1414 if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1415 get_face_center(td->center, eve);
1416 VECCOPY(td->iloc, td->loc);
1419 VECCOPY(td->axismtx[2], eve->no);
1425 td->axismtx[1][2] = 0.0f;
1433 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1435 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1437 float *vec = userData;
1443 /* hurmf, copy from buttons_editing.c, i have to sort this out what it means... */
1444 static void modifiers_setOnCage(void *ob_v, void *md_v)
1449 int i, cageIndex = modifiers_getCageIndex(ob, NULL );
1451 for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next )
1453 if( i >= cageIndex )
1454 md->mode ^= eModifierMode_OnCage;
1460 /* disable subsurf temporal, get mapped cos, and enable it */
1461 static float *get_crazy_mapped_editverts(void)
1469 for( i = 0, md=G.obedit->modifiers.first; md; ++i, md=md->next ) {
1470 if(md->type==eModifierType_Subsurf)
1471 if(md->mode & eModifierMode_OnCage)
1475 /* this call disables subsurf and enables the underlying modifier to deform, apparently */
1476 modifiers_setOnCage(G.obedit, md);
1477 /* make it all over */
1478 makeDispListMesh(G.obedit);
1481 /* now get the cage */
1482 dm= editmesh_get_derived_cage(&needsFree);
1484 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1485 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1487 if (needsFree) dm->release(dm);
1490 /* set back the flag, no new cage needs to be built, transform does it */
1491 modifiers_setOnCage(G.obedit, md);
1497 #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])
1498 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1500 float vecu[3], vecv[3];
1503 TAN_MAKE_VEC(vecu, v1, v2);
1504 TAN_MAKE_VEC(vecv, v1, v3);
1505 triatoquat(v1, vecu, vecv, q1);
1507 TAN_MAKE_VEC(vecu, def1, def2);
1508 TAN_MAKE_VEC(vecv, def1, def3);
1509 triatoquat(def1, vecu, vecv, q2);
1511 QuatSub(quat, q2, q1);
1515 static void set_crazyspace_quats(float *mappedcos, float *quats)
1517 EditMesh *em = G.editMesh;
1518 EditVert *eve, *prev;
1520 float *v1, *v2, *v3, *v4;
1523 /* two abused locations in vertices */
1524 for(eve= em->verts.first; eve; eve= eve->next, index++) {
1526 eve->prev= (EditVert *)index;
1529 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
1530 for(efa= em->faces.first; efa; efa= efa->next) {
1532 /* retrieve mapped coordinates */
1533 v1= mappedcos + 3*( (int)(efa->v1->prev) );
1534 v2= mappedcos + 3*( (int)(efa->v2->prev) );
1535 v3= mappedcos + 3*( (int)(efa->v3->prev) );
1537 if(efa->v2->tmp.fp==NULL && efa->v2->f1) {
1538 set_crazy_vertex_quat(quats, efa->v2->co, efa->v3->co, efa->v1->co, v2, v3, v1);
1539 efa->v2->tmp.fp= quats;
1544 v4= mappedcos + 3*( (int)(efa->v4->prev) );
1546 if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1547 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v4->co, v1, v2, v4);
1548 efa->v1->tmp.fp= quats;
1551 if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1552 set_crazy_vertex_quat(quats, efa->v3->co, efa->v4->co, efa->v2->co, v3, v4, v2);
1553 efa->v3->tmp.fp= quats;
1556 if(efa->v4->tmp.fp==NULL && efa->v4->f1) {
1557 set_crazy_vertex_quat(quats, efa->v4->co, efa->v1->co, efa->v3->co, v4, v1, v3);
1558 efa->v4->tmp.fp= quats;
1563 if(efa->v1->tmp.fp==NULL && efa->v1->f1) {
1564 set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v3->co, v1, v2, v3);
1565 efa->v1->tmp.fp= quats;
1568 if(efa->v3->tmp.fp==NULL && efa->v3->f1) {
1569 set_crazy_vertex_quat(quats, efa->v3->co, efa->v1->co, efa->v2->co, v3, v1, v2);
1570 efa->v3->tmp.fp= quats;
1576 /* restore abused prev pointer */
1577 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
1582 static void createTransEditVerts(TransInfo *t)
1584 TransData *tob = NULL;
1585 EditMesh *em = G.editMesh;
1587 EditVert **nears = NULL;
1588 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
1589 float mtx[3][3], smtx[3][3];
1590 int count=0, countsel=0;
1591 int propmode = t->flag & T_PROP_EDIT;
1592 int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR);
1594 // transform now requires awareness for select mode, so we tag the f1 flags in verts
1595 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
1596 for(eve= em->verts.first; eve; eve= eve->next) {
1597 if(eve->h==0 && (eve->f & SELECT))
1603 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
1605 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1606 for(eed= em->edges.first; eed; eed= eed->next) {
1607 if(eed->h==0 && (eed->f & SELECT))
1608 eed->v1->f1= eed->v2->f1= SELECT;
1613 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
1614 for(efa= em->faces.first; efa; efa= efa->next) {
1615 if(efa->h==0 && (efa->f & SELECT)) {
1616 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
1617 if(efa->v4) efa->v4->f1= SELECT;
1622 /* now we can count */
1623 for(eve= em->verts.first; eve; eve= eve->next) {
1625 if(eve->f1) countsel++;
1626 if(propmode) count++;
1630 /* note: in prop mode we need at least 1 selected */
1631 if (countsel==0) return;
1636 /* allocating scratch arrays */
1637 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
1638 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
1640 else t->total = countsel;
1641 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
1643 Mat3CpyMat4(mtx, G.obedit->obmat);
1646 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
1648 /* detect CrazySpace [tm] */
1650 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
1651 if(modifiers_isDeformed(G.obedit)) {
1652 /* disable subsurf temporal, get mapped cos, and enable it */
1653 mappedcos= get_crazy_mapped_editverts();
1654 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
1655 set_crazyspace_quats(mappedcos, quats);
1660 /* find out which half we do */
1662 for (eve=em->verts.first; eve; eve=eve->next) {
1663 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
1671 for (eve=em->verts.first; eve; eve=eve->next) {
1673 if(propmode || eve->f1) {
1674 VertsToTransData(tob, eve);
1676 if(eve->f1) tob->flag |= TD_SELECTED;
1680 VECCOPY(vec, E_VEC(eve));
1681 Mat3MulVecfl(mtx, vec);
1682 tob->dist= VecLength(vec);
1685 tob->flag |= TD_NOTCONNECTED;
1686 tob->dist = MAXFLOAT;
1691 if(quats && eve->tmp.fp) {
1692 float mat[3][3], imat[3][3], qmat[3][3];
1694 QuatToMat3(eve->tmp.fp, qmat);
1695 Mat3MulMat3(mat, mtx, qmat);
1698 Mat3CpyMat3(tob->smtx, imat);
1699 Mat3CpyMat3(tob->mtx, mat);
1702 Mat3CpyMat3(tob->smtx, smtx);
1703 Mat3CpyMat3(tob->mtx, mtx);
1707 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
1708 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
1709 if(vmir!=eve) tob->tdmir= vmir;
1719 /* crazy space free */
1721 MEM_freeN(mappedcos);
1726 /* ********************* UV ****************** */
1728 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
1732 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1734 /* uv coords are scaled by aspects. this is needed for rotations and
1735 proportional editing to be consistent with the stretchted uv coords
1736 that are displayed. this also means that for display and numinput,
1737 and when the the uv coords are flushed, these are converted each time */
1738 td2d->loc[0] = uv[0]*aspx;
1739 td2d->loc[1] = uv[1]*aspy;
1740 td2d->loc[2] = 0.0f;
1744 td->loc = td2d->loc;
1745 VECCOPY(td->center, td->loc);
1746 VECCOPY(td->iloc, td->loc);
1748 memset(td->axismtx, 0, sizeof(td->axismtx));
1749 td->axismtx[2][2] = 1.0f;
1751 td->ext= NULL; td->tdi= NULL; td->val= NULL;
1754 td->flag |= TD_SELECTED;
1764 static void createTransUVs(TransInfo *t)
1766 TransData *td = NULL;
1767 TransData2D *td2d = NULL;
1771 int a, count=0, countsel=0;
1772 int propmode = t->flag & T_PROP_EDIT;
1774 if(is_uv_tface_editing_allowed()==0) return;
1775 me= get_mesh(OBACT);
1780 for(a=me->totface; a>0; a--, tf++, mf++) {
1781 if(mf->v3 && tf->flag & TF_SELECT) {
1782 if(tf->flag & TF_SEL1) countsel++;
1783 if(tf->flag & TF_SEL2) countsel++;
1784 if(tf->flag & TF_SEL3) countsel++;
1785 if(mf->v4 && (tf->flag & TF_SEL4)) countsel++;
1787 count += (mf->v4)? 4: 3;
1791 /* note: in prop mode we need at least 1 selected */
1792 if (countsel==0) return;
1794 t->total= (propmode)? count: countsel;
1795 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
1796 /* for each 2d uv coord a 3d vector is allocated, so that they can be
1797 treated just as if they were 3d verts */
1798 t->data2d= MEM_mallocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
1800 if(G.sima->flag & SI_CLIP_UV)
1801 t->flag |= T_CLIP_UV;
1807 for(a=me->totface; a>0; a--, tf++, mf++) {
1808 if(mf->v3 && tf->flag & TF_SELECT) {
1809 if(tf->flag & TF_SEL1 || propmode)
1810 UVsToTransData(td++, td2d++, tf->uv[0], (tf->flag & TF_SEL1));
1811 if(tf->flag & TF_SEL2 || propmode)
1812 UVsToTransData(td++, td2d++, tf->uv[1], (tf->flag & TF_SEL2));
1813 if(tf->flag & TF_SEL3 || propmode)
1814 UVsToTransData(td++, td2d++, tf->uv[2], (tf->flag & TF_SEL3));
1816 if(mf->v4 && (tf->flag & TF_SEL4 || propmode))
1817 UVsToTransData(td++, td2d++, tf->uv[3], (tf->flag & TF_SEL4));
1821 if (G.sima->flag & SI_LIVE_UNWRAP)
1822 unwrap_lscm_live_begin();
1825 void flushTransUVs(TransInfo *t)
1828 int a, width, height;
1830 Mesh *me= get_mesh(ob);
1831 float aspx, aspy, invx, invy;
1833 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1834 transform_width_height_tface_uv(&width, &height);
1838 /* flush to 2d vector from internally used 3d vector */
1839 for(a=0, td= t->data2d; a<t->total; a++, td++) {
1840 td->loc2d[0]= td->loc[0]*invx;
1841 td->loc2d[1]= td->loc[1]*invy;
1843 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
1844 td->loc2d[0]= floor(width*td->loc2d[0] + 0.5f)/width;
1845 td->loc2d[1]= floor(height*td->loc2d[1] + 0.5f)/height;
1849 if((G.sima->flag & SI_BE_SQUARE) && (t->state != TRANS_CANCEL))
1850 be_square_tface_uv(me);
1852 /* this is overkill if G.sima->lock is not set, but still needed */
1853 object_uvs_changed(ob);
1856 int clipUVTransform(TransInfo *t, float *vec, int resize)
1859 int a, clipx=1, clipy=1;
1860 float aspx, aspy, min[2], max[2];
1862 transform_aspect_ratio_tface_uv(&aspx, &aspy);
1863 min[0]= min[1]= 0.0f;
1864 max[0]= aspx; max[1]= aspy;
1866 for(a=0, td= t->data; a<t->total; a++, td++) {
1867 DO_MINMAX2(td->loc, min, max);
1871 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
1872 vec[0] *= t->center[0]/(t->center[0] - min[0]);
1873 else if(max[0] > aspx && t->center[0] < aspx)
1874 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
1878 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
1879 vec[1] *= t->center[1]/(t->center[1] - min[1]);
1880 else if(max[1] > aspy && t->center[1] < aspy)
1881 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
1888 else if(max[0] > aspx)
1889 vec[0] -= max[0]-aspx;
1895 else if(max[1] > aspy)
1896 vec[1] -= max[1]-aspy;
1901 return (clipx || clipy);
1904 /* **************** IpoKey stuff, for Object TransData ********** */
1906 /* storage of bezier triple. thats why -3 and +3! */
1907 static void set_tdi_old(float *old, float *poin)
1914 /* while transforming */
1915 void add_tdi_poin(float *poin, float *old, float delta)
1918 poin[0]= old[0]+delta;
1919 poin[-3]= old[3]+delta;
1920 poin[3]= old[6]+delta;
1924 /* fill ipokey transdata with old vals and pointers */
1925 static void ipokey_to_transdata(IpoKey *ik, TransData *td)
1927 extern int ob_ar[]; // blenkernel ipo.c
1928 TransDataIpokey *tdi= td->tdi;
1932 td->val= NULL; // is read on ESC
1934 for(a=0; a<OB_TOTIPO; a++) {
1938 switch( ob_ar[a] ) {
1941 tdi->locx= &(bezt->vec[1][1]); break;
1944 tdi->locy= &(bezt->vec[1][1]); break;
1947 tdi->locz= &(bezt->vec[1][1]); break;
1952 tdi->rotx= &(bezt->vec[1][1]); break;
1956 tdi->roty= &(bezt->vec[1][1]); break;
1960 tdi->rotz= &(bezt->vec[1][1]); break;
1964 tdi->sizex= &(bezt->vec[1][1]); break;
1967 tdi->sizey= &(bezt->vec[1][1]); break;
1970 tdi->sizez= &(bezt->vec[1][1]); break;
1975 /* oldvals for e.g. undo */
1976 if(tdi->locx) set_tdi_old(tdi->oldloc, tdi->locx);
1977 if(tdi->locy) set_tdi_old(tdi->oldloc+1, tdi->locy);
1978 if(tdi->locz) set_tdi_old(tdi->oldloc+2, tdi->locz);
1980 /* remember, for mapping curves ('1'=10 degrees) */
1981 if(tdi->rotx) set_tdi_old(tdi->oldrot, tdi->rotx);
1982 if(tdi->roty) set_tdi_old(tdi->oldrot+1, tdi->roty);
1983 if(tdi->rotz) set_tdi_old(tdi->oldrot+2, tdi->rotz);
1985 /* this is not allowed to be dsize! */
1986 if(tdi->sizex) set_tdi_old(tdi->oldsize, tdi->sizex);
1987 if(tdi->sizey) set_tdi_old(tdi->oldsize+1, tdi->sizey);
1988 if(tdi->sizez) set_tdi_old(tdi->oldsize+2, tdi->sizez);
1991 if(delta) tdi->flag |= TOB_IPODROT;
1995 /* *************************** Object Transform data ******************* */
1997 static void ObjectToTransData(TransData *td, Object *ob)
2001 void *cfirst, *clast;
2003 /* set axismtx BEFORE clearing constraints to have the real orientation */
2004 Mat3CpyMat4(td->axismtx, ob->obmat);
2005 Mat3Ortho(td->axismtx);
2007 /* then why are constraints and track disabled here?
2008 they dont alter loc/rot/size itself (ton) */
2009 cfirst = ob->constraints.first;
2010 clast = ob->constraints.last;
2011 ob->constraints.first=ob->constraints.last=NULL;
2016 where_is_object(ob);
2020 ob->constraints.first = cfirst;
2021 ob->constraints.last = clast;
2026 VECCOPY(td->iloc, td->loc);
2028 td->ext->rot = ob->rot;
2029 VECCOPY(td->ext->irot, ob->rot);
2030 VECCOPY(td->ext->drot, ob->drot);
2032 td->ext->size = ob->size;
2033 VECCOPY(td->ext->isize, ob->size);
2034 VECCOPY(td->ext->dsize, ob->dsize);
2036 VECCOPY(td->center, ob->obmat[3]);
2040 float totmat[3][3], obinv[3][3];
2042 /* we calculate smtx without obmat: so a parmat */
2043 object_to_mat3(ob, obmtx);
2044 Mat3CpyMat4(totmat, ob->obmat);
2045 Mat3Inv(obinv, totmat);
2046 Mat3MulMat3(td->smtx, obmtx, obinv);
2047 Mat3Inv(td->mtx, td->smtx);
2057 /* sets flags in Bases to define whether they take part in transform */
2058 /* it deselects Bases, so we have to call the clear function always after */
2059 static void set_trans_object_base_flags(TransInfo *t)
2062 if Base selected and has parent selected:
2063 base->flag= BA_WAS_SEL
2067 /* makes sure base flags and object flags are identical */
2070 /* handle pending update events, otherwise they got copied below */
2071 for (base= FIRSTBASE; base; base= base->next) {
2072 if(base->object->recalc)
2073 object_handle_update(base->object);
2076 for (base= FIRSTBASE; base; base= base->next) {
2077 base->flag &= ~BA_WAS_SEL;
2079 if(TESTBASELIB(base)) {
2080 Object *ob= base->object;
2081 Object *parsel= ob->parent;
2083 /* if parent selected, deselect */
2085 if(parsel->flag & SELECT) break;
2086 parsel= parsel->parent;
2090 base->flag &= ~SELECT;
2091 base->flag |= BA_WAS_SEL;
2093 /* used for flush, depgraph will change recalcs if needed :) */
2094 ob->recalc |= OB_RECALC_OB;
2097 /* all recalc flags get flushed */
2098 DAG_scene_flush_update(G.scene, screen_view3d_layers());
2100 /* and we store them temporal in base (only used for transform code) */
2101 /* this because after doing updates, the object->recalc is cleared */
2102 for (base= FIRSTBASE; base; base= base->next) {
2103 if(base->object->recalc & OB_RECALC_OB)
2104 base->flag |= BA_HAS_RECALC_OB;
2105 if(base->object->recalc & OB_RECALC_DATA)
2106 base->flag |= BA_HAS_RECALC_DATA;
2110 static void clear_trans_object_base_flags(void)
2116 if(base->flag & BA_WAS_SEL) base->flag |= SELECT;
2117 base->flag &= ~(BA_WAS_SEL|BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA|BA_DO_IPO);
2123 /* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */
2124 /* note; transdata has been freed already! */
2125 void special_aftertrans_update(TransInfo *t)
2131 int cancelled= (t->state == TRANS_CANCEL);
2134 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2135 allqueue(REDRAWBUTSEDIT, 0);
2137 /* table needs to be created for each edit command, since vertices can move etc */
2138 mesh_octree_table(G.obedit, NULL, 'e');
2140 else if( (t->flag & T_POSE) && t->poseobj) {
2144 bPoseChannel *pchan;
2150 /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
2151 pose->flag |= POSE_DO_UNLOCK;
2153 /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */
2154 if(!cancelled && t->mode==TFM_TRANSLATION)
2155 apply_targetless_ik(ob);
2157 /* not forget to clear the auto flag */
2158 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
2159 bKinematicConstraint *data= has_targetless_ik(pchan);
2160 if(data) data->flag &= ~CONSTRAINT_IK_AUTO;
2164 if(t->mode==TFM_TRANSLATION)
2165 pose_grab_with_ik_clear(ob);
2167 /* automatic inserting of keys */
2168 if((G.flags & G_RECORDKEYS) && (!cancelled)) {
2172 act= ob->action= add_empty_action(ID_PO);
2174 for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
2175 if (pchan->bone->flag & BONE_TRANSFORM){
2177 if(U.uiflag & USER_KEYINSERTAVAI) {
2178 bActionChannel *achan;
2180 for (achan = act->chanbase.first; achan; achan=achan->next){
2182 if (achan->ipo && !strcmp (achan->name, pchan->name)){
2183 for (icu = achan->ipo->curve.first; icu; icu=icu->next){
2184 insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode);
2193 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_X);
2194 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
2195 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
2197 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_W);
2198 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_X);
2199 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
2200 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
2202 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_X);
2203 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Y);
2204 insertkey(&ob->id, ID_PO, pchan->name, NULL, AC_LOC_Z);
2209 remake_action_ipos (act);
2210 allspace(REMAKEIPO, 0);
2211 allqueue(REDRAWACTION, 0);
2212 allqueue(REDRAWIPO, 0);
2213 allqueue(REDRAWNLA, 0);
2214 allqueue(REDRAWTIME, 0);
2216 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2218 else if(arm->flag & ARM_DELAYDEFORM) {
2219 /* old optimize trick... this enforces to bypass the depgraph */
2220 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2221 ob->recalc= 0; // is set on OK position already by recalcData()
2224 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
2226 if(t->mode==TFM_BONESIZE || t->mode==TFM_BONE_ENVELOPE)
2227 allqueue(REDRAWBUTSEDIT, 0);
2234 if(base->flag & BA_DO_IPO) redrawipo= 1;
2238 if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
2240 /* Set autokey if necessary */
2241 if ((G.flags & G_RECORDKEYS) && (!cancelled) && (base->flag & SELECT)){
2244 if(ob->ipoflag & OB_ACTION_OB)
2247 if(U.uiflag & USER_KEYINSERTAVAI) {
2248 if(base->object->ipo) {
2249 ID* id= (ID *)(base->object);
2250 icu= base->object->ipo->curve.first;
2252 icu->flag &= ~IPO_SELECT;
2253 insertkey(id, ID_OB, actname, NULL, icu->adrcode);
2260 insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_X);
2261 insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Y);
2262 insertkey(&base->object->id, ID_OB, actname, NULL, OB_ROT_Z);
2264 insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_X);
2265 insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Y);
2266 insertkey(&base->object->id, ID_OB, actname, NULL, OB_LOC_Z);
2268 insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_X);
2269 insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Y);
2270 insertkey(&base->object->id, ID_OB, actname, NULL, OB_SIZE_Z);
2273 remake_object_ipos (ob);
2274 allqueue(REDRAWIPO, 0);
2275 allspace(REMAKEIPO, 0);
2276 allqueue(REDRAWVIEW3D, 0);
2277 allqueue(REDRAWNLA, 0);
2278 allqueue(REDRAWTIME, 0);
2286 clear_trans_object_base_flags();
2289 allqueue(REDRAWNLA, 0);
2290 allqueue(REDRAWACTION, 0);
2291 allqueue(REDRAWIPO, 0);
2294 reset_slowparents();
2296 /* note; should actually only be done for all objects when a lamp is moved... (ton) */
2297 if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED)
2298 reshadeall_displist();
2301 static void createTransObject(TransInfo *t)
2303 TransData *td = NULL;
2304 TransDataExtension *tx;
2310 set_trans_object_base_flags(t);
2313 for(base= FIRSTBASE; base; base= base->next) {
2314 if TESTBASELIB(base) {
2317 /* store ipo keys? */
2318 if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2319 elems.first= elems.last= NULL;
2320 make_ipokey_transform(ob, &elems, 1); /* '1' only selected keys */
2322 pushdata(&elems, sizeof(ListBase));
2324 for(ik= elems.first; ik; ik= ik->next) t->total++;
2326 if(elems.first==NULL) t->total++;
2335 /* clear here, main transform function escapes too */
2336 clear_trans_object_base_flags();
2340 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransOb");
2341 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransObExtension");
2343 for(base= FIRSTBASE; base; base= base->next) {
2344 if TESTBASELIB(base) {
2347 td->flag= TD_SELECTED;
2348 td->protectflag= ob->protectflag;
2351 /* store ipo keys? */
2352 if(ob->ipo && ob->ipo->showkey && (ob->ipoflag & OB_DRAWKEY)) {
2354 popfirst(&elems); // bring back pushed listbase
2360 base->flag |= BA_DO_IPO+BA_WAS_SEL;
2361 base->flag &= ~SELECT;
2364 set_no_parent_ipo(1);
2365 ipoflag= ob->ipoflag;
2366 ob->ipoflag &= ~OB_OFFS_OB;
2368 pushdata(ob->loc, 7*3*4); // tsk! tsk!
2370 for(ik= elems.first; ik; ik= ik->next) {
2372 /* weak... this doesn't correct for floating values, giving small errors */
2373 CFRA= (int)(ik->val/G.scene->r.framelen);
2376 ObjectToTransData(td, ob); // does where_is_object()
2378 td->flag= TD_SELECTED;
2380 td->tdi= MEM_callocN(sizeof(TransDataIpokey), "TransDataIpokey");
2381 /* also does tdi->flag and oldvals, needs to be after ob_to_transob()! */
2382 ipokey_to_transdata(ik, td);
2386 if(ik->next) td->ext= tx; // prevent corrupting mem!
2388 free_ipokey(&elems);
2391 set_no_parent_ipo(0);
2394 ob->ipoflag= ipoflag;
2396 where_is_object(ob); // restore
2399 ObjectToTransData(td, ob);
2407 ObjectToTransData(td, ob);
2417 void createTransData(TransInfo *t)
2421 if (t->context == CTX_TEXTURE) {
2422 t->flag |= T_TEXTURE;
2423 createTransTexspace(t);
2425 else if (t->context == CTX_EDGE) {
2429 if(t->data && t->flag & T_PROP_EDIT) {
2430 sort_trans_data(t); // makes selected become first in array
2431 set_prop_dist(t, 1);
2432 sort_trans_data_dist(t);
2435 else if (t->spacetype == SPACE_IMAGE) {
2436 t->flag |= T_POINTS|T_2D_EDIT;
2438 if(t->data && (t->flag & T_PROP_EDIT)) {
2439 sort_trans_data(t); // makes selected become first in array
2440 set_prop_dist(t, 1);
2441 sort_trans_data_dist(t);
2444 else if (G.obedit) {
2446 if (G.obedit->type == OB_MESH) {
2447 createTransEditVerts(t);
2449 else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) {
2450 createTransCurveVerts(t);
2452 else if (G.obedit->type==OB_LATTICE) {
2453 createTransLatticeVerts(t);
2455 else if (G.obedit->type==OB_MBALL) {
2456 createTransMBallVerts(t);
2458 else if (G.obedit->type==OB_ARMATURE) {
2459 t->flag &= ~T_PROP_EDIT;
2460 createTransArmatureVerts(t);
2463 printf("not done yet! only have mesh surface curve\n");
2466 if(t->data && t->flag & T_PROP_EDIT) {
2467 if (ELEM(G.obedit->type, OB_CURVE, OB_MESH)) {
2468 sort_trans_data(t); // makes selected become first in array
2469 set_prop_dist(t, 0);
2470 sort_trans_data_dist(t);
2473 sort_trans_data(t); // makes selected become first in array
2474 set_prop_dist(t, 1);
2475 sort_trans_data_dist(t);
2479 t->flag |= T_EDIT|T_POINTS;
2481 /* exception... hackish, we want bonesize to use bone orientation matrix (ton) */
2482 if(t->mode==TFM_BONESIZE) {
2483 t->flag &= ~(T_EDIT|T_POINTS);
2485 t->poseobj= ob; /* <- tsk tsk, this is going to give issues one day */
2488 else if (ob && (ob->flag & OB_POSEMODE)) {
2489 createTransPose(t, OBACT);
2491 else if (G.f & G_WEIGHTPAINT) {
2492 /* exception, we look for the one selected armature */
2494 for(base=FIRSTBASE; base; base= base->next) {
2495 if(TESTBASELIB(base)) {
2496 if(base->object->type==OB_ARMATURE)
2497 if(base->object->flag & OB_POSEMODE)
2502 createTransPose(t, base->object);
2506 createTransObject(t);
2507 t->flag |= T_OBJECT;
2510 if((t->flag & T_OBJECT) && G.vd->camera==OBACT && G.vd->persp>1) {
2511 t->flag |= T_CAMERA;
2515 G.scene->recalc |= SCE_PRV_CHANGED; /* test for 3d preview */