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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 *****
30 /** \file blender/editors/transform/transform_conversions.c
31 * \ingroup edtransform
43 #include "DNA_anim_types.h"
44 #include "DNA_armature_types.h"
45 #include "DNA_lattice_types.h"
46 #include "DNA_meta_types.h"
47 #include "DNA_node_types.h"
48 #include "DNA_screen_types.h"
49 #include "DNA_space_types.h"
50 #include "DNA_sequence_types.h"
51 #include "DNA_view3d_types.h"
52 #include "DNA_constraint_types.h"
53 #include "DNA_scene_types.h"
54 #include "DNA_meshdata_types.h"
55 #include "DNA_gpencil_types.h"
57 #include "MEM_guardedalloc.h"
59 #include "BKE_action.h"
60 #include "BKE_armature.h"
61 #include "BKE_context.h"
62 #include "BKE_curve.h"
63 #include "BKE_constraint.h"
64 #include "BKE_depsgraph.h"
65 #include "BKE_fcurve.h"
66 #include "BKE_gpencil.h"
67 #include "BKE_global.h"
70 #include "BKE_modifier.h"
72 #include "BKE_object.h"
73 #include "BKE_particle.h"
74 #include "BKE_sequencer.h"
75 #include "BKE_pointcache.h"
76 #include "BKE_bmesh.h"
77 #include "BKE_scene.h"
78 #include "BKE_report.h"
81 #include "ED_anim_api.h"
82 #include "ED_armature.h"
83 #include "ED_particle.h"
85 #include "ED_keyframing.h"
86 #include "ED_keyframes_edit.h"
87 #include "ED_object.h"
88 #include "ED_markers.h"
91 #include "ED_uvedit.h"
92 #include "ED_curve.h" /* for ED_curve_editnurbs */
93 #include "ED_util.h" /* for crazyspace correction */
95 #include "UI_view2d.h"
98 #include "BLI_blenlib.h"
99 #include "BLI_editVert.h"
100 #include "BLI_utildefines.h"
102 #include "RNA_access.h"
104 extern ListBase editelems;
106 #include "transform.h"
108 #include "BLO_sys_types.h" // for intptr_t support
110 /* local function prototype - for Object/Bone Constraints */
111 static short constraints_list_needinv(TransInfo *t, ListBase *list);
113 /* ************************** Functions *************************** */
115 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail, TransData *temp) {
116 TransData *ihead = head;
117 TransData *itail = tail;
122 if (t->flag & T_PROP_CONNECTED) {
123 while ((tail->dist >= temp->dist) && (head < tail))
127 while ((tail->rdist >= temp->rdist) && (head < tail))
137 if (t->flag & T_PROP_CONNECTED) {
138 while ((head->dist <= temp->dist) && (head < tail))
142 while ((head->rdist <= temp->rdist) && (head < tail))
155 qsort_trans_data(t, ihead, head-1, temp);
158 qsort_trans_data(t, head+1, itail, temp);
162 void sort_trans_data_dist(TransInfo *t) {
164 TransData *start = t->data;
167 while(i < t->total && start->flag & TD_SELECTED) {
171 qsort_trans_data(t, start, t->data + t->total - 1, &temp);
174 static void sort_trans_data(TransInfo *t)
176 TransData *sel, *unsel;
181 while (sel > unsel) {
182 while (unsel->flag & TD_SELECTED) {
188 while (!(sel->flag & TD_SELECTED)) {
202 /* distance calculated from not-selected vertex to nearest selected vertex
203 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
204 static void set_prop_dist(TransInfo *t, short with_dist)
209 for(a=0, tob= t->data; a<t->total; a++, tob++) {
211 tob->rdist= 0.0f; // init, it was mallocced
213 if((tob->flag & TD_SELECTED)==0) {
218 tob->rdist = -1.0f; // signal for next loop
220 for (i = 0, td= t->data; i < t->total; i++, td++) {
221 if(td->flag & TD_SELECTED) {
222 sub_v3_v3v3(vec, tob->center, td->center);
223 mul_m3_v3(tob->mtx, vec);
224 dist = normalize_v3(vec);
225 if (tob->rdist == -1.0f) {
228 else if (dist < tob->rdist) {
232 else break; // by definition transdata has selected items in beginning
235 tob->dist = tob->rdist;
241 /* ************************** CONVERSIONS ************************* */
243 /* ********************* texture space ********* */
245 static void createTransTexspace(TransInfo *t)
247 Scene *scene = t->scene;
255 if (ob == NULL) { // Shouldn't logically happen, but still...
261 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
267 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
268 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
270 td->flag= TD_SELECTED;
271 VECCOPY(td->center, ob->obmat[3]);
274 copy_m3_m4(td->mtx, ob->obmat);
275 copy_m3_m4(td->axismtx, ob->obmat);
276 normalize_m3(td->axismtx);
277 invert_m3_m3(td->smtx, td->mtx);
279 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
280 ob->dtx |= OB_TEXSPACE;
281 *texflag &= ~AUTOSPACE;
284 VECCOPY(td->iloc, td->loc);
285 VECCOPY(td->ext->irot, td->ext->rot);
286 VECCOPY(td->ext->isize, td->ext->size);
289 /* ********************* edge (for crease) ***** */
291 static void createTransEdge(TransInfo *t) {
292 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
293 TransData *td = NULL;
295 float mtx[3][3], smtx[3][3];
296 int count=0, countsel=0;
297 int propmode = t->flag & T_PROP_EDIT;
299 for(eed= em->edges.first; eed; eed= eed->next) {
301 if (eed->f & SELECT) countsel++;
302 if (propmode) count++;
316 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
318 copy_m3_m4(mtx, t->obedit->obmat);
319 invert_m3_m3(smtx, mtx);
321 for(eed= em->edges.first; eed; eed= eed->next) {
322 if(eed->h==0 && (eed->f & SELECT || propmode)) {
323 /* need to set center for center calculations */
324 add_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
325 mul_v3_fl(td->center, 0.5f);
329 td->flag= TD_SELECTED;
334 copy_m3_m3(td->smtx, smtx);
335 copy_m3_m3(td->mtx, mtx);
338 if (t->mode == TFM_BWEIGHT) {
339 td->val = &(eed->bweight);
340 td->ival = eed->bweight;
343 td->val = &(eed->crease);
344 td->ival = eed->crease;
352 /* ********************* pose mode ************* */
354 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
356 bConstraint *con= pchan->constraints.first;
358 for(;con; con= con->next) {
359 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0f)) {
360 bKinematicConstraint *data= con->data;
364 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
371 static short apply_targetless_ik(Object *ob)
373 bPoseChannel *pchan, *parchan, *chanlist[256];
374 bKinematicConstraint *data;
375 int segcount, apply= 0;
377 /* now we got a difficult situation... we have to find the
378 target-less IK pchans, and apply transformation to the all
379 pchans that were in the chain */
381 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
382 data= has_targetless_ik(pchan);
383 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
385 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
388 /* exclude tip from chain? */
389 if(!(data->flag & CONSTRAINT_IK_TIP))
390 parchan= pchan->parent;
394 /* Find the chain's root & count the segments needed */
395 for (; parchan; parchan=parchan->parent){
396 chanlist[segcount]= parchan;
399 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
401 for(;segcount;segcount--) {
403 float rmat[4][4], tmat[4][4], imat[4][4];
405 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
406 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
407 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
408 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
410 parchan= chanlist[segcount-1];
412 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
414 if(parchan->parent) {
415 Bone *parbone= parchan->parent->bone;
416 float offs_bone[4][4];
418 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
419 copy_m4_m3(offs_bone, bone->bone_mat);
421 /* The bone's root offset (is in the parent's coordinate system) */
422 VECCOPY(offs_bone[3], bone->head);
424 /* Get the length translation of parent (length along y axis) */
425 offs_bone[3][1]+= parbone->length;
427 /* pose_mat(b-1) * offs_bone */
428 if(parchan->bone->flag & BONE_HINGE) {
429 /* the rotation of the parent restposition */
430 copy_m4_m4(rmat, parbone->arm_mat); /* rmat used as temp */
432 /* the location of actual parent transform */
433 VECCOPY(rmat[3], offs_bone[3]);
434 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
435 mul_m4_v3(parchan->parent->pose_mat, rmat[3]);
437 mul_m4_m4m4(tmat, offs_bone, rmat);
439 else if(parchan->bone->flag & BONE_NO_SCALE) {
440 mul_m4_m4m4(tmat, offs_bone, parchan->parent->pose_mat);
444 mul_m4_m4m4(tmat, offs_bone, parchan->parent->pose_mat);
446 invert_m4_m4(imat, tmat);
449 copy_m4_m3(tmat, bone->bone_mat);
451 VECCOPY(tmat[3], bone->head);
452 invert_m4_m4(imat, tmat);
455 mul_m4_m4m4(rmat, parchan->pose_mat, imat);
457 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
459 float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
461 copy_m3_m4(rmat3, rmat);
464 /* [#22409] is partially caused by this, as slight numeric error introduced during
465 * the solving process leads to locked-axis values changing. However, we cannot modify
466 * the values here, or else there are huge discreptancies between IK-solver (interactive)
469 if (parchan->rotmode > 0)
470 mat3_to_eulO(parchan->eul, parchan->rotmode,rmat3);
471 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
472 mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle,rmat3);
474 mat3_to_quat(parchan->quat,rmat3);
476 /* for size, remove rotation */
477 /* causes problems with some constraints (so apply only if needed) */
478 if (data->flag & CONSTRAINT_IK_STRETCH) {
479 if (parchan->rotmode > 0)
480 eulO_to_mat3( qrmat,parchan->eul, parchan->rotmode);
481 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
482 axis_angle_to_mat3( qrmat,parchan->rotAxis, parchan->rotAngle);
484 quat_to_mat3( qrmat,parchan->quat);
486 invert_m3_m3(imat3, qrmat);
487 mul_m3_m3m3(smat, rmat3, imat3);
488 mat3_to_size( parchan->size,smat);
491 /* causes problems with some constraints (e.g. childof), so disable this */
492 /* as it is IK shouldn't affect location directly */
493 /* VECCOPY(parchan->loc, rmat[3]); */
499 data->flag &= ~CONSTRAINT_IK_AUTO;
506 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
508 Bone *bone= pchan->bone;
509 float pmat[3][3], omat[3][3], bmat[3][3];
510 float cmat[3][3], tmat[3][3];
513 VECCOPY(vec, pchan->pose_mat[3]);
514 VECCOPY(td->center, vec);
517 td->flag = TD_SELECTED;
518 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
520 td->flag |= TD_NOCENTER;
523 if (bone->flag & BONE_TRANSFORM_CHILD)
525 td->flag |= TD_NOCENTER;
526 td->flag |= TD_NO_LOC;
529 td->protectflag= pchan->protectflag;
531 td->loc = pchan->loc;
532 VECCOPY(td->iloc, pchan->loc);
534 td->ext->size= pchan->size;
535 VECCOPY(td->ext->isize, pchan->size);
537 if (pchan->rotmode > 0) {
538 td->ext->rot= pchan->eul;
539 td->ext->rotAxis= NULL;
540 td->ext->rotAngle= NULL;
543 VECCOPY(td->ext->irot, pchan->eul);
545 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
547 td->ext->rotAxis= pchan->rotAxis;
548 td->ext->rotAngle= &pchan->rotAngle;
551 td->ext->irotAngle= pchan->rotAngle;
552 VECCOPY(td->ext->irotAxis, pchan->rotAxis);
556 td->ext->rotAxis= NULL;
557 td->ext->rotAngle= NULL;
558 td->ext->quat= pchan->quat;
560 QUATCOPY(td->ext->iquat, pchan->quat);
562 td->ext->rotOrder= pchan->rotmode;
565 /* proper way to get parent transform + own transform + constraints transform */
566 copy_m3_m4(omat, ob->obmat);
568 if (ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION))
571 copy_m3_m3(bmat, pchan->bone->bone_mat);
574 if(pchan->bone->flag & BONE_HINGE)
575 copy_m3_m4(pmat, pchan->parent->bone->arm_mat);
577 copy_m3_m4(pmat, pchan->parent->pose_mat);
579 if (constraints_list_needinv(t, &pchan->constraints)) {
580 copy_m3_m4(tmat, pchan->constinv);
581 invert_m3_m3(cmat, tmat);
582 mul_serie_m3(td->mtx, bmat, pmat, omat, cmat, NULL,NULL,NULL,NULL); // dang mulserie swaps args
585 mul_serie_m3(td->mtx, bmat, pmat, omat, NULL,NULL,NULL,NULL,NULL); // dang mulserie swaps args
588 if (constraints_list_needinv(t, &pchan->constraints)) {
589 copy_m3_m4(tmat, pchan->constinv);
590 invert_m3_m3(cmat, tmat);
591 mul_serie_m3(td->mtx, bmat, omat, cmat, NULL,NULL,NULL,NULL,NULL); // dang mulserie swaps args
594 mul_m3_m3m3(td->mtx, omat, bmat); // Mat3MulMat3 has swapped args!
597 invert_m3_m3(td->smtx, td->mtx);
599 /* exceptional case: rotate the pose bone which also applies transformation
600 * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
601 if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
603 /* same as td->smtx but without pchan->bone->bone_mat */
604 td->flag |= TD_PBONE_LOCAL_MTX_C;
605 mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
608 td->flag |= TD_PBONE_LOCAL_MTX_P;
612 /* for axismat we use bone's own transform */
613 copy_m3_m4(pmat, pchan->pose_mat);
614 mul_m3_m3m3(td->axismtx, omat, pmat);
615 normalize_m3(td->axismtx);
617 if (t->mode==TFM_BONESIZE) {
618 bArmature *arm= t->poseobj->data;
620 if(arm->drawtype==ARM_ENVELOPE) {
622 td->val= &bone->dist;
623 td->ival= bone->dist;
626 // abusive storage of scale in the loc pointer :)
627 td->loc= &bone->xwidth;
628 VECCOPY (td->iloc, td->loc);
633 /* in this case we can do target-less IK grabbing */
634 if (t->mode==TFM_TRANSLATION) {
635 bKinematicConstraint *data= has_targetless_ik(pchan);
637 if(data->flag & CONSTRAINT_IK_TIP) {
638 VECCOPY(data->grabtarget, pchan->pose_tail);
641 VECCOPY(data->grabtarget, pchan->pose_head);
643 td->loc = data->grabtarget;
644 VECCOPY(td->iloc, td->loc);
645 data->flag |= CONSTRAINT_IK_AUTO;
647 /* only object matrix correction */
648 copy_m3_m3(td->mtx, omat);
649 invert_m3_m3(td->smtx, td->mtx);
653 /* store reference to first constraint */
654 td->con= pchan->constraints.first;
657 static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
659 Bone *bone= lb->first;
661 for(;bone;bone= bone->next) {
662 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
664 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
666 else if (bone->flag & BONE_TRANSFORM && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) && around == V3D_LOCAL)
668 bone->flag |= BONE_TRANSFORM_CHILD;
672 bone->flag &= ~BONE_TRANSFORM;
675 bone_children_clear_transflag(mode, around, &bone->childbase);
679 /* sets transform flags in the bones
680 * returns total number of bones with BONE_TRANSFORM */
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 (PBONE_VISIBLE(arm, bone)) {
693 if ((bone->flag & BONE_SELECTED) && !(ob->proxy && pchan->bone->layer & arm->layer_protected))
694 bone->flag |= BONE_TRANSFORM;
696 bone->flag &= ~BONE_TRANSFORM;
698 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
699 bone->flag &= ~BONE_TRANSFORM_CHILD;
702 bone->flag &= ~BONE_TRANSFORM;
705 /* make sure no bone can be transformed when a parent is transformed */
706 /* since pchans are depsgraph sorted, the parents are in beginning of list */
707 if(mode != TFM_BONESIZE) {
708 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
710 if(bone->flag & BONE_TRANSFORM)
711 bone_children_clear_transflag(mode, around, &bone->childbase);
714 /* now count, and check if we have autoIK or have to switch from translate to rotate */
717 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
719 if(bone->flag & BONE_TRANSFORM) {
722 if(mode == TFM_TRANSLATION) {
723 if( has_targetless_ik(pchan)==NULL ) {
724 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
725 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
728 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
737 /* if there are no translatable bones, do rotation */
738 if(mode == TFM_TRANSLATION && !hastranslation)
740 *out_mode = TFM_ROTATION;
747 /* -------- Auto-IK ---------- */
749 /* adjust pose-channel's auto-ik chainlen */
750 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
754 /* don't bother to search if no valid constraints */
755 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
758 /* check if pchan has ik-constraint */
759 for (con= pchan->constraints.first; con; con= con->next) {
760 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0f)) {
761 bKinematicConstraint *data= con->data;
763 /* only accept if a temporary one (for auto-ik) */
764 if (data->flag & CONSTRAINT_IK_TEMP) {
765 /* chainlen is new chainlen, but is limited by maximum chainlen */
766 if ((chainlen==0) || (chainlen > data->max_rootbone))
767 data->rootbone= data->max_rootbone;
769 data->rootbone= chainlen;
775 /* change the chain-length of auto-ik */
776 void transform_autoik_update (TransInfo *t, short mode)
778 short *chainlen= &t->settings->autoik_chainlen;
781 /* mode determines what change to apply to chainlen */
783 /* mode=1 is from WHEELMOUSEDOWN... increases len */
786 else if (mode == -1) {
787 /* mode==-1 is from WHEELMOUSEUP... decreases len */
788 if (*chainlen > 0) (*chainlen)--;
791 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
792 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
795 /* apply to all pose-channels */
796 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
797 pchan_autoik_adjust(pchan, *chainlen);
801 /* frees temporal IKs */
802 static void pose_grab_with_ik_clear(Object *ob)
804 bKinematicConstraint *data;
806 bConstraint *con, *next;
808 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
809 /* clear all temporary lock flags */
810 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
812 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
814 /* remove all temporary IK-constraints added */
815 for (con= pchan->constraints.first; con; con= next) {
817 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
819 if (data->flag & CONSTRAINT_IK_TEMP) {
820 BLI_remlink(&pchan->constraints, con);
821 MEM_freeN(con->data);
825 pchan->constflag |= PCHAN_HAS_IK;
826 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
827 pchan->constflag |= PCHAN_HAS_TARGET;
833 /* adds the IK to pchan - returns if added */
834 static short pose_grab_with_ik_add(bPoseChannel *pchan)
836 bKinematicConstraint *targetless = NULL;
837 bKinematicConstraint *data;
844 /* Rule: not if there's already an IK on this channel */
845 for (con= pchan->constraints.first; con; con= con->next) {
846 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
849 if (data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]=='\0')) {
850 /* make reference to constraint to base things off later (if it's the last targetless constraint encountered) */
851 targetless = (bKinematicConstraint *)con->data;
853 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
854 if (con->enforce!=0.0f) {
855 data->flag |= CONSTRAINT_IK_AUTO;
857 /* if no chain length has been specified, just make things obey standard rotation locks too */
858 if (data->rootbone == 0) {
859 for (; pchan; pchan=pchan->parent) {
860 /* here, we set ik-settings for bone from pchan->protectflag */
861 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
862 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
863 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
864 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
872 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0f))
877 con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
878 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
881 /* if exists, use values from last targetless (but disabled) IK-constraint as base */
885 data->flag= CONSTRAINT_IK_TIP;
886 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
887 VECCOPY(data->grabtarget, pchan->pose_tail);
888 data->rootbone= 0; /* watch-it! has to be 0 here, since we're still on the same bone for the first time through the loop [#25885] */
890 /* we only include bones that are part of a continual connected chain */
892 /* here, we set ik-settings for bone from pchan->protectflag */
893 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
894 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
895 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
896 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
898 /* now we count this pchan as being included */
901 /* continue to parent, but only if we're connected to it */
902 if (pchan->bone->flag & BONE_CONNECTED)
903 pchan = pchan->parent;
908 /* make a copy of maximum chain-length */
909 data->max_rootbone= data->rootbone;
914 /* bone is a candidate to get IK, but we don't do it if it has children connected */
915 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
918 short wentdeeper=0, added=0;
920 /* go deeper if children & children are connected */
921 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
922 if (bonec->flag & BONE_CONNECTED) {
924 added+= pose_grab_with_ik_children(pose, bonec);
928 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
930 added+= pose_grab_with_ik_add(pchan);
936 /* main call which adds temporal IK chains */
937 static short pose_grab_with_ik(Object *ob)
940 bPoseChannel *pchan, *parent;
944 if ((ob==NULL) || (ob->pose==NULL) || (ob->mode & OB_MODE_POSE)==0)
949 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
950 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
951 if (pchan->bone->layer & arm->layer) {
952 if (pchan->bone->flag & BONE_SELECTED) {
953 /* Rule: no IK for solitatry (unconnected) bones */
954 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
955 if (bonec->flag & BONE_CONNECTED) {
959 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
962 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
964 /* only adds if there's no IK yet (and no parent bone was selected) */
965 for (parent= pchan->parent; parent; parent= parent->parent) {
966 if (parent->bone->flag & BONE_SELECTED)
970 tot_ik += pose_grab_with_ik_add(pchan);
973 /* rule: go over the children and add IK to the tips */
974 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
980 return (tot_ik) ? 1 : 0;
984 /* only called with pose mode active object now */
985 static void createTransPose(TransInfo *t, Object *ob)
990 TransDataExtension *tdx;
996 /* check validity of state */
997 arm= get_armature(ob);
998 if ((arm==NULL) || (ob->pose==NULL)) return;
1000 if (arm->flag & ARM_RESTPOS) {
1001 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
1002 // XXX use transform operator reports
1003 // BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled.");
1008 /* do we need to add temporal IK chains? */
1009 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
1010 ik_on= pose_grab_with_ik(ob);
1011 if (ik_on) t->flag |= T_AUTOIK;
1014 /* set flags and count total (warning, can change transform to rotate) */
1015 t->total = count_set_pose_transflags(&t->mode, t->around, ob);
1017 if(t->total == 0) return;
1020 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
1022 /* init trans data */
1023 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
1024 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
1025 for(i=0; i<t->total; i++, td++, tdx++) {
1030 /* use pose channels to fill trans data */
1032 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1033 if (pchan->bone->flag & BONE_TRANSFORM) {
1034 add_pose_transdata(t, pchan, ob, td);
1039 if(td != (t->data+t->total)) {
1040 // XXX use transform operator reports
1041 // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error.");
1044 /* initialise initial auto=ik chainlen's? */
1045 if (ik_on) transform_autoik_update(t, 0);
1048 /* ********************* armature ************** */
1050 static void createTransArmatureVerts(TransInfo *t)
1053 bArmature *arm= t->obedit->data;
1054 ListBase *edbo = arm->edbo;
1056 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1058 /* special hack for envelope drawmode and scaling:
1059 * to allow scaling the size of the envelope around single points,
1060 * mode should become TFM_BONE_ENVELOPE in this case
1062 // TODO: maybe we need a separate hotkey for it, but this is consistent with 2.4x for now
1063 if ((t->mode == TFM_RESIZE) && (arm->drawtype==ARM_ENVELOPE))
1064 t->mode= TFM_BONE_ENVELOPE;
1067 for (ebo = edbo->first; ebo; ebo = ebo->next)
1069 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED))
1071 if (t->mode==TFM_BONESIZE)
1073 if (ebo->flag & BONE_SELECTED)
1076 else if (t->mode==TFM_BONE_ROLL)
1078 if (ebo->flag & BONE_SELECTED)
1083 if (ebo->flag & BONE_TIPSEL)
1085 if (ebo->flag & BONE_ROOTSEL)
1091 if (!t->total) return;
1093 copy_m3_m4(mtx, t->obedit->obmat);
1094 invert_m3_m3(smtx, mtx);
1096 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1098 for (ebo = edbo->first; ebo; ebo = ebo->next)
1100 ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1102 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED))
1104 if (t->mode==TFM_BONE_ENVELOPE)
1106 if (ebo->flag & BONE_ROOTSEL)
1108 td->val= &ebo->rad_head;
1111 VECCOPY (td->center, ebo->head);
1112 td->flag= TD_SELECTED;
1114 copy_m3_m3(td->smtx, smtx);
1115 copy_m3_m3(td->mtx, mtx);
1123 if (ebo->flag & BONE_TIPSEL)
1125 td->val= &ebo->rad_tail;
1127 VECCOPY (td->center, ebo->tail);
1128 td->flag= TD_SELECTED;
1130 copy_m3_m3(td->smtx, smtx);
1131 copy_m3_m3(td->mtx, mtx);
1141 else if (t->mode==TFM_BONESIZE)
1143 if (ebo->flag & BONE_SELECTED) {
1144 if(arm->drawtype==ARM_ENVELOPE)
1147 td->val= &ebo->dist;
1148 td->ival= ebo->dist;
1152 // abusive storage of scale in the loc pointer :)
1153 td->loc= &ebo->xwidth;
1154 VECCOPY (td->iloc, td->loc);
1157 VECCOPY (td->center, ebo->head);
1158 td->flag= TD_SELECTED;
1160 /* use local bone matrix */
1161 sub_v3_v3v3(delta, ebo->tail, ebo->head);
1162 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1163 mul_m3_m3m3(td->mtx, mtx, bonemat);
1164 invert_m3_m3(td->smtx, td->mtx);
1166 copy_m3_m3(td->axismtx, td->mtx);
1167 normalize_m3(td->axismtx);
1175 else if (t->mode==TFM_BONE_ROLL)
1177 if (ebo->flag & BONE_SELECTED)
1180 td->val= &(ebo->roll);
1181 td->ival= ebo->roll;
1183 VECCOPY (td->center, ebo->head);
1184 td->flag= TD_SELECTED;
1194 if (ebo->flag & BONE_TIPSEL)
1196 VECCOPY (td->iloc, ebo->tail);
1197 VECCOPY (td->center, td->iloc);
1199 td->flag= TD_SELECTED;
1200 if (ebo->flag & BONE_EDITMODE_LOCKED)
1201 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1203 copy_m3_m3(td->smtx, smtx);
1204 copy_m3_m3(td->mtx, mtx);
1206 sub_v3_v3v3(delta, ebo->tail, ebo->head);
1207 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1209 if ((ebo->flag & BONE_ROOTSEL) == 0)
1220 if (ebo->flag & BONE_ROOTSEL)
1222 VECCOPY (td->iloc, ebo->head);
1223 VECCOPY (td->center, td->iloc);
1225 td->flag= TD_SELECTED;
1226 if (ebo->flag & BONE_EDITMODE_LOCKED)
1227 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1229 copy_m3_m3(td->smtx, smtx);
1230 copy_m3_m3(td->mtx, mtx);
1232 sub_v3_v3v3(delta, ebo->tail, ebo->head);
1233 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1235 td->extra = ebo; /* to fix roll */
1248 /* ********************* meta elements ********* */
1250 static void createTransMBallVerts(TransInfo *t)
1252 MetaBall *mb = (MetaBall*)t->obedit->data;
1255 TransDataExtension *tx;
1256 float mtx[3][3], smtx[3][3];
1257 int count=0, countsel=0;
1258 int propmode = t->flag & T_PROP_EDIT;
1261 for(ml= mb->editelems->first; ml; ml= ml->next) {
1262 if(ml->flag & SELECT) countsel++;
1263 if(propmode) count++;
1266 /* note: in prop mode we need at least 1 selected */
1267 if (countsel==0) return;
1269 if(propmode) t->total = count;
1270 else t->total = countsel;
1272 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1273 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1275 copy_m3_m4(mtx, t->obedit->obmat);
1276 invert_m3_m3(smtx, mtx);
1278 for(ml= mb->editelems->first; ml; ml= ml->next) {
1279 if(propmode || (ml->flag & SELECT)) {
1281 VECCOPY(td->iloc, td->loc);
1282 VECCOPY(td->center, td->loc);
1284 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1285 else td->flag= TD_USEQUAT;
1287 copy_m3_m3(td->smtx, smtx);
1288 copy_m3_m3(td->mtx, mtx);
1292 /* Radius of MetaElem (mass of MetaElem influence) */
1293 if(ml->flag & MB_SCALE_RAD){
1302 /* expx/expy/expz determine "shape" of some MetaElem types */
1303 tx->size = &ml->expx;
1304 tx->isize[0] = ml->expx;
1305 tx->isize[1] = ml->expy;
1306 tx->isize[2] = ml->expz;
1308 /* quat is used for rotation of MetaElem */
1309 tx->quat = ml->quat;
1310 QUATCOPY(tx->iquat, ml->quat);
1320 /* ********************* curve/surface ********* */
1322 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1323 TransData *td, *td_near = NULL;
1324 for (td = head; td<=tail; td++) {
1325 if (td->flag & TD_SELECTED) {
1331 dist = len_v3v3(td_near->center, td->center);
1332 if (dist < (td-1)->dist) {
1333 td->dist = (td-1)->dist;
1340 td->dist = MAXFLOAT;
1341 td->flag |= TD_NOTCONNECTED;
1345 for (td = tail; td>=head; td--) {
1346 if (td->flag & TD_SELECTED) {
1352 dist = len_v3v3(td_near->center, td->center);
1353 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1354 td->flag &= ~TD_NOTCONNECTED;
1355 if (dist < (td+1)->dist) {
1356 td->dist = (td+1)->dist;
1366 /* Utility function for getting the handle data from bezier's */
1367 static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt) {
1368 TransDataCurveHandleFlags *hdata;
1369 td->flag |= TD_BEZTRIPLE;
1370 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1371 hdata->ih1 = bezt->h1;
1372 hdata->h1 = &bezt->h1;
1373 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1374 hdata->h2 = &bezt->h2;
1378 static void createTransCurveVerts(bContext *C, TransInfo *t)
1380 Object *obedit= CTX_data_edit_object(C);
1381 Curve *cu= obedit->data;
1382 TransData *td = NULL;
1386 float mtx[3][3], smtx[3][3];
1388 int count=0, countsel=0;
1389 int propmode = t->flag & T_PROP_EDIT;
1390 short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
1394 if(cu->editnurb==NULL) return;
1396 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1397 nurbs= ED_curve_editnurbs(cu);
1398 for(nu= nurbs->first; nu; nu= nu->next) {
1399 if(nu->type == CU_BEZIER) {
1400 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1403 if(bezt->f2 & SELECT) countsel+=3;
1404 if(propmode) count+= 3;
1406 if(bezt->f1 & SELECT) countsel++;
1407 if(bezt->f2 & SELECT) countsel++;
1408 if(bezt->f3 & SELECT) countsel++;
1409 if(propmode) count+= 3;
1415 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1417 if(propmode) count++;
1418 if(bp->f1 & SELECT) countsel++;
1423 /* note: in prop mode we need at least 1 selected */
1424 if (countsel==0) return;
1426 if(propmode) t->total = count;
1427 else t->total = countsel;
1428 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1430 copy_m3_m4(mtx, t->obedit->obmat);
1431 invert_m3_m3(smtx, mtx);
1434 for(nu= nurbs->first; nu; nu= nu->next) {
1435 if(nu->type == CU_BEZIER) {
1436 TransData *head, *tail;
1438 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1440 TransDataCurveHandleFlags *hdata = NULL;
1443 ((bezt->f2 & SELECT) && hide_handles) ||
1444 ((bezt->f1 & SELECT) && hide_handles == 0)
1446 VECCOPY(td->iloc, bezt->vec[0]);
1447 td->loc= bezt->vec[0];
1448 VECCOPY(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:0]);
1450 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1453 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1459 hdata = initTransDataCurveHandles(td, bezt);
1461 copy_m3_m3(td->smtx, smtx);
1462 copy_m3_m3(td->mtx, mtx);
1469 /* This is the Curve Point, the other two are handles */
1470 if(propmode || (bezt->f2 & SELECT)) {
1471 VECCOPY(td->iloc, bezt->vec[1]);
1472 td->loc= bezt->vec[1];
1473 VECCOPY(td->center, td->loc);
1474 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1478 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1479 td->val = &(bezt->radius);
1480 td->ival = bezt->radius;
1481 } else if (t->mode==TFM_TILT) {
1482 td->val = &(bezt->alfa);
1483 td->ival = bezt->alfa;
1488 copy_m3_m3(td->smtx, smtx);
1489 copy_m3_m3(td->mtx, mtx);
1491 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1492 /* If the middle is selected but the sides arnt, this is needed */
1493 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1494 hdata = initTransDataCurveHandles(td, bezt);
1502 ((bezt->f2 & SELECT) && hide_handles) ||
1503 ((bezt->f3 & SELECT) && hide_handles == 0)
1505 VECCOPY(td->iloc, bezt->vec[2]);
1506 td->loc= bezt->vec[2];
1507 VECCOPY(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:2]);
1509 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1512 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1518 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1519 hdata = initTransDataCurveHandles(td, bezt);
1522 copy_m3_m3(td->smtx, smtx);
1523 copy_m3_m3(td->mtx, mtx);
1530 else if (propmode && head != tail) {
1531 calc_distanceCurveVerts(head, tail-1);
1535 if (propmode && head != tail)
1536 calc_distanceCurveVerts(head, tail-1);
1538 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
1539 * but for now just dont change handle types */
1540 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1541 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1544 TransData *head, *tail;
1546 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1548 if(propmode || (bp->f1 & SELECT)) {
1549 VECCOPY(td->iloc, bp->vec);
1551 VECCOPY(td->center, td->loc);
1552 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1556 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1557 td->val = &(bp->radius);
1558 td->ival = bp->radius;
1560 td->val = &(bp->alfa);
1561 td->ival = bp->alfa;
1564 copy_m3_m3(td->smtx, smtx);
1565 copy_m3_m3(td->mtx, mtx);
1572 else if (propmode && head != tail) {
1573 calc_distanceCurveVerts(head, tail-1);
1577 if (propmode && head != tail)
1578 calc_distanceCurveVerts(head, tail-1);
1583 /* ********************* lattice *************** */
1585 static void createTransLatticeVerts(TransInfo *t)
1587 Lattice *latt = ((Lattice*)t->obedit->data)->editlatt->latt;
1588 TransData *td = NULL;
1590 float mtx[3][3], smtx[3][3];
1592 int count=0, countsel=0;
1593 int propmode = t->flag & T_PROP_EDIT;
1596 a = latt->pntsu * latt->pntsv * latt->pntsw;
1599 if(bp->f1 & SELECT) countsel++;
1600 if(propmode) count++;
1605 /* note: in prop mode we need at least 1 selected */
1606 if (countsel==0) return;
1608 if(propmode) t->total = count;
1609 else t->total = countsel;
1610 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1612 copy_m3_m4(mtx, t->obedit->obmat);
1613 invert_m3_m3(smtx, mtx);
1617 a = latt->pntsu * latt->pntsv * latt->pntsw;
1619 if(propmode || (bp->f1 & SELECT)) {
1621 VECCOPY(td->iloc, bp->vec);
1623 VECCOPY(td->center, td->loc);
1624 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1626 copy_m3_m3(td->smtx, smtx);
1627 copy_m3_m3(td->mtx, mtx);
1640 /* ******************* particle edit **************** */
1641 static void createTransParticleVerts(bContext *C, TransInfo *t)
1643 TransData *td = NULL;
1644 TransDataExtension *tx;
1645 Base *base = CTX_data_active_base(C);
1646 Object *ob = CTX_data_active_object(C);
1647 ParticleEditSettings *pset = PE_settings(t->scene);
1648 PTCacheEdit *edit = PE_get_current(t->scene, ob);
1649 ParticleSystem *psys = NULL;
1650 ParticleSystemModifierData *psmd = NULL;
1651 PTCacheEditPoint *point;
1652 PTCacheEditKey *key;
1654 int i,k, transformparticle;
1655 int count = 0, hasselected = 0;
1656 int propmode = t->flag & T_PROP_EDIT;
1658 if(edit==NULL || t->settings->particle.selectmode==SCE_SELECT_PATH) return;
1663 psmd = psys_get_modifier(ob,psys);
1665 base->flag |= BA_HAS_RECALC_DATA;
1667 for(i=0, point=edit->points; i<edit->totpoint; i++, point++) {
1668 point->flag &= ~PEP_TRANSFORM;
1669 transformparticle= 0;
1671 if((point->flag & PEP_HIDE)==0) {
1672 for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1673 if((key->flag&PEK_HIDE)==0) {
1674 if(key->flag&PEK_SELECT) {
1676 transformparticle= 1;
1679 transformparticle= 1;
1684 if(transformparticle) {
1685 count += point->totkey;
1686 point->flag |= PEP_TRANSFORM;
1690 /* note: in prop mode we need at least 1 selected */
1691 if (hasselected==0) return;
1694 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1696 if(t->mode == TFM_BAKE_TIME)
1697 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1703 invert_m4_m4(ob->imat,ob->obmat);
1705 for(i=0, point=edit->points; i<edit->totpoint; i++, point++) {
1706 TransData *head, *tail;
1709 if(!(point->flag & PEP_TRANSFORM)) continue;
1711 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR))
1712 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1714 for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1715 if(key->flag & PEK_USE_WCO) {
1716 VECCOPY(key->world_co, key->co);
1717 mul_m4_v3(mat, key->world_co);
1718 td->loc = key->world_co;
1723 VECCOPY(td->iloc, td->loc);
1724 VECCOPY(td->center, td->loc);
1726 if(key->flag & PEK_SELECT)
1727 td->flag |= TD_SELECTED;
1729 td->flag |= TD_SKIP;
1734 /* don't allow moving roots */
1735 if(k==0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
1736 td->protectflag |= OB_LOCK_LOC;
1740 if(t->mode == TFM_BAKE_TIME) {
1741 td->val = key->time;
1742 td->ival = *(key->time);
1743 /* abuse size and quat for min/max values */
1744 td->flag |= TD_NO_EXT;
1745 if(k==0) tx->size = NULL;
1746 else tx->size = (key - 1)->time;
1748 if(k == point->totkey - 1) tx->quat = NULL;
1749 else tx->quat = (key + 1)->time;
1757 if (propmode && head != tail)
1758 calc_distanceCurveVerts(head, tail - 1);
1762 void flushTransParticles(TransInfo *t)
1764 Scene *scene = t->scene;
1766 PTCacheEdit *edit = PE_get_current(scene, ob);
1767 ParticleSystem *psys = edit->psys;
1768 ParticleSystemModifierData *psmd = NULL;
1769 PTCacheEditPoint *point;
1770 PTCacheEditKey *key;
1772 float mat[4][4], imat[4][4], co[3];
1773 int i, k, propmode = t->flag & T_PROP_EDIT;
1776 psmd = psys_get_modifier(ob, psys);
1778 /* we do transform in world space, so flush world space position
1779 * back to particle local space (only for hair particles) */
1781 for(i=0, point=edit->points; i<edit->totpoint; i++, point++, td++) {
1782 if(!(point->flag & PEP_TRANSFORM)) continue;
1784 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
1785 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1786 invert_m4_m4(imat,mat);
1788 for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1789 VECCOPY(co, key->world_co);
1790 mul_m4_v3(imat, co);
1793 /* optimization for proportional edit */
1794 if(!propmode || !compare_v3v3(key->co, co, 0.0001f)) {
1795 VECCOPY(key->co, co);
1796 point->flag |= PEP_EDIT_RECALC;
1801 point->flag |= PEP_EDIT_RECALC;
1804 PE_update_object(scene, OBACT, 1);
1807 /* ********************* mesh ****************** */
1809 /* proportional distance based on connectivity */
1810 #define THRESHOLD 0.0001f
1812 static int connectivity_edge(float mtx[][3], EditVert *v1, EditVert *v2)
1818 /* note: hidden verts are not being checked for, this assumes
1819 * flushing of hidden faces & edges is working right */
1821 if (v1->f2 + v2->f2 == 4)
1824 sub_v3_v3v3(edge_vec, v1->co, v2->co);
1825 mul_m3_v3(mtx, edge_vec);
1827 edge_len = len_v3(edge_vec);
1831 if (v2->tmp.fp + edge_len + THRESHOLD < v1->tmp.fp) {
1832 v1->tmp.fp = v2->tmp.fp + edge_len;
1834 } else if (v1->tmp.fp + edge_len + THRESHOLD < v2->tmp.fp) {
1835 v2->tmp.fp = v1->tmp.fp + edge_len;
1841 v2->tmp.fp = v1->tmp.fp + edge_len;
1847 v1->tmp.fp = v2->tmp.fp + edge_len;
1854 static void editmesh_set_connectivity_distance(EditMesh *em, float mtx[][3])
1861 /* f2 flag is used for 'selection' */
1862 /* tmp.l is offset on scratch array */
1863 for(eve= em->verts.first; eve; eve= eve->next) {
1867 if(eve->f & SELECT) {
1877 /* Floodfill routine */
1879 At worst this is n*n of complexity where n is number of edges
1880 Best case would be n if the list is ordered perfectly.
1881 Estimate is n log n in average (so not too bad)
1886 for(eed= em->edges.first; eed; eed= eed->next) {
1888 done |= connectivity_edge(mtx, eed->v1, eed->v2);
1892 /* do internal edges for quads */
1893 for(efa= em->faces.first; efa; efa= efa->next) {
1894 if (efa->v4 && efa->h==0) {
1895 done |= connectivity_edge(mtx, efa->v1, efa->v3);
1896 done |= connectivity_edge(mtx, efa->v2, efa->v4);
1902 /* loop-in-a-loop I know, but we need it! (ton) */
1903 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1907 for(efa= em->faces.first; efa; efa= efa->next)
1909 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1912 VECCOPY(cent, efa->cent);
1916 //way to overwrite what data is edited with transform
1917 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1918 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1922 // td->loc = key->co;
1926 VECCOPY(td->center, td->loc);
1927 if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1928 get_face_center(td->center, em, eve);
1929 VECCOPY(td->iloc, td->loc);
1932 VECCOPY(td->axismtx[2], eve->no);
1938 td->axismtx[1][2] = 0.0f;
1943 if (t->mode == TFM_BWEIGHT) {
1944 td->val = &(eve->bweight);
1945 td->ival = eve->bweight;
1950 static void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
1956 tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
1958 for (i=0,v=bm->verts.first;v;v=v->next) {
1959 if ( (vtd = BME_get_transdata(td,v)) ) {
1960 tob->loc = vtd->loc;
1961 tob->val = &vtd->factor;
1962 VECCOPY(tob->iloc,vtd->co);
1963 VECCOPY(tob->center,vtd->org);
1964 VECCOPY(tob->axismtx[0],vtd->vec);
1965 tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
1970 /* since td is a memarena, it can hold more transdata than actual elements
1971 * (i.e. we can't depend on td->len to determine the number of actual elements) */
1976 static void createTransEditVerts(bContext *C, TransInfo *t)
1978 ToolSettings *ts = CTX_data_tool_settings(C);
1979 TransData *tob = NULL;
1980 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
1982 EditVert *eve_act = NULL;
1983 float *mappedcos = NULL, *quats= NULL;
1984 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
1985 int count=0, countsel=0, a, totleft;
1986 int propmode = t->flag & T_PROP_EDIT;
1988 short selectmode = ts->selectmode;
1990 if (t->flag & T_MIRROR)
1995 /* edge slide forces edge select */
1996 if (t->mode == TFM_EDGE_SLIDE) {
1997 selectmode = SCE_SELECT_EDGE;
2000 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2001 if(selectmode & SCE_SELECT_VERTEX) {
2002 for(eve= em->verts.first; eve; eve= eve->next) {
2003 if(eve->h==0 && (eve->f & SELECT))
2009 else if(selectmode & SCE_SELECT_EDGE) {
2011 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2012 for(eed= em->edges.first; eed; eed= eed->next) {
2013 if(eed->h==0 && (eed->f & SELECT))
2014 eed->v1->f1= eed->v2->f1= SELECT;
2019 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2020 for(efa= em->faces.first; efa; efa= efa->next) {
2021 if(efa->h==0 && (efa->f & SELECT)) {
2022 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2023 if(efa->v4) efa->v4->f1= SELECT;
2028 /* now we can count */
2029 for(eve= em->verts.first; eve; eve= eve->next) {
2031 if(eve->f1) countsel++;
2032 if(propmode) count++;
2036 /* note: in prop mode we need at least 1 selected */
2037 if (countsel==0) return;
2040 if (em->selected.last) {
2041 EditSelection *ese = em->selected.last;
2042 if ( ese->type == EDITVERT ) {
2043 eve_act = (EditVert *)ese->data;
2048 if(propmode) t->total = count;
2049 else t->total = countsel;
2051 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2053 copy_m3_m4(mtx, t->obedit->obmat);
2054 invert_m3_m3(smtx, mtx);
2056 if(propmode) editmesh_set_connectivity_distance(em, mtx);
2058 /* detect CrazySpace [tm] */
2059 if(modifiers_getCageIndex(t->scene, t->obedit, NULL, 1)>=0) {
2060 if(modifiers_isCorrectableDeformed(t->obedit)) {
2061 /* check if we can use deform matrices for modifier from the
2062 start up to stack, they are more accurate than quats */
2063 totleft= editmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
2065 /* if we still have more modifiers, also do crazyspace
2066 correction with quats, relative to the coordinates after
2067 the modifiers that support deform matrices (defcos) */
2069 mappedcos= crazyspace_get_mapped_editverts(t->scene, t->obedit);
2070 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2071 crazyspace_set_quats_editmesh(em, (float*)defcos, mappedcos, quats);
2073 MEM_freeN(mappedcos);
2081 /* find out which half we do */
2083 for (eve=em->verts.first; eve; eve=eve->next) {
2084 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2095 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2097 if(propmode || eve->f1) {
2098 VertsToTransData(t, tob, em, eve);
2101 if(eve->f1) tob->flag |= TD_SELECTED;
2104 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2108 tob->dist= eve->tmp.fp;
2111 tob->flag |= TD_NOTCONNECTED;
2112 tob->dist = MAXFLOAT;
2117 if(defmats || (quats && eve->tmp.p)) {
2118 float mat[3][3], imat[3][3], qmat[3][3];
2120 /* use both or either quat and defmat correction */
2121 if(quats && eve->tmp.f) {
2122 quat_to_mat3( qmat,eve->tmp.p);
2125 mul_serie_m3(mat, mtx, qmat, defmats[a],
2126 NULL, NULL, NULL, NULL, NULL);
2128 mul_m3_m3m3(mat, mtx, qmat);
2131 mul_m3_m3m3(mat, mtx, defmats[a]);
2133 invert_m3_m3(imat, mat);
2135 copy_m3_m3(tob->smtx, imat);
2136 copy_m3_m3(tob->mtx, mat);
2139 copy_m3_m3(tob->smtx, smtx);
2140 copy_m3_m3(tob->mtx, mtx);
2144 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2145 EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, eve, tob->iloc, a); /* initializes octree on first call */
2158 for( a = 0; a < t->total; a++, tob++ )
2160 if (ABS(tob->loc[0]) <= 0.00001f)
2162 tob->flag |= TD_MIRROR_EDGE;
2167 /* crazy space free */
2174 /* *** NODE EDITOR *** */
2175 void flushTransNodes(TransInfo *t)
2180 /* flush to 2d vector from internally used 3d vector */
2181 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2182 td->loc2d[0]= td->loc[0];
2183 td->loc2d[1]= td->loc[1];
2187 /* *** SEQUENCE EDITOR *** */
2188 void flushTransSeq(TransInfo *t)
2190 ListBase *seqbasep= seq_give_editing(t->scene, FALSE)->seqbasep; /* Editing null check already done */
2191 int a, new_frame, old_start;
2192 TransData *td= NULL;
2193 TransData2D *td2d= NULL;
2194 TransDataSeq *tdsq= NULL;
2199 /* prevent updating the same seq twice
2200 * if the transdata order is changed this will mess up
2201 * but so will TransDataSeq */
2202 Sequence *seq_prev= NULL;
2204 /* flush to 2d vector from internally used 3d vector */
2205 for(a=0, td= t->data, td2d= t->data2d; a<t->total; a++, td++, td2d++) {
2206 tdsq= (TransDataSeq *)td->extra;
2208 old_start = seq->start;
2209 new_frame= (int)floor(td2d->loc[0] + 0.5f);
2211 switch (tdsq->sel_flag) {
2213 if (seq->type != SEQ_META && (seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */
2214 seq->start= new_frame - tdsq->start_offset;
2216 if (seq->depth==0) {
2217 seq->machine= (int)floor(td2d->loc[1] + 0.5f);
2218 CLAMP(seq->machine, 1, MAXSEQ);
2221 case SEQ_LEFTSEL: /* no vertical transform */
2222 seq_tx_set_final_left(seq, new_frame);
2223 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2224 seq_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2226 case SEQ_RIGHTSEL: /* no vertical transform */
2227 seq_tx_set_final_right(seq, new_frame);
2228 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2229 seq_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2233 if (seq != seq_prev) {
2235 /* Calculate this strip and all nested strips
2236 * children are ALWAYS transformed first
2237 * so we dont need to do this in another loop. */
2238 calc_sequence(t->scene, seq);
2241 calc_sequence_disp(t->scene, seq);
2244 if(tdsq->sel_flag == SELECT)
2245 seq_offset_animdata(t->scene, seq, seq->start - old_start);
2250 /* need to do the overlap check in a new loop otherwise adjacent strips
2251 * will not be updated and we'll get false positives */
2253 for(a=0, td= t->data, td2d= t->data2d; a<t->total; a++, td++, td2d++) {
2255 tdsq= (TransDataSeq *)td->extra;
2258 if (seq != seq_prev) {
2260 /* test overlap, displayes red outline */
2261 seq->flag &= ~SEQ_OVERLAP;
2262 if( seq_test_overlap(seqbasep, seq) ) {
2263 seq->flag |= SEQ_OVERLAP;
2270 if (t->mode == TFM_TIME_TRANSLATE) { /* originally TFM_TIME_EXTEND, transform changes */
2271 /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
2272 seq= seqbasep->first;
2275 if (seq->type == SEQ_META && seq->flag & SELECT)
2276 calc_sequence(t->scene, seq);
2282 /* ********************* UV ****************** */
2284 static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
2288 ED_space_image_uv_aspect(sima, &aspx, &aspy);
2290 /* uv coords are scaled by aspects. this is needed for rotations and
2291 proportional editing to be consistent with the stretchted uv coords
2292 that are displayed. this also means that for display and numinput,
2293 and when the the uv coords are flushed, these are converted each time */
2294 td2d->loc[0] = uv[0]*aspx;
2295 td2d->loc[1] = uv[1]*aspy;
2296 td2d->loc[2] = 0.0f;
2300 td->loc = td2d->loc;
2301 VECCOPY(td->center, td->loc);
2302 VECCOPY(td->iloc, td->loc);
2304 memset(td->axismtx, 0, sizeof(td->axismtx));
2305 td->axismtx[2][2] = 1.0f;
2307 td->ext= NULL; td->val= NULL;
2310 td->flag |= TD_SELECTED;
2320 static void createTransUVs(bContext *C, TransInfo *t)
2322 SpaceImage *sima = CTX_wm_space_image(C);
2323 Image *ima = CTX_data_edit_image(C);
2324 Scene *scene = t->scene;
2325 TransData *td = NULL;
2326 TransData2D *td2d = NULL;
2328 int count=0, countsel=0;
2329 int propmode = t->flag & T_PROP_EDIT;
2331 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2334 if(!ED_space_image_show_uvedit(sima, t->obedit)) return;
2337 for (efa= em->faces.first; efa; efa= efa->next) {
2338 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2340 if(uvedit_face_visible(scene, ima, efa, tf)) {
2343 if (uvedit_uv_selected(scene, efa, tf, 0)) countsel++;
2344 if (uvedit_uv_selected(scene, efa, tf, 1)) countsel++;
2345 if (uvedit_uv_selected(scene, efa, tf, 2)) countsel++;
2346 if (efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) countsel++;
2348 count += (efa->v4)? 4: 3;
2354 /* note: in prop mode we need at least 1 selected */
2355 if (countsel==0) return;
2357 t->total= (propmode)? count: countsel;
2358 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2359 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2360 treated just as if they were 3d verts */
2361 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2363 if(sima->flag & SI_CLIP_UV)
2364 t->flag |= T_CLIP_UV;
2369 for (efa= em->faces.first; efa; efa= efa->next) {
2370 if ((tf=(MTFace *)efa->tmp.p)) {
2372 UVsToTransData(sima, td++, td2d++, tf->uv[0], uvedit_uv_selected(scene, efa, tf, 0));
2373 UVsToTransData(sima, td++, td2d++, tf->uv[1], uvedit_uv_selected(scene, efa, tf, 1));
2374 UVsToTransData(sima, td++, td2d++, tf->uv[2], uvedit_uv_selected(scene, efa, tf, 2));
2376 UVsToTransData(sima, td++, td2d++, tf->uv[3], uvedit_uv_selected(scene, efa, tf, 3));
2378 if(uvedit_uv_selected(scene, efa, tf, 0)) UVsToTransData(sima, td++, td2d++, tf->uv[0], 1);
2379 if(uvedit_uv_selected(scene, efa, tf, 1)) UVsToTransData(sima, td++, td2d++, tf->uv[1], 1);
2380 if(uvedit_uv_selected(scene, efa, tf, 2)) UVsToTransData(sima, td++, td2d++, tf->uv[2], 1);
2381 if(efa->v4 && uvedit_uv_selected(scene, efa, tf, 3)) UVsToTransData(sima, td++, td2d++, tf->uv[3], 1);
2386 if (sima->flag & SI_LIVE_UNWRAP)
2387 ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
2390 void flushTransUVs(TransInfo *t)
2392 SpaceImage *sima = t->sa->spacedata.first;
2394 int a, width, height;
2395 float aspx, aspy, invx, invy;
2397 ED_space_image_uv_aspect(sima, &aspx, &aspy);
2398 ED_space_image_size(sima, &width, &height);
2402 /* flush to 2d vector from internally used 3d vector */
2403 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2404 td->loc2d[0]= td->loc[0]*invx;
2405 td->loc2d[1]= td->loc[1]*invy;
2407 if((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2408 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2409 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2414 int clipUVTransform(TransInfo *t, float *vec, int resize)
2417 int a, clipx=1, clipy=1;
2418 float aspx, aspy, min[2], max[2];
2420 ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
2421 min[0]= min[1]= 0.0f;
2422 max[0]= aspx; max[1]= aspy;
2424 for(a=0, td= t->data; a<t->total; a++, td++) {
2425 DO_MINMAX2(td->loc, min, max);
2429 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2430 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2431 else if(max[0] > aspx && t->center[0] < aspx)
2432 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2436 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2437 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2438 else if(max[1] > aspy && t->center[1] < aspy)
2439 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2446 else if(max[0] > aspx)
2447 vec[0] -= max[0]-aspx;
2453 else if(max[1] > aspy)
2454 vec[1] -= max[1]-aspy;
2459 return (clipx || clipy);
2462 /* ********************* ANIMATION EDITORS (GENERAL) ************************* */
2464 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
2465 static short FrameOnMouseSide(char side, float frame, float cframe)
2467 /* both sides, so it doesn't matter */
2468 if (side == 'B') return 1;
2470 /* only on the named side */
2472 return (frame >= cframe) ? 1 : 0;
2474 return (frame <= cframe) ? 1 : 0;
2477 /* ********************* NLA EDITOR ************************* */
2479 static void createTransNlaData(bContext *C, TransInfo *t)
2481 Scene *scene= t->scene;
2482 TransData *td = NULL;
2483 TransDataNla *tdn = NULL;
2486 ListBase anim_data = {NULL, NULL};
2492 /* determine what type of data we are operating on */
2493 if (ANIM_animdata_get_context(C, &ac) == 0)
2497 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_NLATRACKS | ANIMFILTER_FOREDIT);
2498 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2500 /* which side of the current frame should be allowed */
2501 if (t->mode == TFM_TIME_EXTEND) {
2502 /* only side on which mouse is gets transformed */
2503 float xmouse, ymouse;
2505 UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
2506 t->frame_side= (xmouse > CFRA) ? 'R' : 'L';
2509 /* normal transform - both sides of current frame are considered */
2510 t->frame_side = 'B';
2513 /* loop 1: count how many strips are selected (consider each strip as 2 points) */
2514 for (ale= anim_data.first; ale; ale= ale->next) {
2515 NlaTrack *nlt= (NlaTrack *)ale->data;
2518 /* make some meta-strips for chains of selected strips */
2519 BKE_nlastrips_make_metas(&nlt->strips, 1);
2521 /* only consider selected strips */
2522 for (strip= nlt->strips.first; strip; strip= strip->next) {
2523 // TODO: we can make strips have handles later on...
2524 /* transition strips can't get directly transformed */
2525 if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2526 if (strip->flag & NLASTRIP_FLAG_SELECT) {
2527 if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) count++;
2528 if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) count++;
2534 /* stop if trying to build list if nothing selected */
2536 /* cleanup temp list */
2537 BLI_freelistN(&anim_data);
2541 /* allocate memory for data */
2544 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)");
2546 t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)");
2549 /* loop 2: build transdata array */
2550 for (ale= anim_data.first; ale; ale= ale->next) {
2551 /* only if a real NLA-track */
2552 if (ale->type == ANIMTYPE_NLATRACK) {
2553 AnimData *adt = ale->adt;
2554 NlaTrack *nlt= (NlaTrack *)ale->data;
2557 /* only consider selected strips */
2558 for (strip= nlt->strips.first; strip; strip= strip->next) {
2559 // TODO: we can make strips have handles later on...
2560 /* transition strips can't get directly transformed */
2561 if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2562 if (strip->flag & NLASTRIP_FLAG_SELECT) {
2563 /* our transform data is constructed as follows:
2564 * - only the handles on the right side of the current-frame get included
2565 * - td structs are transform-elements operated on by the transform system
2566 * and represent a single handle. The storage/pointer used (val or loc) depends on
2567 * whether we're scaling or transforming. Ultimately though, the handles
2568 * the td writes to will simply be a dummy in tdn
2569 * - for each strip being transformed, a single tdn struct is used, so in some
2570 * cases, there will need to be 1 of these tdn elements in the array skipped...
2572 float center[3], yval;
2574 /* firstly, init tdn settings */
2576 tdn->oldTrack= tdn->nlt= nlt;
2578 tdn->trackIndex= BLI_findindex(&adt->nla_tracks, nlt);
2580 yval= (float)(tdn->trackIndex * NLACHANNEL_STEP);
2582 tdn->h1[0]= strip->start;
2584 tdn->h2[0]= strip->end;
2587 center[0]= (float)CFRA;
2591 /* set td's based on which handles are applicable */
2592 if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA))
2594 /* just set tdn to assume that it only has one handle for now */
2597 /* now, link the transform data up to this data */
2598 if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
2600 VECCOPY(td->iloc, tdn->h1);
2602 /* store all the other gunk that is required by transform */
2603 VECCOPY(td->center, center);
2604 memset(td->axismtx, 0, sizeof(td->axismtx));
2605 td->axismtx[2][2] = 1.0f;
2607 td->ext= NULL; td->val= NULL;
2609 td->flag |= TD_SELECTED;
2616 /* time scaling only needs single value */
2617 td->val= &tdn->h1[0];
2618 td->ival= tdn->h1[0];
2624 if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA))
2626 /* if tdn is already holding the start handle, then we're doing both, otherwise, only end */
2627 tdn->handle= (tdn->handle) ? 2 : 1;
2629 /* now, link the transform data up to this data */
2630 if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
2632 VECCOPY(td->iloc, tdn->h2);
2634 /* store all the other gunk that is required by transform */
2635 VECCOPY(td->center, center);
2636 memset(td->axismtx, 0, sizeof(td->axismtx));
2637 td->axismtx[2][2] = 1.0f;
2639 td->ext= NULL; td->val= NULL;
2641 td->flag |= TD_SELECTED;
2648 /* time scaling only needs single value */
2649 td->val= &tdn->h2[0];
2650 td->ival= tdn->h2[0];
2657 /* if both handles were used, skip the next tdn (i.e. leave it blank) since the counting code is dumb...
2658 * otherwise, just advance to the next one...
2660 if (tdn->handle == 2)
2670 /* cleanup temp list */
2671 BLI_freelistN(&anim_data);
2674 /* ********************* ACTION EDITOR ****************** */
2676 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2677 * any other gp-frames which may reside on that frame (that are not selected).
2678 * It also makes sure gp-frames are still stored in chronological order after
2681 static void posttrans_gpd_clean (bGPdata *gpd)
2685 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2686 ListBase sel_buffer = {NULL, NULL};
2687 bGPDframe *gpf, *gpfn;
2688 bGPDframe *gfs, *gfsn;
2690 /* loop 1: loop through and isolate selected gp-frames to buffer
2691 * (these need to be sorted as they are isolated)
2693 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2697 if (gpf->flag & GP_FRAME_SELECT) {
2698 BLI_remlink(&gpl->frames, gpf);
2700 /* find place to add them in buffer
2701 * - go backwards as most frames will still be in order,
2702 * so doing it this way will be faster
2704 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2705 /* if current (gpf) occurs after this one in buffer, add! */
2706 if (gfs->framenum < gpf->framenum) {
2707 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2713 BLI_addhead(&sel_buffer, gpf);
2717 /* error checking: it is unlikely, but may be possible to have none selected */
2718 if (sel_buffer.first == NULL)
2721 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2722 if (gpl->frames.first == NULL) {
2723 gpl->frames.first= sel_buffer.first;
2724 gpl->frames.last= sel_buffer.last;
2729 /* loop 2: remove duplicates of frames in buffers */
2730 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2733 /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2734 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2737 /* if this buffer frame needs to go before current, add it! */
2738 if (gfs->framenum < gpf->framenum) {
2739 /* transfer buffer frame to frames list (before current) */
2740 BLI_remlink(&sel_buffer, gfs);
2741 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2743 /* if this buffer frame is on same frame, replace current with it and stop */
2744 else if (gfs->framenum == gpf->framenum) {
2745 /* transfer buffer frame to frames list (before current) */
2746 BLI_remlink(&sel_buffer, gfs);
2747 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2749 /* get rid of current frame */
2750 gpencil_layer_delframe(gpl, gpf);