4 * ***** BEGIN GPL 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.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
38 #include "MEM_guardedalloc.h"
40 #include "DNA_anim_types.h"
41 #include "DNA_action_types.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_camera_types.h"
44 #include "DNA_curve_types.h"
45 #include "DNA_effect_types.h"
46 #include "DNA_image_types.h"
47 #include "DNA_key_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_modifier_types.h"
54 #include "DNA_nla_types.h"
55 #include "DNA_node_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_object_force.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_sequence_types.h"
63 #include "DNA_texture_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
66 #include "DNA_userdef_types.h"
67 #include "DNA_property_types.h"
68 #include "DNA_vfont_types.h"
69 #include "DNA_constraint_types.h"
70 #include "DNA_listBase.h"
71 #include "DNA_gpencil_types.h"
73 #include "BKE_action.h"
74 #include "BKE_armature.h"
75 #include "BKE_blender.h"
76 #include "BKE_cloth.h"
77 #include "BKE_context.h"
78 #include "BKE_curve.h"
79 #include "BKE_constraint.h"
80 #include "BKE_depsgraph.h"
81 #include "BKE_displist.h"
82 #include "BKE_DerivedMesh.h"
83 #include "BKE_effect.h"
85 #include "BKE_fcurve.h"
86 #include "BKE_global.h"
87 #include "BKE_lattice.h"
90 #include "BKE_mball.h"
92 #include "BKE_modifier.h"
94 #include "BKE_object.h"
95 #include "BKE_particle.h"
96 #include "BKE_sequence.h"
97 #include "BKE_pointcache.h"
98 #include "BKE_softbody.h"
99 #include "BKE_utildefines.h"
100 #include "BKE_bmesh.h"
101 #include "BKE_context.h"
102 #include "BKE_report.h"
104 //#include "BIF_editview.h"
105 //#include "BIF_editlattice.h"
106 //#include "BIF_editconstraint.h"
107 //#include "BIF_editmesh.h"
108 //#include "BIF_editsima.h"
109 //#include "BIF_editparticle.h"
111 //#include "BIF_poseobject.h"
112 //#include "BIF_meshtools.h"
113 //#include "BIF_mywindow.h"
114 //#include "BIF_resources.h"
115 //#include "BIF_screen.h"
116 //#include "BIF_space.h"
117 //#include "BIF_toolbox.h"
119 #include "ED_anim_api.h"
120 #include "ED_armature.h"
121 #include "ED_particle.h"
122 #include "ED_image.h"
123 #include "ED_keyframing.h"
124 #include "ED_keyframes_edit.h"
125 #include "ED_object.h"
126 #include "ED_markers.h"
128 #include "ED_retopo.h"
129 #include "ED_types.h"
130 #include "ED_uvedit.h"
131 #include "ED_view3d.h"
133 #include "UI_view2d.h"
135 //#include "BSE_edit.h"
136 //#include "BDR_editobject.h" // reset_slowparents()
137 //#include "BDR_gpencil.h"
139 #include "BLI_arithb.h"
140 #include "BLI_blenlib.h"
141 #include "BLI_editVert.h"
143 //#include "editmesh.h"
145 //#include "blendef.h"
147 //#include "mydevice.h"
149 extern ListBase editelems;
151 #include "transform.h"
153 #include "BLO_sys_types.h" // for intptr_t support
155 /* local function prototype - for Object/Bone Constraints */
156 static short constraints_list_needinv(TransInfo *t, ListBase *list);
158 /* ************************** Functions *************************** */
160 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
161 TransData pivot = *head;
162 TransData *ihead = head;
163 TransData *itail = tail;
164 short connected = t->flag & T_PROP_CONNECTED;
169 while ((tail->dist >= pivot.dist) && (head < tail))
173 while ((tail->rdist >= pivot.rdist) && (head < tail))
184 while ((head->dist <= pivot.dist) && (head < tail))
188 while ((head->rdist <= pivot.rdist) && (head < tail))
201 qsort_trans_data(t, ihead, head-1);
204 qsort_trans_data(t, head+1, itail);
208 void sort_trans_data_dist(TransInfo *t) {
209 TransData *start = t->data;
212 while(i < t->total && start->flag & TD_SELECTED) {
216 qsort_trans_data(t, start, t->data + t->total - 1);
219 static void sort_trans_data(TransInfo *t)
221 TransData *sel, *unsel;
226 while (sel > unsel) {
227 while (unsel->flag & TD_SELECTED) {
233 while (!(sel->flag & TD_SELECTED)) {
247 /* distance calculated from not-selected vertex to nearest selected vertex
248 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
249 static void set_prop_dist(TransInfo *t, short with_dist)
254 for(a=0, tob= t->data; a<t->total; a++, tob++) {
256 tob->rdist= 0.0f; // init, it was mallocced
258 if((tob->flag & TD_SELECTED)==0) {
263 tob->rdist = -1.0f; // signal for next loop
265 for (i = 0, td= t->data; i < t->total; i++, td++) {
266 if(td->flag & TD_SELECTED) {
267 VecSubf(vec, tob->center, td->center);
268 Mat3MulVecfl(tob->mtx, vec);
269 dist = Normalize(vec);
270 if (tob->rdist == -1.0f) {
273 else if (dist < tob->rdist) {
277 else break; // by definition transdata has selected items in beginning
280 tob->dist = tob->rdist;
286 /* ************************** CONVERSIONS ************************* */
288 /* ********************* texture space ********* */
290 static void createTransTexspace(bContext *C, TransInfo *t)
292 Scene *scene = CTX_data_scene(C);
300 if (ob == NULL) { // Shouldn't logically happen, but still...
306 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
312 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
313 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
315 td->flag= TD_SELECTED;
316 VECCOPY(td->center, ob->obmat[3]);
319 Mat3CpyMat4(td->mtx, ob->obmat);
320 Mat3CpyMat4(td->axismtx, ob->obmat);
321 Mat3Ortho(td->axismtx);
322 Mat3Inv(td->smtx, td->mtx);
324 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
325 *texflag &= ~AUTOSPACE;
328 VECCOPY(td->iloc, td->loc);
329 VECCOPY(td->ext->irot, td->ext->rot);
330 VECCOPY(td->ext->isize, td->ext->size);
333 /* ********************* edge (for crease) ***** */
335 static void createTransEdge(bContext *C, TransInfo *t) {
336 #if 0 // TRANSFORM_FIX_ME
337 TransData *td = NULL;
339 float mtx[3][3], smtx[3][3];
340 int count=0, countsel=0;
341 int propmode = t->flag & T_PROP_EDIT;
343 for(eed= em->edges.first; eed; eed= eed->next) {
345 if (eed->f & SELECT) countsel++;
346 if (propmode) count++;
360 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
362 Mat3CpyMat4(mtx, t->obedit->obmat);
365 for(eed= em->edges.first; eed; eed= eed->next) {
366 if(eed->h==0 && (eed->f & SELECT || propmode)) {
367 /* need to set center for center calculations */
368 VecAddf(td->center, eed->v1->co, eed->v2->co);
369 VecMulf(td->center, 0.5f);
373 td->flag= TD_SELECTED;
378 Mat3CpyMat3(td->smtx, smtx);
379 Mat3CpyMat3(td->mtx, mtx);
383 if (t->mode == TFM_BWEIGHT) {
384 td->val = &(eed->bweight);
385 td->ival = eed->bweight;
388 td->val = &(eed->crease);
389 td->ival = eed->crease;
398 /* ********************* pose mode ************* */
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 && (con->enforce!=0.0)) {
406 bKinematicConstraint *data= con->data;
410 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
417 static short apply_targetless_ik(Object *ob)
419 bPoseChannel *pchan, *parchan, *chanlist[256];
420 bKinematicConstraint *data;
421 int segcount, apply= 0;
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);
485 else if(parchan->bone->flag & BONE_NO_SCALE) {
486 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
490 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
492 Mat4Invert(imat, tmat);
495 Mat4CpyMat3(tmat, bone->bone_mat);
497 VECCOPY(tmat[3], bone->head);
498 Mat4Invert(imat, tmat);
501 Mat4MulMat4(rmat, parchan->pose_mat, imat);
503 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
505 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
507 Mat3CpyMat4(rmat3, rmat);
510 Mat3ToQuat(rmat3, parchan->quat);
512 /* for size, remove rotation */
513 /* causes problems with some constraints (so apply only if needed) */
514 if (data->flag & CONSTRAINT_IK_STRETCH) {
515 QuatToMat3(parchan->quat, qmat);
517 Mat3MulMat3(smat, rmat3, imat);
518 Mat3ToSize(smat, parchan->size);
521 /* causes problems with some constraints (e.g. childof), so disable this */
522 /* as it is IK shouldn't affect location directly */
523 /* VECCOPY(parchan->loc, rmat[3]); */
529 data->flag &= ~CONSTRAINT_IK_AUTO;
536 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
538 Bone *bone= pchan->bone;
539 float pmat[3][3], omat[3][3];
540 float cmat[3][3], tmat[3][3];
543 VECCOPY(vec, pchan->pose_mat[3]);
544 VECCOPY(td->center, vec);
547 td->flag = TD_SELECTED;
548 if (pchan->rotmode == PCHAN_ROT_QUAT)
550 td->flag |= TD_USEQUAT;
552 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
554 td->flag |= TD_NOCENTER;
557 if (bone->flag & BONE_TRANSFORM_CHILD)
559 td->flag |= TD_NOCENTER;
560 td->flag |= TD_NO_LOC;
563 td->protectflag= pchan->protectflag;
565 td->loc = pchan->loc;
566 VECCOPY(td->iloc, pchan->loc);
568 td->ext->size= pchan->size;
569 VECCOPY(td->ext->isize, pchan->size);
571 if (pchan->rotmode) {
572 td->ext->rot= pchan->eul;
575 VECCOPY(td->ext->irot, pchan->eul);
579 td->ext->quat= pchan->quat;
581 QUATCOPY(td->ext->iquat, pchan->quat);
584 /* proper way to get parent transform + own transform + constraints transform */
585 Mat3CpyMat4(omat, ob->obmat);
588 if(pchan->bone->flag & BONE_HINGE)
589 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
591 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
593 if (constraints_list_needinv(t, &pchan->constraints)) {
594 Mat3CpyMat4(tmat, pchan->constinv);
596 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
599 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
602 if (constraints_list_needinv(t, &pchan->constraints)) {
603 Mat3CpyMat4(tmat, pchan->constinv);
605 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
608 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
611 Mat3Inv(td->smtx, td->mtx);
613 /* for axismat we use bone's own transform */
614 Mat3CpyMat4(pmat, pchan->pose_mat);
615 Mat3MulMat3(td->axismtx, omat, pmat);
616 Mat3Ortho(td->axismtx);
618 if (t->mode==TFM_BONESIZE) {
619 bArmature *arm= t->poseobj->data;
621 if(arm->drawtype==ARM_ENVELOPE) {
623 td->val= &bone->dist;
624 td->ival= bone->dist;
627 // abusive storage of scale in the loc pointer :)
628 td->loc= &bone->xwidth;
629 VECCOPY (td->iloc, td->loc);
634 /* in this case we can do target-less IK grabbing */
635 if (t->mode==TFM_TRANSLATION) {
636 bKinematicConstraint *data= has_targetless_ik(pchan);
638 if(data->flag & CONSTRAINT_IK_TIP) {
639 VECCOPY(data->grabtarget, pchan->pose_tail);
642 VECCOPY(data->grabtarget, pchan->pose_head);
644 td->loc = data->grabtarget;
645 VECCOPY(td->iloc, td->loc);
646 data->flag |= CONSTRAINT_IK_AUTO;
648 /* only object matrix correction */
649 Mat3CpyMat3 (td->mtx, omat);
650 Mat3Inv (td->smtx, td->mtx);
654 /* store reference to first constraint */
655 td->con= pchan->constraints.first;
658 static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
660 Bone *bone= lb->first;
662 for(;bone;bone= bone->next) {
663 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
665 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
667 else if (bone->flag & BONE_TRANSFORM && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) && around == V3D_LOCAL)
669 bone->flag |= BONE_TRANSFORM_CHILD;
673 bone->flag &= ~BONE_TRANSFORM;
676 bone_children_clear_transflag(mode, around, &bone->childbase);
680 /* sets transform flags in the bones, returns total */
681 int count_set_pose_transflags(int *out_mode, short around, Object *ob)
683 bArmature *arm= ob->data;
686 int mode = *out_mode;
687 int hastranslation = 0;
690 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
692 if(bone->layer & arm->layer) {
693 if(bone->flag & BONE_SELECTED)
694 bone->flag |= BONE_TRANSFORM;
696 bone->flag &= ~BONE_TRANSFORM;
698 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
699 bone->flag &= ~BONE_TRANSFORM_CHILD;
703 /* make sure no bone can be transformed when a parent is transformed */
704 /* since pchans are depsgraph sorted, the parents are in beginning of list */
705 if(mode != TFM_BONESIZE) {
706 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
708 if(bone->flag & BONE_TRANSFORM)
709 bone_children_clear_transflag(mode, around, &bone->childbase);
712 /* now count, and check if we have autoIK or have to switch from translate to rotate */
715 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
717 if(bone->flag & BONE_TRANSFORM) {
721 if(mode == TFM_TRANSLATION) {
722 if( has_targetless_ik(pchan)==NULL ) {
723 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
724 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
727 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
736 /* if there are no translatable bones, do rotation */
737 if(mode == TFM_TRANSLATION && !hastranslation)
739 *out_mode = TFM_ROTATION;
746 /* -------- Auto-IK ---------- */
748 /* adjust pose-channel's auto-ik chainlen */
749 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
753 /* don't bother to search if no valid constraints */
754 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
757 /* check if pchan has ik-constraint */
758 for (con= pchan->constraints.first; con; con= con->next) {
759 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
760 bKinematicConstraint *data= con->data;
762 /* only accept if a temporary one (for auto-ik) */
763 if (data->flag & CONSTRAINT_IK_TEMP) {
764 /* chainlen is new chainlen, but is limited by maximum chainlen */
765 if ((chainlen==0) || (chainlen > data->max_rootbone))
766 data->rootbone= data->max_rootbone;
768 data->rootbone= chainlen;
774 /* change the chain-length of auto-ik */
775 void transform_autoik_update (TransInfo *t, short mode)
777 short *chainlen= &t->settings->autoik_chainlen;
780 /* mode determines what change to apply to chainlen */
782 /* mode=1 is from WHEELMOUSEDOWN... increases len */
785 else if (mode == -1) {
786 /* mode==-1 is from WHEELMOUSEUP... decreases len */
787 if (*chainlen > 0) (*chainlen)--;
790 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
791 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
794 /* apply to all pose-channels */
795 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
796 pchan_autoik_adjust(pchan, *chainlen);
800 /* frees temporal IKs */
801 static void pose_grab_with_ik_clear(Object *ob)
803 bKinematicConstraint *data;
805 bConstraint *con, *next;
807 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
808 /* clear all temporary lock flags */
809 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
811 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
812 /* remove all temporary IK-constraints added */
813 for (con= pchan->constraints.first; con; con= next) {
815 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
817 if (data->flag & CONSTRAINT_IK_TEMP) {
818 BLI_remlink(&pchan->constraints, con);
819 MEM_freeN(con->data);
823 pchan->constflag |= PCHAN_HAS_IK;
824 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
825 pchan->constflag |= PCHAN_HAS_TARGET;
831 /* adds the IK to pchan - returns if added */
832 static short pose_grab_with_ik_add(bPoseChannel *pchan)
834 bKinematicConstraint *data;
836 bConstraint *targetless = 0;
842 /* Rule: not if there's already an IK on this channel */
843 for (con= pchan->constraints.first; con; con= con->next) {
844 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
845 bKinematicConstraint *data= con->data;
846 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
848 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
849 if (con->enforce!=0.0f) {
850 targetless->flag |= CONSTRAINT_IK_AUTO;
854 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0f))
859 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
860 BLI_addtail(&pchan->constraints, con);
861 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
863 if (targetless) { /* if exists use values from last targetless IK-constraint as base */
864 *data = *((bKinematicConstraint*)targetless->data);
867 data->flag= CONSTRAINT_IK_TIP;
868 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
869 VECCOPY(data->grabtarget, pchan->pose_tail);
872 /* we include only a connected chain */
873 while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
874 /* here, we set ik-settings for bone from pchan->protectflag */
875 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
876 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
877 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
879 /* now we count this pchan as being included */
881 pchan= pchan->parent;
884 /* make a copy of maximum chain-length */
885 data->max_rootbone= data->rootbone;
890 /* bone is a candidate to get IK, but we don't do it if it has children connected */
891 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
894 short wentdeeper=0, added=0;
896 /* go deeper if children & children are connected */
897 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
898 if (bonec->flag & BONE_CONNECTED) {
900 added+= pose_grab_with_ik_children(pose, bonec);
904 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
906 added+= pose_grab_with_ik_add(pchan);
912 /* main call which adds temporal IK chains */
913 static short pose_grab_with_ik(Object *ob)
916 bPoseChannel *pchan, *parent;
920 if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
925 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
926 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
927 if (pchan->bone->layer & arm->layer) {
928 if (pchan->bone->flag & BONE_SELECTED) {
929 /* Rule: no IK for solitatry (unconnected) bones */
930 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
931 if (bonec->flag & BONE_CONNECTED) {
935 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
938 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
940 /* only adds if there's no IK yet (and no parent bone was selected) */
941 for (parent= pchan->parent; parent; parent= parent->parent) {
942 if (parent->bone->flag & BONE_SELECTED)
946 tot_ik += pose_grab_with_ik_add(pchan);
949 /* rule: go over the children and add IK to the tips */
950 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
956 return (tot_ik) ? 1 : 0;
960 /* only called with pose mode active object now */
961 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
966 TransDataExtension *tdx;
972 /* check validity of state */
973 arm= get_armature(ob);
974 if ((arm==NULL) || (ob->pose==NULL)) return;
976 if (arm->flag & ARM_RESTPOS) {
977 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
978 // XXX use transform operator reports
979 // BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
984 /* do we need to add temporal IK chains? */
985 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
986 ik_on= pose_grab_with_ik(ob);
987 if (ik_on) t->flag |= T_AUTOIK;
990 /* set flags and count total (warning, can change transform to rotate) */
991 t->total = count_set_pose_transflags(&t->mode, t->around, ob);
993 if(t->total == 0) return;
996 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
998 /* init trans data */
999 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
1000 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
1001 for(i=0; i<t->total; i++, td++, tdx++) {
1007 /* use pose channels to fill trans data */
1009 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1010 if (pchan->bone->flag & BONE_TRANSFORM) {
1011 add_pose_transdata(t, pchan, ob, td);
1016 if(td != (t->data+t->total)) {
1017 // XXX use transform operator reports
1018 // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error.");
1021 /* initialise initial auto=ik chainlen's? */
1022 if (ik_on) transform_autoik_update(t, 0);
1025 /* ********************* armature ************** */
1027 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1030 bArmature *arm= t->obedit->data;
1031 ListBase *edbo = arm->edbo;
1033 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1036 for (ebo = edbo->first; ebo; ebo = ebo->next)
1038 if(ebo->layer & arm->layer)
1040 if (t->mode==TFM_BONESIZE)
1042 if (ebo->flag & BONE_SELECTED)
1045 else if (t->mode==TFM_BONE_ROLL)
1047 if (ebo->flag & BONE_SELECTED)
1052 if (ebo->flag & BONE_TIPSEL)
1054 if (ebo->flag & BONE_ROOTSEL)
1060 if (!t->total) return;
1062 Mat3CpyMat4(mtx, t->obedit->obmat);
1065 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1067 for (ebo = edbo->first; ebo; ebo = ebo->next)
1069 ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1071 if(ebo->layer & arm->layer) {
1072 if (t->mode==TFM_BONE_ENVELOPE)
1074 if (ebo->flag & BONE_ROOTSEL)
1076 td->val= &ebo->rad_head;
1079 VECCOPY (td->center, ebo->head);
1080 td->flag= TD_SELECTED;
1082 Mat3CpyMat3(td->smtx, smtx);
1083 Mat3CpyMat3(td->mtx, mtx);
1091 if (ebo->flag & BONE_TIPSEL)
1093 td->val= &ebo->rad_tail;
1095 VECCOPY (td->center, ebo->tail);
1096 td->flag= TD_SELECTED;
1098 Mat3CpyMat3(td->smtx, smtx);
1099 Mat3CpyMat3(td->mtx, mtx);
1109 else if (t->mode==TFM_BONESIZE)
1111 if (ebo->flag & BONE_SELECTED) {
1112 if(arm->drawtype==ARM_ENVELOPE)
1115 td->val= &ebo->dist;
1116 td->ival= ebo->dist;
1120 // abusive storage of scale in the loc pointer :)
1121 td->loc= &ebo->xwidth;
1122 VECCOPY (td->iloc, td->loc);
1125 VECCOPY (td->center, ebo->head);
1126 td->flag= TD_SELECTED;
1128 /* use local bone matrix */
1129 VecSubf(delta, ebo->tail, ebo->head);
1130 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1131 Mat3MulMat3(td->mtx, mtx, bonemat);
1132 Mat3Inv(td->smtx, td->mtx);
1134 Mat3CpyMat3(td->axismtx, td->mtx);
1135 Mat3Ortho(td->axismtx);
1143 else if (t->mode==TFM_BONE_ROLL)
1145 if (ebo->flag & BONE_SELECTED)
1148 td->val= &(ebo->roll);
1149 td->ival= ebo->roll;
1151 VECCOPY (td->center, ebo->head);
1152 td->flag= TD_SELECTED;
1162 if (ebo->flag & BONE_TIPSEL)
1164 VECCOPY (td->iloc, ebo->tail);
1165 VECCOPY (td->center, td->iloc);
1167 td->flag= TD_SELECTED;
1168 if (ebo->flag & BONE_EDITMODE_LOCKED)
1169 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1171 Mat3CpyMat3(td->smtx, smtx);
1172 Mat3CpyMat3(td->mtx, mtx);
1174 VecSubf(delta, ebo->tail, ebo->head);
1175 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1177 if ((ebo->flag & BONE_ROOTSEL) == 0)
1188 if (ebo->flag & BONE_ROOTSEL)
1190 VECCOPY (td->iloc, ebo->head);
1191 VECCOPY (td->center, td->iloc);
1193 td->flag= TD_SELECTED;
1194 if (ebo->flag & BONE_EDITMODE_LOCKED)
1195 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1197 Mat3CpyMat3(td->smtx, smtx);
1198 Mat3CpyMat3(td->mtx, mtx);
1200 VecSubf(delta, ebo->tail, ebo->head);
1201 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1203 td->extra = ebo; /* to fix roll */
1216 /* ********************* meta elements ********* */
1218 static void createTransMBallVerts(bContext *C, TransInfo *t)
1224 TransDataExtension *tx;
1225 float mtx[3][3], smtx[3][3];
1226 int count=0, countsel=0;
1227 int propmode = t->flag & T_PROP_EDIT;
1230 for(ml= editelems.first; ml; ml= ml->next) {
1231 if(ml->flag & SELECT) countsel++;
1232 if(propmode) count++;
1235 /* note: in prop mode we need at least 1 selected */
1236 if (countsel==0) return;
1238 if(propmode) t->total = count;
1239 else t->total = countsel;
1241 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1242 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1244 Mat3CpyMat4(mtx, t->obedit->obmat);
1247 for(ml= editelems.first; ml; ml= ml->next) {
1248 if(propmode || (ml->flag & SELECT)) {
1250 VECCOPY(td->iloc, td->loc);
1251 VECCOPY(td->center, td->loc);
1253 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1254 else td->flag= TD_USEQUAT;
1256 Mat3CpyMat3(td->smtx, smtx);
1257 Mat3CpyMat3(td->mtx, mtx);
1262 /* Radius of MetaElem (mass of MetaElem influence) */
1263 if(ml->flag & MB_SCALE_RAD){
1272 /* expx/expy/expz determine "shape" of some MetaElem types */
1273 tx->size = &ml->expx;
1274 tx->isize[0] = ml->expx;
1275 tx->isize[1] = ml->expy;
1276 tx->isize[2] = ml->expz;
1278 /* quat is used for rotation of MetaElem */
1279 tx->quat = ml->quat;
1280 QUATCOPY(tx->iquat, ml->quat);
1291 /* ********************* curve/surface ********* */
1293 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1294 TransData *td, *td_near = NULL;
1295 for (td = head; td<=tail; td++) {
1296 if (td->flag & TD_SELECTED) {
1302 dist = VecLenf(td_near->center, td->center);
1303 if (dist < (td-1)->dist) {
1304 td->dist = (td-1)->dist;
1311 td->dist = MAXFLOAT;
1312 td->flag |= TD_NOTCONNECTED;
1316 for (td = tail; td>=head; td--) {
1317 if (td->flag & TD_SELECTED) {
1323 dist = VecLenf(td_near->center, td->center);
1324 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1325 td->flag &= ~TD_NOTCONNECTED;
1326 if (dist < (td+1)->dist) {
1327 td->dist = (td+1)->dist;
1337 /* Utility function for getting the handle data from bezier's */
1338 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1339 TransDataCurveHandleFlags *hdata;
1340 td->flag |= TD_BEZTRIPLE;
1341 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1342 hdata->ih1 = bezt->h1;
1343 hdata->h1 = &bezt->h1;
1344 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1345 hdata->h2 = &bezt->h2;
1349 static void createTransCurveVerts(bContext *C, TransInfo *t)
1351 Object *obedit= CTX_data_edit_object(C);
1352 Curve *cu= obedit->data;
1353 TransData *td = NULL;
1357 float mtx[3][3], smtx[3][3];
1359 int count=0, countsel=0;
1360 int propmode = t->flag & T_PROP_EDIT;
1363 if(cu->editnurb==NULL) return;
1365 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1366 for(nu= cu->editnurb->first; nu; nu= nu->next) {
1367 if((nu->type & 7)==CU_BEZIER) {
1368 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1370 if (G.f & G_HIDDENHANDLES) {
1371 if(bezt->f2 & SELECT) countsel+=3;
1372 if(propmode) count+= 3;
1374 if(bezt->f1 & SELECT) countsel++;
1375 if(bezt->f2 & SELECT) countsel++;
1376 if(bezt->f3 & SELECT) countsel++;
1377 if(propmode) count+= 3;
1383 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1385 if(propmode) count++;
1386 if(bp->f1 & SELECT) countsel++;
1391 /* note: in prop mode we need at least 1 selected */
1392 if (countsel==0) return;
1394 if(propmode) t->total = count;
1395 else t->total = countsel;
1396 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1398 Mat3CpyMat4(mtx, t->obedit->obmat);
1402 for(nu= cu->editnurb->first; nu; nu= nu->next) {
1403 if((nu->type & 7)==CU_BEZIER) {
1404 TransData *head, *tail;
1406 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1408 TransDataCurveHandleFlags *hdata = NULL;
1411 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1412 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1414 VECCOPY(td->iloc, bezt->vec[0]);
1415 td->loc= bezt->vec[0];
1416 VECCOPY(td->center, bezt->vec[1]);
1417 if (G.f & G_HIDDENHANDLES) {
1418 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1421 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1428 hdata = initTransDataCurveHandes(td, bezt);
1430 Mat3CpyMat3(td->smtx, smtx);
1431 Mat3CpyMat3(td->mtx, mtx);
1438 /* This is the Curve Point, the other two are handles */
1439 if(propmode || (bezt->f2 & SELECT)) {
1440 VECCOPY(td->iloc, bezt->vec[1]);
1441 td->loc= bezt->vec[1];
1442 VECCOPY(td->center, td->loc);
1443 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1448 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1449 td->val = &(bezt->radius);
1450 td->ival = bezt->radius;
1451 } else if (t->mode==TFM_TILT) {
1452 td->val = &(bezt->alfa);
1453 td->ival = bezt->alfa;
1458 Mat3CpyMat3(td->smtx, smtx);
1459 Mat3CpyMat3(td->mtx, mtx);
1461 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1462 /* If the middle is selected but the sides arnt, this is needed */
1463 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1464 hdata = initTransDataCurveHandes(td, bezt);
1472 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1473 ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1475 VECCOPY(td->iloc, bezt->vec[2]);
1476 td->loc= bezt->vec[2];
1477 VECCOPY(td->center, bezt->vec[1]);
1478 if (G.f & G_HIDDENHANDLES) {
1479 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1482 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1489 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1490 hdata = initTransDataCurveHandes(td, bezt);
1493 Mat3CpyMat3(td->smtx, smtx);
1494 Mat3CpyMat3(td->mtx, mtx);
1501 else if (propmode && head != tail) {
1502 calc_distanceCurveVerts(head, tail-1);
1506 if (propmode && head != tail)
1507 calc_distanceCurveVerts(head, tail-1);
1509 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1510 * but for now just dont change handle types */
1511 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1512 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1515 TransData *head, *tail;
1517 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1519 if(propmode || (bp->f1 & SELECT)) {
1520 VECCOPY(td->iloc, bp->vec);
1522 VECCOPY(td->center, td->loc);
1523 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1528 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1529 td->val = &(bp->radius);
1530 td->ival = bp->radius;
1532 td->val = &(bp->alfa);
1533 td->ival = bp->alfa;
1536 Mat3CpyMat3(td->smtx, smtx);
1537 Mat3CpyMat3(td->mtx, mtx);
1544 else if (propmode && head != tail) {
1545 calc_distanceCurveVerts(head, tail-1);
1549 if (propmode && head != tail)
1550 calc_distanceCurveVerts(head, tail-1);
1555 /* ********************* lattice *************** */
1557 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1559 Lattice *latt = ((Lattice*)t->obedit->data)->editlatt;
1560 TransData *td = NULL;
1562 float mtx[3][3], smtx[3][3];
1564 int count=0, countsel=0;
1565 int propmode = t->flag & T_PROP_EDIT;
1568 a = latt->pntsu * latt->pntsv * latt->pntsw;
1571 if(bp->f1 & SELECT) countsel++;
1572 if(propmode) count++;
1577 /* note: in prop mode we need at least 1 selected */
1578 if (countsel==0) return;
1580 if(propmode) t->total = count;
1581 else t->total = countsel;
1582 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1584 Mat3CpyMat4(mtx, t->obedit->obmat);
1589 a = latt->pntsu * latt->pntsv * latt->pntsw;
1591 if(propmode || (bp->f1 & SELECT)) {
1593 VECCOPY(td->iloc, bp->vec);
1595 VECCOPY(td->center, td->loc);
1596 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1598 Mat3CpyMat3(td->smtx, smtx);
1599 Mat3CpyMat3(td->mtx, mtx);
1613 /* ******************* particle edit **************** */
1614 static void createTransParticleVerts(bContext *C, TransInfo *t)
1616 TransData *td = NULL;
1617 TransDataExtension *tx;
1618 Base *base = CTX_data_active_base(C);
1619 Object *ob = CTX_data_active_object(C);
1620 ParticleSystem *psys = PE_get_current(t->scene, ob);
1621 ParticleSystemModifierData *psmd = NULL;
1622 ParticleEditSettings *pset = PE_settings(t->scene);
1623 ParticleData *pa = NULL;
1625 ParticleEditKey *key;
1627 int i,k, totpart, transformparticle;
1628 int count = 0, hasselected = 0;
1629 int propmode = t->flag & T_PROP_EDIT;
1631 if(psys==NULL || t->settings->particle.selectmode==SCE_SELECT_PATH) return;
1633 psmd = psys_get_modifier(ob,psys);
1636 totpart = psys->totpart;
1637 base->flag |= BA_HAS_RECALC_DATA;
1639 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1640 pa->flag &= ~PARS_TRANSFORM;
1641 transformparticle= 0;
1643 if((pa->flag & PARS_HIDE)==0) {
1644 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1645 if((key->flag&PEK_HIDE)==0) {
1646 if(key->flag&PEK_SELECT) {
1648 transformparticle= 1;
1651 transformparticle= 1;
1656 if(transformparticle) {
1657 count += pa->totkey;
1658 pa->flag |= PARS_TRANSFORM;
1662 /* note: in prop mode we need at least 1 selected */
1663 if (hasselected==0) return;
1666 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1668 if(t->mode == TFM_BAKE_TIME)
1669 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1675 Mat4Invert(ob->imat,ob->obmat);
1677 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1678 TransData *head, *tail;
1681 if(!(pa->flag & PARS_TRANSFORM)) continue;
1683 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1685 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1686 VECCOPY(key->world_co, key->co);
1687 Mat4MulVecfl(mat, key->world_co);
1688 td->loc = key->world_co;
1690 VECCOPY(td->iloc, td->loc);
1691 VECCOPY(td->center, td->loc);
1693 if(key->flag & PEK_SELECT)
1694 td->flag |= TD_SELECTED;
1696 td->flag |= TD_SKIP;
1701 /* don't allow moving roots */
1702 if(k==0 && pset->flag & PE_LOCK_FIRST)
1703 td->protectflag |= OB_LOCK_LOC;
1708 if(t->mode == TFM_BAKE_TIME) {
1709 td->val = key->time;
1710 td->ival = *(key->time);
1711 /* abuse size and quat for min/max values */
1712 td->flag |= TD_NO_EXT;
1713 if(k==0) tx->size = 0;
1714 else tx->size = (key - 1)->time;
1716 if(k == pa->totkey - 1) tx->quat = 0;
1717 else tx->quat = (key + 1)->time;
1725 if (propmode && head != tail)
1726 calc_distanceCurveVerts(head, tail - 1);
1730 void flushTransParticles(TransInfo *t)
1732 Scene *scene = t->scene;
1734 ParticleSystem *psys = PE_get_current(scene, ob);
1735 ParticleSystemModifierData *psmd;
1737 ParticleEditKey *key;
1739 float mat[4][4], imat[4][4], co[3];
1740 int i, k, propmode = t->flag & T_PROP_EDIT;
1742 psmd = psys_get_modifier(ob, psys);
1744 /* we do transform in world space, so flush world space position
1745 * back to particle local space */
1747 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1748 if(!(pa->flag & PARS_TRANSFORM)) continue;
1750 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1751 Mat4Invert(imat,mat);
1753 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1754 VECCOPY(co, key->world_co);
1755 Mat4MulVecfl(imat, co);
1757 /* optimization for proportional edit */
1758 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1759 VECCOPY(key->co, co);
1760 pa->flag |= PARS_EDIT_RECALC;
1765 PE_update_object(scene, OBACT, 1);
1768 /* ********************* mesh ****************** */
1770 /* proportional distance based on connectivity */
1771 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1772 #define E_NEAR(a) (nears[((a)->tmp.l)])
1773 #define THRESHOLD 0.0001f
1774 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1780 /* f2 flag is used for 'selection' */
1781 /* tmp.l is offset on scratch array */
1782 for(eve= em->verts.first; eve; eve= eve->next) {
1786 if(eve->f & SELECT) {
1789 E_VEC(eve)[0] = 0.0f;
1790 E_VEC(eve)[1] = 0.0f;
1791 E_VEC(eve)[2] = 0.0f;
1800 /* Floodfill routine */
1802 At worst this is n*n of complexity where n is number of edges
1803 Best case would be n if the list is ordered perfectly.
1804 Estimate is n log n in average (so not too bad)
1809 for(eed= em->edges.first; eed; eed= eed->next) {
1811 EditVert *v1= eed->v1, *v2= eed->v2;
1812 float *vec2 = E_VEC(v2);
1813 float *vec1 = E_VEC(v1);
1815 if (v1->f2 + v2->f2 == 4)
1821 float len1 = VecLength(vec1);
1822 float len2 = VecLength(vec2);
1824 /* for v2 if not selected */
1826 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1827 lenn = VecLength(nvec);
1829 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1830 VECCOPY(vec2, nvec);
1831 E_NEAR(v2) = E_NEAR(v1);
1835 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1836 VECCOPY(vec2, vec1);
1837 E_NEAR(v2) = E_NEAR(v1);
1841 /* for v1 if not selected */
1843 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1844 lenn = VecLength(nvec);
1846 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1847 VECCOPY(vec1, nvec);
1848 E_NEAR(v1) = E_NEAR(v2);
1852 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1853 VECCOPY(vec1, vec2);
1854 E_NEAR(v1) = E_NEAR(v2);
1861 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1863 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1864 VECCOPY(vec2, vec1);
1866 E_NEAR(v2) = E_NEAR(v1);
1872 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1874 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1875 VECCOPY(vec1, vec2);
1877 E_NEAR(v1) = E_NEAR(v2);
1885 /* loop-in-a-loop I know, but we need it! (ton) */
1886 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1890 for(efa= em->faces.first; efa; efa= efa->next)
1892 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1895 VECCOPY(cent, efa->cent);
1899 //way to overwrite what data is edited with transform
1900 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1901 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1905 // td->loc = key->co;
1909 VECCOPY(td->center, td->loc);
1910 if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1911 get_face_center(td->center, em, eve);
1912 VECCOPY(td->iloc, td->loc);
1915 VECCOPY(td->axismtx[2], eve->no);
1921 td->axismtx[1][2] = 0.0f;
1927 if (t->mode == TFM_BWEIGHT) {
1928 td->val = &(eve->bweight);
1929 td->ival = eve->bweight;
1933 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1935 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1937 float *vec = userData;
1943 static int modifiers_disable_subsurf_temporary(Object *ob)
1948 for(md=ob->modifiers.first; md; md=md->next)
1949 if(md->type==eModifierType_Subsurf)
1950 if(md->mode & eModifierMode_OnCage) {
1951 md->mode ^= eModifierMode_DisableTemporary;
1958 /* disable subsurf temporal, get mapped cos, and enable it */
1959 static float *get_crazy_mapped_editverts(TransInfo *t)
1961 Mesh *me= t->obedit->data;
1965 /* disable subsurf temporal, get mapped cos, and enable it */
1966 if(modifiers_disable_subsurf_temporary(t->obedit)) {
1967 /* need to make new derivemesh */
1968 makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1971 /* now get the cage */
1972 dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1974 vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->totvert, "vertexcos map");
1975 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1979 /* set back the flag, no new cage needs to be built, transform does it */
1980 modifiers_disable_subsurf_temporary(t->obedit);
1985 #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])
1986 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1988 float vecu[3], vecv[3];
1991 TAN_MAKE_VEC(vecu, v1, v2);
1992 TAN_MAKE_VEC(vecv, v1, v3);
1993 triatoquat(v1, vecu, vecv, q1);
1995 TAN_MAKE_VEC(vecu, def1, def2);
1996 TAN_MAKE_VEC(vecv, def1, def3);
1997 triatoquat(def1, vecu, vecv, q2);
1999 QuatSub(quat, q2, q1);
2003 static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
2005 EditVert *eve, *prev;
2007 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2010 /* two abused locations in vertices */
2011 for(eve= em->verts.first; eve; eve= eve->next, index++) {
2013 eve->prev= (EditVert *)index;
2016 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2017 for(efa= em->faces.first; efa; efa= efa->next) {
2019 /* retrieve mapped coordinates */
2020 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2021 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2022 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2024 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2025 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2026 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2028 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2029 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2030 efa->v2->tmp.p= (void*)quats;
2035 v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2036 co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2038 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2039 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2040 efa->v1->tmp.p= (void*)quats;
2043 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2044 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2045 efa->v3->tmp.p= (void*)quats;
2048 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2049 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2050 efa->v4->tmp.p= (void*)quats;
2055 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2056 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2057 efa->v1->tmp.p= (void*)quats;
2060 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2061 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2062 efa->v3->tmp.p= (void*)quats;
2068 /* restore abused prev pointer */
2069 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2074 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2080 tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2082 for (i=0,v=bm->verts.first;v;v=v->next) {
2083 if ( (vtd = BME_get_transdata(td,v)) ) {
2084 tob->loc = vtd->loc;
2085 tob->val = &vtd->factor;
2086 VECCOPY(tob->iloc,vtd->co);
2087 VECCOPY(tob->center,vtd->org);
2088 VECCOPY(tob->axismtx[0],vtd->vec);
2089 tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2094 /* since td is a memarena, it can hold more transdata than actual elements
2095 * (i.e. we can't depend on td->len to determine the number of actual elements) */
2099 static void createTransEditVerts(bContext *C, TransInfo *t)
2101 ToolSettings *ts = CTX_data_tool_settings(C);
2102 TransData *tob = NULL;
2103 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2105 EditVert **nears = NULL;
2106 EditVert *eve_act = NULL;
2107 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2108 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2109 int count=0, countsel=0, a, totleft;
2110 int propmode = t->flag & T_PROP_EDIT;
2113 if (t->flag & T_MIRROR)
2118 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2119 if(ts->selectmode & SCE_SELECT_VERTEX) {
2120 for(eve= em->verts.first; eve; eve= eve->next) {
2121 if(eve->h==0 && (eve->f & SELECT))
2127 else if(ts->selectmode & SCE_SELECT_EDGE) {
2129 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2130 for(eed= em->edges.first; eed; eed= eed->next) {
2131 if(eed->h==0 && (eed->f & SELECT))
2132 eed->v1->f1= eed->v2->f1= SELECT;
2137 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2138 for(efa= em->faces.first; efa; efa= efa->next) {
2139 if(efa->h==0 && (efa->f & SELECT)) {
2140 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2141 if(efa->v4) efa->v4->f1= SELECT;
2146 /* now we can count */
2147 for(eve= em->verts.first; eve; eve= eve->next) {
2149 if(eve->f1) countsel++;
2150 if(propmode) count++;
2154 /* note: in prop mode we need at least 1 selected */
2155 if (countsel==0) return;
2158 if (em->selected.last) {
2159 EditSelection *ese = em->selected.last;
2160 if ( ese->type == EDITVERT ) {
2161 eve_act = (EditVert *)ese->data;
2169 /* allocating scratch arrays */
2170 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2171 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2173 else t->total = countsel;
2174 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2176 Mat3CpyMat4(mtx, t->obedit->obmat);
2179 if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2181 /* detect CrazySpace [tm] */
2183 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2184 if(modifiers_isDeformed(t->scene, t->obedit)) {
2185 /* check if we can use deform matrices for modifier from the
2186 start up to stack, they are more accurate than quats */
2187 totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
2189 /* if we still have more modifiers, also do crazyspace
2190 correction with quats, relative to the coordinates after
2191 the modifiers that support deform matrices (defcos) */
2193 mappedcos= get_crazy_mapped_editverts(t);
2194 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2195 set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2197 MEM_freeN(mappedcos);
2206 /* find out which half we do */
2208 for (eve=em->verts.first; eve; eve=eve->next) {
2209 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2217 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2219 if(propmode || eve->f1) {
2220 VertsToTransData(t, tob, em, eve);
2223 if(eve->f1) tob->flag |= TD_SELECTED;
2226 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2231 VECCOPY(vec, E_VEC(eve));
2232 Mat3MulVecfl(mtx, vec);
2233 tob->dist= VecLength(vec);
2236 tob->flag |= TD_NOTCONNECTED;
2237 tob->dist = MAXFLOAT;
2242 if(defmats || (quats && eve->tmp.p)) {
2243 float mat[3][3], imat[3][3], qmat[3][3];
2245 /* use both or either quat and defmat correction */
2246 if(quats && eve->tmp.f) {
2247 QuatToMat3(eve->tmp.p, qmat);
2250 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2251 NULL, NULL, NULL, NULL, NULL);
2253 Mat3MulMat3(mat, mtx, qmat);
2256 Mat3MulMat3(mat, mtx, defmats[a]);
2260 Mat3CpyMat3(tob->smtx, imat);
2261 Mat3CpyMat3(tob->mtx, mat);
2264 Mat3CpyMat3(tob->smtx, smtx);
2265 Mat3CpyMat3(tob->mtx, mtx);
2269 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2270 EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */
2271 if(vmir != eve) tob->extra = vmir;
2281 /* crazy space free */
2288 /* *** NODE EDITOR *** */
2289 void flushTransNodes(TransInfo *t)
2294 /* flush to 2d vector from internally used 3d vector */
2295 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2296 td->loc2d[0]= td->loc[0];
2297 td->loc2d[1]= td->loc[1];
2301 /* *** SEQUENCE EDITOR *** */
2302 void flushTransSeq(TransInfo *t)
2304 ListBase *seqbasep= seq_give_editing(t->scene, FALSE)->seqbasep; /* Editing null check alredy done */
2306 TransData *td= t->data;
2307 TransData2D *td2d= t->data2d;
2308 TransDataSeq *tdsq= NULL;
2313 /* prevent updating the same seq twice
2314 * if the transdata order is changed this will mess up
2315 * but so will TransDataSeq */
2316 Sequence *seq_prev= NULL;
2318 /* flush to 2d vector from internally used 3d vector */
2319 for(a=0; a<t->total; a++, td++, td2d++) {
2321 tdsq= (TransDataSeq *)td->extra;
2323 new_frame= (int)(td2d->loc[0] + 0.5f);
2325 switch (tdsq->sel_flag) {
2327 if (seq->type != SEQ_META && seq_tx_test(seq)) /* for meta's, their children move */
2328 seq->start= new_frame - tdsq->start_offset;
2330 if (seq->depth==0) {
2331 seq->machine= (int)(td2d->loc[1] + 0.5f);
2332 CLAMP(seq->machine, 1, MAXSEQ);
2335 case SEQ_LEFTSEL: /* no vertical transform */
2336 seq_tx_set_final_left(seq, new_frame);
2337 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2338 fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2340 case SEQ_RIGHTSEL: /* no vertical transform */
2341 seq_tx_set_final_right(seq, new_frame);
2342 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2343 fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2347 if (seq != seq_prev) {
2349 /* Calculate this strip and all nested strips
2350 * children are ALWAYS transformed first
2351 * so we dont need to do this in another loop. */
2354 /* test overlap, displayes red outline */
2355 seq->flag &= ~SEQ_OVERLAP;
2356 if( seq_test_overlap(seqbasep, seq) ) {
2357 seq->flag |= SEQ_OVERLAP;
2361 calc_sequence_disp(seq);
2367 if (t->mode == TFM_TIME_TRANSLATE) { /* originally TFM_TIME_EXTEND, transform changes */
2368 /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
2369 seq= seqbasep->first;
2372 if (seq->type == SEQ_META && seq->flag & SELECT)
2379 /* ********************* UV ****************** */
2381 static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
2385 ED_space_image_uv_aspect(sima, &aspx, &aspy);
2387 /* uv coords are scaled by aspects. this is needed for rotations and
2388 proportional editing to be consistent with the stretchted uv coords
2389 that are displayed. this also means that for display and numinput,
2390 and when the the uv coords are flushed, these are converted each time */
2391 td2d->loc[0] = uv[0]*aspx;
2392 td2d->loc[1] = uv[1]*aspy;
2393 td2d->loc[2] = 0.0f;
2397 td->loc = td2d->loc;
2398 VECCOPY(td->center, td->loc);
2399 VECCOPY(td->iloc, td->loc);
2401 memset(td->axismtx, 0, sizeof(td->axismtx));
2402 td->axismtx[2][2] = 1.0f;
2404 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2407 td->flag |= TD_SELECTED;
2417 static void createTransUVs(bContext *C, TransInfo *t)
2419 SpaceImage *sima = (SpaceImage*)CTX_wm_space_data(C);
2420 Image *ima = CTX_data_edit_image(C);
2421 Scene *scene = CTX_data_scene(C);
2422 TransData *td = NULL;
2423 TransData2D *td2d = NULL;
2425 int count=0, countsel=0;
2426 int propmode = t->flag & T_PROP_EDIT;
2428 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2431 if(!ED_uvedit_test(t->obedit)) return;
2434 for (efa= em->faces.first; efa; efa= efa->next) {
2435 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2437 if(uvedit_face_visible(scene, ima, efa, tf)) {
2440 if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++;
2441 if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++;
2442 if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++;
2443 if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++;
2445 count += (efa->v4)? 4: 3;
2451 /* note: in prop mode we need at least 1 selected */
2452 if (countsel==0) return;
2454 t->total= (propmode)? count: countsel;
2455 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2456 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2457 treated just as if they were 3d verts */
2458 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2460 if(sima->flag & SI_CLIP_UV)
2461 t->flag |= T_CLIP_UV;
2466 for (efa= em->faces.first; efa; efa= efa->next) {
2467 if ((tf=(MTFace *)efa->tmp.p)) {
2469 UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0));
2470 UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1));
2471 UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2));
2473 UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3));
2475 if(uvedit_uv_selected(scene, efa, tf, 0)) UVsToTransData(sima, td++, td2d++, tf->uv[0], 1);
2476 if(uvedit_uv_selected(scene, efa, tf, 1)) UVsToTransData(sima, td++, td2d++, tf->uv[1], 1);
2477 if(uvedit_uv_selected(scene, efa, tf, 2)) UVsToTransData(sima, td++, td2d++, tf->uv[2], 1);
2478 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) UVsToTransData(sima, td++, td2d++, tf->uv[3], 1);
2483 if (sima->flag & SI_LIVE_UNWRAP)
2484 ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
2487 void flushTransUVs(TransInfo *t)
2489 SpaceImage *sima = t->sa->spacedata.first;
2491 int a, width, height;
2492 float aspx, aspy, invx, invy;
2494 ED_space_image_uv_aspect(sima, &aspx, &aspy);
2495 ED_space_image_size(sima, &width, &height);
2499 /* flush to 2d vector from internally used 3d vector */
2500 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2501 td->loc2d[0]= td->loc[0]*invx;
2502 td->loc2d[1]= td->loc[1]*invy;
2504 if((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2505 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2506 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2511 int clipUVTransform(TransInfo *t, float *vec, int resize)
2514 int a, clipx=1, clipy=1;
2515 float aspx, aspy, min[2], max[2];
2517 ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
2518 min[0]= min[1]= 0.0f;
2519 max[0]= aspx; max[1]= aspy;
2521 for(a=0, td= t->data; a<t->total; a++, td++) {
2522 DO_MINMAX2(td->loc, min, max);
2526 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2527 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2528 else if(max[0] > aspx && t->center[0] < aspx)
2529 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2533 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2534 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2535 else if(max[1] > aspy && t->center[1] < aspy)
2536 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2543 else if(max[0] > aspx)
2544 vec[0] -= max[0]-aspx;
2550 else if(max[1] > aspy)
2551 vec[1] -= max[1]-aspy;
2556 return (clipx || clipy);
2559 /* ********************* ANIMATION EDITORS (GENERAL) ************************* */
2561 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
2562 static short FrameOnMouseSide(char side, float frame, float cframe)
2564 /* both sides, so it doesn't matter */
2565 if (side == 'B') return 1;
2567 /* only on the named side */
2569 return (frame >= cframe) ? 1 : 0;
2571 return (frame <= cframe) ? 1 : 0;
2574 /* ********************* NLA EDITOR ************************* */
2576 static void createTransNlaData(bContext *C, TransInfo *t)
2578 Scene *scene= CTX_data_scene(C);
2579 TransData *td = NULL;
2580 TransDataNla *tdn = NULL;
2583 ListBase anim_data = {NULL, NULL};
2590 /* determine what type of data we are operating on */
2591 if (ANIM_animdata_get_context(C, &ac) == 0)
2595 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
2596 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2598 /* which side of the current frame should be allowed */
2599 if (t->mode == TFM_TIME_EXTEND) {
2600 /* only side on which mouse is gets transformed */
2601 float xmouse, ymouse;
2603 UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
2604 side = (xmouse > CFRA) ? 'R' : 'L'; // XXX use t->frame_side
2607 /* normal transform - both sides of current frame are considered */
2611 /* loop 1: count how many strips are selected (consider each strip as 2 points) */
2612 for (ale= anim_data.first; ale; ale= ale->next) {
2613 NlaTrack *nlt= (NlaTrack *)ale->data;
2616 /* make some meta-strips for chains of selected strips */
2617 BKE_nlastrips_make_metas(&nlt->strips, 1);
2619 /* only consider selected strips */
2620 for (strip= nlt->strips.first; strip; strip= strip->next) {
2621 // TODO: we can make strips have handles later on...
2622 /* transition strips can't get directly transformed */
2623 if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2624 if (strip->flag & NLASTRIP_FLAG_SELECT) {
2625 if (FrameOnMouseSide(side, strip->start, (float)CFRA)) count++;
2626 if (FrameOnMouseSide(side, strip->end, (float)CFRA)) count++;
2632 /* stop if trying to build list if nothing selected */
2634 /* cleanup temp list */
2635 BLI_freelistN(&anim_data);
2639 /* allocate memory for data */
2642 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)");
2644 t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)");
2647 /* loop 2: build transdata array */
2648 for (ale= anim_data.first; ale; ale= ale->next) {
2649 /* only if a real NLA-track */
2650 if (ale->type == ANIMTYPE_NLATRACK) {
2651 NlaTrack *nlt= (NlaTrack *)ale->data;
2654 /* only consider selected strips */
2655 for (strip= nlt->strips.first; strip; strip= strip->next) {
2656 // TODO: we can make strips have handles later on...
2657 /* transition strips can't get directly transformed */
2658 if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2659 if (strip->flag & NLASTRIP_FLAG_SELECT) {
2660 /* our transform data is constructed as follows:
2661 * - only the handles on the right side of the current-frame get included
2662 * - td structs are transform-elements operated on by the transform system
2663 * and represent a single handle. The storage/pointer used (val or loc) depends on
2664 * whether we're scaling or transforming. Ultimately though, the handles
2665 * the td writes to will simply be a dummy in tdn
2666 * - for each strip being transformed, a single tdn struct is used, so in some
2667 * cases, there will need to be 1 of these tdn elements in the array skipped...
2669 float center[3], yval;
2671 /* firstly, init tdn settings */
2673 tdn->oldTrack= tdn->nlt= nlt;
2675 tdn->trackIndex= BLI_findindex(&nlt->strips, strip);
2677 yval= (float)(tdn->trackIndex * NLACHANNEL_STEP);
2679 tdn->h1[0]= strip->start;
2681 tdn->h2[0]= strip->end;
2684 center[0]= (float)CFRA;
2688 /* set td's based on which handles are applicable */
2689 if (FrameOnMouseSide(side, strip->start, (float)CFRA))
2691 /* just set tdn to assume that it only has one handle for now */
2694 /* now, link the transform data up to this data */
2695 if (t->mode == TFM_TRANSLATION) {
2697 VECCOPY(td->iloc, tdn->h1);
2699 /* store all the other gunk that is required by transform */
2700 VECCOPY(td->center, center);
2701 memset(td->axismtx, 0, sizeof(td->axismtx));
2702 td->axismtx[2][2] = 1.0f;
2704 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2706 td->flag |= TD_SELECTED;
2713 td->val= &tdn->h1[0];
2714 td->ival= tdn->h1[0];
2720 if (FrameOnMouseSide(side, strip->end, (float)CFRA))
2722 /* if tdn is already holding the start handle, then we're doing both, otherwise, only end */
2723 tdn->handle= (tdn->handle) ? 2 : 1;
2725 /* now, link the transform data up to this data */
2726 if (t->mode == TFM_TRANSLATION) {
2728 VECCOPY(td->iloc, tdn->h2);