2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/transform/transform_conversions.c
29 * \ingroup edtransform
41 #include "DNA_anim_types.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_lattice_types.h"
44 #include "DNA_meta_types.h"
45 #include "DNA_node_types.h"
46 #include "DNA_screen_types.h"
47 #include "DNA_space_types.h"
48 #include "DNA_sequence_types.h"
49 #include "DNA_view3d_types.h"
50 #include "DNA_constraint_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_gpencil_types.h"
54 #include "DNA_movieclip_types.h"
56 #include "MEM_guardedalloc.h"
58 #include "BKE_action.h"
59 #include "BKE_armature.h"
60 #include "BKE_context.h"
61 #include "BKE_curve.h"
62 #include "BKE_constraint.h"
63 #include "BKE_depsgraph.h"
64 #include "BKE_fcurve.h"
65 #include "BKE_gpencil.h"
66 #include "BKE_global.h"
69 #include "BKE_modifier.h"
71 #include "BKE_object.h"
72 #include "BKE_particle.h"
73 #include "BKE_sequencer.h"
74 #include "BKE_pointcache.h"
75 #include "BKE_bmesh.h"
76 #include "BKE_tessmesh.h"
77 #include "BKE_scene.h"
78 #include "BKE_report.h"
79 #include "BKE_tracking.h"
80 #include "BKE_movieclip.h"
84 #include "ED_anim_api.h"
85 #include "ED_armature.h"
86 #include "ED_particle.h"
88 #include "ED_keyframing.h"
89 #include "ED_keyframes_edit.h"
90 #include "ED_object.h"
91 #include "ED_markers.h"
95 #include "ED_uvedit.h"
97 #include "ED_util.h" /* for crazyspace correction */
99 #include "WM_api.h" /* for WM_event_add_notifier to deal with stabilization nodes */
100 #include "WM_types.h"
102 #include "UI_view2d.h"
104 #include "BLI_math.h"
105 #include "BLI_blenlib.h"
106 #include "BLI_editVert.h"
107 #include "BLI_array.h"
108 #include "BLI_utildefines.h"
109 #include "BLI_smallhash.h"
111 #include "RNA_access.h"
113 extern ListBase editelems;
115 #include "transform.h"
118 #include "BLO_sys_types.h" // for intptr_t support
120 /* local function prototype - for Object/Bone Constraints */
121 static short constraints_list_needinv(TransInfo *t, ListBase *list);
123 /* ************************** Functions *************************** */
125 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail, TransData *temp) {
126 TransData *ihead = head;
127 TransData *itail = tail;
132 if (t->flag & T_PROP_CONNECTED) {
133 while ((tail->dist >= temp->dist) && (head < tail))
137 while ((tail->rdist >= temp->rdist) && (head < tail))
147 if (t->flag & T_PROP_CONNECTED) {
148 while ((head->dist <= temp->dist) && (head < tail))
152 while ((head->rdist <= temp->rdist) && (head < tail))
165 qsort_trans_data(t, ihead, head-1, temp);
168 qsort_trans_data(t, head+1, itail, temp);
172 void sort_trans_data_dist(TransInfo *t) {
174 TransData *start = t->data;
177 while(i < t->total && start->flag & TD_SELECTED) {
181 qsort_trans_data(t, start, t->data + t->total - 1, &temp);
184 static void sort_trans_data(TransInfo *t)
186 TransData *sel, *unsel;
191 while (sel > unsel) {
192 while (unsel->flag & TD_SELECTED) {
198 while (!(sel->flag & TD_SELECTED)) {
212 /* distance calculated from not-selected vertex to nearest selected vertex
213 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
214 static void set_prop_dist(TransInfo *t, short with_dist)
219 for(a=0, tob= t->data; a<t->total; a++, tob++) {
221 tob->rdist= 0.0f; // init, it was mallocced
223 if((tob->flag & TD_SELECTED)==0) {
228 tob->rdist = -1.0f; // signal for next loop
230 for (i = 0, td= t->data; i < t->total; i++, td++) {
231 if(td->flag & TD_SELECTED) {
232 sub_v3_v3v3(vec, tob->center, td->center);
233 mul_m3_v3(tob->mtx, vec);
234 dist = normalize_v3(vec);
235 if (tob->rdist == -1.0f) {
238 else if (dist < tob->rdist) {
242 else break; // by definition transdata has selected items in beginning
245 tob->dist = tob->rdist;
251 /* ************************** CONVERSIONS ************************* */
253 /* ********************* texture space ********* */
255 static void createTransTexspace(TransInfo *t)
257 Scene *scene = t->scene;
265 if (ob == NULL) { // Shouldn't logically happen, but still...
271 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
277 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
278 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
280 td->flag= TD_SELECTED;
281 copy_v3_v3(td->center, ob->obmat[3]);
284 copy_m3_m4(td->mtx, ob->obmat);
285 copy_m3_m4(td->axismtx, ob->obmat);
286 normalize_m3(td->axismtx);
287 invert_m3_m3(td->smtx, td->mtx);
289 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
290 ob->dtx |= OB_TEXSPACE;
291 *texflag &= ~AUTOSPACE;
294 copy_v3_v3(td->iloc, td->loc);
295 copy_v3_v3(td->ext->irot, td->ext->rot);
296 copy_v3_v3(td->ext->isize, td->ext->size);
299 /* ********************* edge (for crease) ***** */
301 static void createTransEdge(TransInfo *t) {
302 BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
303 TransData *td = NULL;
306 float mtx[3][3], smtx[3][3];
307 int count=0, countsel=0;
308 int propmode = t->flag & T_PROP_EDIT;
310 BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
311 if (BM_TestHFlag(eed, BM_HIDDEN))
314 if (BM_TestHFlag(eed, BM_SELECT)) countsel++;
315 if (propmode) count++;
328 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
330 copy_m3_m4(mtx, t->obedit->obmat);
331 invert_m3_m3(smtx, mtx);
333 BM_ITER(eed, &iter, em->bm, BM_EDGES_OF_MESH, NULL) {
334 if(!BM_TestHFlag(eed, BM_HIDDEN) && (BM_TestHFlag(eed, BM_SELECT) || propmode)) {
335 float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT);
336 float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE);
338 /* need to set center for center calculations */
339 add_v3_v3v3(td->center, eed->v1->co, eed->v2->co);
340 mul_v3_fl(td->center, 0.5f);
343 if (BM_TestHFlag(eed, BM_SELECT))
344 td->flag= TD_SELECTED;
349 copy_m3_m3(td->smtx, smtx);
350 copy_m3_m3(td->mtx, mtx);
353 if (t->mode == TFM_BWEIGHT) {
355 td->ival = bweight ? *bweight : 1.0f;
359 td->ival = crease ? *crease : 0.0f;
367 /* ********************* pose mode ************* */
369 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
371 bConstraint *con= pchan->constraints.first;
373 for(;con; con= con->next) {
374 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0f)) {
375 bKinematicConstraint *data= con->data;
379 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
386 static short apply_targetless_ik(Object *ob)
388 bPoseChannel *pchan, *parchan, *chanlist[256];
389 bKinematicConstraint *data;
390 int segcount, apply= 0;
392 /* now we got a difficult situation... we have to find the
393 target-less IK pchans, and apply transformation to the all
394 pchans that were in the chain */
396 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
397 data= has_targetless_ik(pchan);
398 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
400 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
403 /* exclude tip from chain? */
404 if(!(data->flag & CONSTRAINT_IK_TIP))
405 parchan= pchan->parent;
409 /* Find the chain's root & count the segments needed */
410 for (; parchan; parchan=parchan->parent){
411 chanlist[segcount]= parchan;
414 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
416 for(;segcount;segcount--) {
418 float rmat[4][4], tmat[4][4], imat[4][4];
420 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
421 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
422 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
423 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
425 parchan= chanlist[segcount-1];
427 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
429 if(parchan->parent) {
430 Bone *parbone= parchan->parent->bone;
431 float offs_bone[4][4];
433 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
434 copy_m4_m3(offs_bone, bone->bone_mat);
436 /* The bone's root offset (is in the parent's coordinate system) */
437 copy_v3_v3(offs_bone[3], bone->head);
439 /* Get the length translation of parent (length along y axis) */
440 offs_bone[3][1]+= parbone->length;
442 /* pose_mat(b-1) * offs_bone */
443 if(parchan->bone->flag & BONE_HINGE) {
444 /* the rotation of the parent restposition */
445 copy_m4_m4(rmat, parbone->arm_mat); /* rmat used as temp */
447 /* the location of actual parent transform */
448 copy_v3_v3(rmat[3], offs_bone[3]);
449 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
450 mul_m4_v3(parchan->parent->pose_mat, rmat[3]);
452 mul_m4_m4m4(tmat, offs_bone, rmat);
454 else if(parchan->bone->flag & BONE_NO_SCALE) {
455 mul_m4_m4m4(tmat, offs_bone, parchan->parent->pose_mat);
459 mul_m4_m4m4(tmat, offs_bone, parchan->parent->pose_mat);
461 invert_m4_m4(imat, tmat);
464 copy_m4_m3(tmat, bone->bone_mat);
466 copy_v3_v3(tmat[3], bone->head);
467 invert_m4_m4(imat, tmat);
470 mul_m4_m4m4(rmat, parchan->pose_mat, imat);
472 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
474 float rmat3[3][3], qrmat[3][3], imat3[3][3], smat[3][3];
476 copy_m3_m4(rmat3, rmat);
479 /* [#22409] is partially caused by this, as slight numeric error introduced during
480 * the solving process leads to locked-axis values changing. However, we cannot modify
481 * the values here, or else there are huge discreptancies between IK-solver (interactive)
484 if (parchan->rotmode > 0)
485 mat3_to_eulO(parchan->eul, parchan->rotmode,rmat3);
486 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
487 mat3_to_axis_angle(parchan->rotAxis, &parchan->rotAngle,rmat3);
489 mat3_to_quat(parchan->quat,rmat3);
491 /* for size, remove rotation */
492 /* causes problems with some constraints (so apply only if needed) */
493 if (data->flag & CONSTRAINT_IK_STRETCH) {
494 if (parchan->rotmode > 0)
495 eulO_to_mat3( qrmat,parchan->eul, parchan->rotmode);
496 else if (parchan->rotmode == ROT_MODE_AXISANGLE)
497 axis_angle_to_mat3( qrmat,parchan->rotAxis, parchan->rotAngle);
499 quat_to_mat3( qrmat,parchan->quat);
501 invert_m3_m3(imat3, qrmat);
502 mul_m3_m3m3(smat, rmat3, imat3);
503 mat3_to_size( parchan->size,smat);
506 /* causes problems with some constraints (e.g. childof), so disable this */
507 /* as it is IK shouldn't affect location directly */
508 /* copy_v3_v3(parchan->loc, rmat[3]); */
514 data->flag &= ~CONSTRAINT_IK_AUTO;
521 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
523 Bone *bone= pchan->bone;
524 float pmat[3][3], omat[3][3], bmat[3][3];
525 float cmat[3][3], tmat[3][3];
528 copy_v3_v3(vec, pchan->pose_mat[3]);
529 copy_v3_v3(td->center, vec);
532 td->flag = TD_SELECTED;
533 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
535 td->flag |= TD_NOCENTER;
538 if (bone->flag & BONE_TRANSFORM_CHILD)
540 td->flag |= TD_NOCENTER;
541 td->flag |= TD_NO_LOC;
544 td->protectflag= pchan->protectflag;
546 td->loc = pchan->loc;
547 copy_v3_v3(td->iloc, pchan->loc);
549 td->ext->size= pchan->size;
550 copy_v3_v3(td->ext->isize, pchan->size);
552 if (pchan->rotmode > 0) {
553 td->ext->rot= pchan->eul;
554 td->ext->rotAxis= NULL;
555 td->ext->rotAngle= NULL;
558 copy_v3_v3(td->ext->irot, pchan->eul);
560 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
562 td->ext->rotAxis= pchan->rotAxis;
563 td->ext->rotAngle= &pchan->rotAngle;
566 td->ext->irotAngle= pchan->rotAngle;
567 copy_v3_v3(td->ext->irotAxis, pchan->rotAxis);
571 td->ext->rotAxis= NULL;
572 td->ext->rotAngle= NULL;
573 td->ext->quat= pchan->quat;
575 copy_qt_qt(td->ext->iquat, pchan->quat);
577 td->ext->rotOrder= pchan->rotmode;
580 /* proper way to get parent transform + own transform + constraints transform */
581 copy_m3_m4(omat, ob->obmat);
583 if (ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION))
586 copy_m3_m3(bmat, pchan->bone->bone_mat);
589 if(pchan->bone->flag & BONE_HINGE)
590 copy_m3_m4(pmat, pchan->parent->bone->arm_mat);
592 copy_m3_m4(pmat, pchan->parent->pose_mat);
594 if (constraints_list_needinv(t, &pchan->constraints)) {
595 copy_m3_m4(tmat, pchan->constinv);
596 invert_m3_m3(cmat, tmat);
597 mul_serie_m3(td->mtx, bmat, pmat, omat, cmat, NULL,NULL,NULL,NULL); // dang mulserie swaps args
600 mul_serie_m3(td->mtx, bmat, pmat, omat, NULL,NULL,NULL,NULL,NULL); // dang mulserie swaps args
603 if (constraints_list_needinv(t, &pchan->constraints)) {
604 copy_m3_m4(tmat, pchan->constinv);
605 invert_m3_m3(cmat, tmat);
606 mul_serie_m3(td->mtx, bmat, omat, cmat, NULL,NULL,NULL,NULL,NULL); // dang mulserie swaps args
609 mul_m3_m3m3(td->mtx, omat, bmat); // Mat3MulMat3 has swapped args!
612 invert_m3_m3(td->smtx, td->mtx);
614 /* exceptional case: rotate the pose bone which also applies transformation
615 * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */
616 if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) {
618 /* same as td->smtx but without pchan->bone->bone_mat */
619 td->flag |= TD_PBONE_LOCAL_MTX_C;
620 mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx);
623 td->flag |= TD_PBONE_LOCAL_MTX_P;
627 /* for axismat we use bone's own transform */
628 copy_m3_m4(pmat, pchan->pose_mat);
629 mul_m3_m3m3(td->axismtx, omat, pmat);
630 normalize_m3(td->axismtx);
632 if (t->mode==TFM_BONESIZE) {
633 bArmature *arm= t->poseobj->data;
635 if(arm->drawtype==ARM_ENVELOPE) {
637 td->val= &bone->dist;
638 td->ival= bone->dist;
641 // abusive storage of scale in the loc pointer :)
642 td->loc= &bone->xwidth;
643 copy_v3_v3(td->iloc, td->loc);
648 /* in this case we can do target-less IK grabbing */
649 if (t->mode==TFM_TRANSLATION) {
650 bKinematicConstraint *data= has_targetless_ik(pchan);
652 if(data->flag & CONSTRAINT_IK_TIP) {
653 copy_v3_v3(data->grabtarget, pchan->pose_tail);
656 copy_v3_v3(data->grabtarget, pchan->pose_head);
658 td->loc = data->grabtarget;
659 copy_v3_v3(td->iloc, td->loc);
660 data->flag |= CONSTRAINT_IK_AUTO;
662 /* only object matrix correction */
663 copy_m3_m3(td->mtx, omat);
664 invert_m3_m3(td->smtx, td->mtx);
668 /* store reference to first constraint */
669 td->con= pchan->constraints.first;
672 static void bone_children_clear_transflag(int mode, short around, ListBase *lb)
674 Bone *bone= lb->first;
676 for(;bone;bone= bone->next) {
677 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
679 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
681 else if (bone->flag & BONE_TRANSFORM && (mode == TFM_ROTATION || mode == TFM_TRACKBALL) && around == V3D_LOCAL)
683 bone->flag |= BONE_TRANSFORM_CHILD;
687 bone->flag &= ~BONE_TRANSFORM;
690 bone_children_clear_transflag(mode, around, &bone->childbase);
694 /* sets transform flags in the bones
695 * returns total number of bones with BONE_TRANSFORM */
696 int count_set_pose_transflags(int *out_mode, short around, Object *ob)
698 bArmature *arm= ob->data;
701 int mode = *out_mode;
702 int hastranslation = 0;
705 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
707 if (PBONE_VISIBLE(arm, bone)) {
708 if ((bone->flag & BONE_SELECTED))
709 bone->flag |= BONE_TRANSFORM;
711 bone->flag &= ~BONE_TRANSFORM;
713 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
714 bone->flag &= ~BONE_TRANSFORM_CHILD;
717 bone->flag &= ~BONE_TRANSFORM;
720 /* make sure no bone can be transformed when a parent is transformed */
721 /* since pchans are depsgraph sorted, the parents are in beginning of list */
722 if(mode != TFM_BONESIZE) {
723 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
725 if(bone->flag & BONE_TRANSFORM)
726 bone_children_clear_transflag(mode, around, &bone->childbase);
729 /* now count, and check if we have autoIK or have to switch from translate to rotate */
732 for(pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
734 if(bone->flag & BONE_TRANSFORM) {
737 if(mode == TFM_TRANSLATION) {
738 if( has_targetless_ik(pchan)==NULL ) {
739 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
740 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
743 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
752 /* if there are no translatable bones, do rotation */
753 if(mode == TFM_TRANSLATION && !hastranslation)
755 *out_mode = TFM_ROTATION;
762 /* -------- Auto-IK ---------- */
764 /* adjust pose-channel's auto-ik chainlen */
765 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
769 /* don't bother to search if no valid constraints */
770 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
773 /* check if pchan has ik-constraint */
774 for (con= pchan->constraints.first; con; con= con->next) {
775 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0f)) {
776 bKinematicConstraint *data= con->data;
778 /* only accept if a temporary one (for auto-ik) */
779 if (data->flag & CONSTRAINT_IK_TEMP) {
780 /* chainlen is new chainlen, but is limited by maximum chainlen */
781 if ((chainlen==0) || (chainlen > data->max_rootbone))
782 data->rootbone= data->max_rootbone;
784 data->rootbone= chainlen;
790 /* change the chain-length of auto-ik */
791 void transform_autoik_update (TransInfo *t, short mode)
793 short *chainlen= &t->settings->autoik_chainlen;
796 /* mode determines what change to apply to chainlen */
798 /* mode=1 is from WHEELMOUSEDOWN... increases len */
801 else if (mode == -1) {
802 /* mode==-1 is from WHEELMOUSEUP... decreases len */
803 if (*chainlen > 0) (*chainlen)--;
806 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
807 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
810 /* apply to all pose-channels */
811 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
812 pchan_autoik_adjust(pchan, *chainlen);
816 /* frees temporal IKs */
817 static void pose_grab_with_ik_clear(Object *ob)
819 bKinematicConstraint *data;
821 bConstraint *con, *next;
823 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
824 /* clear all temporary lock flags */
825 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
827 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
829 /* remove all temporary IK-constraints added */
830 for (con= pchan->constraints.first; con; con= next) {
832 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
834 if (data->flag & CONSTRAINT_IK_TEMP) {
835 BLI_remlink(&pchan->constraints, con);
836 MEM_freeN(con->data);
840 pchan->constflag |= PCHAN_HAS_IK;
841 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
842 pchan->constflag |= PCHAN_HAS_TARGET;
848 /* adds the IK to pchan - returns if added */
849 static short pose_grab_with_ik_add(bPoseChannel *pchan)
851 bKinematicConstraint *targetless = NULL;
852 bKinematicConstraint *data;
859 /* Rule: not if there's already an IK on this channel */
860 for (con= pchan->constraints.first; con; con= con->next) {
861 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
864 if (data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]=='\0')) {
865 /* make reference to constraint to base things off later (if it's the last targetless constraint encountered) */
866 targetless = (bKinematicConstraint *)con->data;
868 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
869 if (con->enforce!=0.0f) {
870 data->flag |= CONSTRAINT_IK_AUTO;
872 /* if no chain length has been specified, just make things obey standard rotation locks too */
873 if (data->rootbone == 0) {
874 for (; pchan; pchan=pchan->parent) {
875 /* here, we set ik-settings for bone from pchan->protectflag */
876 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
877 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
878 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
879 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
887 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0f))
892 con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC);
893 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
896 /* if exists, use values from last targetless (but disabled) IK-constraint as base */
900 data->flag= CONSTRAINT_IK_TIP;
901 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
902 copy_v3_v3(data->grabtarget, pchan->pose_tail);
903 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] */
905 /* we only include bones that are part of a continual connected chain */
907 /* here, we set ik-settings for bone from pchan->protectflag */
908 // XXX: careful with quats/axis-angle rotations where we're locking 4d components
909 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
910 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
911 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
913 /* now we count this pchan as being included */
916 /* continue to parent, but only if we're connected to it */
917 if (pchan->bone->flag & BONE_CONNECTED)
918 pchan = pchan->parent;
923 /* make a copy of maximum chain-length */
924 data->max_rootbone= data->rootbone;
929 /* bone is a candidate to get IK, but we don't do it if it has children connected */
930 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
933 short wentdeeper=0, added=0;
935 /* go deeper if children & children are connected */
936 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
937 if (bonec->flag & BONE_CONNECTED) {
939 added+= pose_grab_with_ik_children(pose, bonec);
943 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
945 added+= pose_grab_with_ik_add(pchan);
951 /* main call which adds temporal IK chains */
952 static short pose_grab_with_ik(Object *ob)
955 bPoseChannel *pchan, *parent;
959 if ((ob==NULL) || (ob->pose==NULL) || (ob->mode & OB_MODE_POSE)==0)
964 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
965 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
966 if (pchan->bone->layer & arm->layer) {
967 if (pchan->bone->flag & BONE_SELECTED) {
968 /* Rule: no IK for solitatry (unconnected) bones */
969 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
970 if (bonec->flag & BONE_CONNECTED) {
974 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
977 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
979 /* only adds if there's no IK yet (and no parent bone was selected) */
980 for (parent= pchan->parent; parent; parent= parent->parent) {
981 if (parent->bone->flag & BONE_SELECTED)
985 tot_ik += pose_grab_with_ik_add(pchan);
988 /* rule: go over the children and add IK to the tips */
989 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
995 return (tot_ik) ? 1 : 0;
999 /* only called with pose mode active object now */
1000 static void createTransPose(TransInfo *t, Object *ob)
1003 bPoseChannel *pchan;
1005 TransDataExtension *tdx;
1011 /* check validity of state */
1012 arm= get_armature(ob);
1013 if ((arm==NULL) || (ob->pose==NULL)) return;
1015 if (arm->flag & ARM_RESTPOS) {
1016 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
1017 // XXX use transform operator reports
1018 // BKE_report(op->reports, RPT_ERROR, "Can't select linked when sync selection is enabled");
1023 /* do we need to add temporal IK chains? */
1024 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
1025 ik_on= pose_grab_with_ik(ob);
1026 if (ik_on) t->flag |= T_AUTOIK;
1029 /* set flags and count total (warning, can change transform to rotate) */
1030 t->total = count_set_pose_transflags(&t->mode, t->around, ob);
1032 if(t->total == 0) return;
1035 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
1037 /* init trans data */
1038 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
1039 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
1040 for(i=0; i<t->total; i++, td++, tdx++) {
1045 /* use pose channels to fill trans data */
1047 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1048 if (pchan->bone->flag & BONE_TRANSFORM) {
1049 add_pose_transdata(t, pchan, ob, td);
1054 if(td != (t->data+t->total)) {
1055 // XXX use transform operator reports
1056 // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error");
1059 /* initialise initial auto=ik chainlen's? */
1060 if (ik_on) transform_autoik_update(t, 0);
1063 /* ********************* armature ************** */
1065 static void createTransArmatureVerts(TransInfo *t)
1068 bArmature *arm= t->obedit->data;
1069 ListBase *edbo = arm->edbo;
1071 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1073 /* special hack for envelope drawmode and scaling:
1074 * to allow scaling the size of the envelope around single points,
1075 * mode should become TFM_BONE_ENVELOPE in this case
1077 // TODO: maybe we need a separate hotkey for it, but this is consistent with 2.4x for now
1078 if ((t->mode == TFM_RESIZE) && (arm->drawtype==ARM_ENVELOPE))
1079 t->mode= TFM_BONE_ENVELOPE;
1082 for (ebo = edbo->first; ebo; ebo = ebo->next)
1084 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED))
1086 if (t->mode==TFM_BONESIZE)
1088 if (ebo->flag & BONE_SELECTED)
1091 else if (t->mode==TFM_BONE_ROLL)
1093 if (ebo->flag & BONE_SELECTED)
1098 if (ebo->flag & BONE_TIPSEL)
1100 if (ebo->flag & BONE_ROOTSEL)
1106 if (!t->total) return;
1108 copy_m3_m4(mtx, t->obedit->obmat);
1109 invert_m3_m3(smtx, mtx);
1111 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1113 for (ebo = edbo->first; ebo; ebo = ebo->next)
1115 ebo->oldlength = ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1117 if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED))
1119 if (t->mode==TFM_BONE_ENVELOPE)
1121 if (ebo->flag & BONE_ROOTSEL)
1123 td->val= &ebo->rad_head;
1126 copy_v3_v3(td->center, ebo->head);
1127 td->flag= TD_SELECTED;
1129 copy_m3_m3(td->smtx, smtx);
1130 copy_m3_m3(td->mtx, mtx);
1138 if (ebo->flag & BONE_TIPSEL)
1140 td->val= &ebo->rad_tail;
1142 copy_v3_v3(td->center, ebo->tail);
1143 td->flag= TD_SELECTED;
1145 copy_m3_m3(td->smtx, smtx);
1146 copy_m3_m3(td->mtx, mtx);
1156 else if (t->mode==TFM_BONESIZE)
1158 if (ebo->flag & BONE_SELECTED) {
1159 if(arm->drawtype==ARM_ENVELOPE)
1162 td->val= &ebo->dist;
1163 td->ival= ebo->dist;
1167 // abusive storage of scale in the loc pointer :)
1168 td->loc= &ebo->xwidth;
1169 copy_v3_v3(td->iloc, td->loc);
1172 copy_v3_v3(td->center, ebo->head);
1173 td->flag= TD_SELECTED;
1175 /* use local bone matrix */
1176 sub_v3_v3v3(delta, ebo->tail, ebo->head);
1177 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1178 mul_m3_m3m3(td->mtx, mtx, bonemat);
1179 invert_m3_m3(td->smtx, td->mtx);
1181 copy_m3_m3(td->axismtx, td->mtx);
1182 normalize_m3(td->axismtx);
1190 else if (t->mode==TFM_BONE_ROLL)
1192 if (ebo->flag & BONE_SELECTED)
1195 td->val= &(ebo->roll);
1196 td->ival= ebo->roll;
1198 copy_v3_v3(td->center, ebo->head);
1199 td->flag= TD_SELECTED;
1209 if (ebo->flag & BONE_TIPSEL)
1211 copy_v3_v3(td->iloc, ebo->tail);
1212 copy_v3_v3(td->center, (t->around==V3D_LOCAL) ? ebo->head : td->iloc);
1214 td->flag= TD_SELECTED;
1215 if (ebo->flag & BONE_EDITMODE_LOCKED)
1216 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1218 copy_m3_m3(td->smtx, smtx);
1219 copy_m3_m3(td->mtx, mtx);
1221 sub_v3_v3v3(delta, ebo->tail, ebo->head);
1222 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1224 if ((ebo->flag & BONE_ROOTSEL) == 0)
1235 if (ebo->flag & BONE_ROOTSEL)
1237 copy_v3_v3(td->iloc, ebo->head);
1238 copy_v3_v3(td->center, td->iloc);
1240 td->flag= TD_SELECTED;
1241 if (ebo->flag & BONE_EDITMODE_LOCKED)
1242 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1244 copy_m3_m3(td->smtx, smtx);
1245 copy_m3_m3(td->mtx, mtx);
1247 sub_v3_v3v3(delta, ebo->tail, ebo->head);
1248 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1250 td->extra = ebo; /* to fix roll */
1263 /* ********************* meta elements ********* */
1265 static void createTransMBallVerts(TransInfo *t)
1267 MetaBall *mb = (MetaBall*)t->obedit->data;
1270 TransDataExtension *tx;
1271 float mtx[3][3], smtx[3][3];
1272 int count=0, countsel=0;
1273 int propmode = t->flag & T_PROP_EDIT;
1276 for(ml= mb->editelems->first; ml; ml= ml->next) {
1277 if(ml->flag & SELECT) countsel++;
1278 if(propmode) count++;
1281 /* note: in prop mode we need at least 1 selected */
1282 if (countsel==0) return;
1284 if(propmode) t->total = count;
1285 else t->total = countsel;
1287 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1288 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1290 copy_m3_m4(mtx, t->obedit->obmat);
1291 invert_m3_m3(smtx, mtx);
1293 for(ml= mb->editelems->first; ml; ml= ml->next) {
1294 if(propmode || (ml->flag & SELECT)) {
1296 copy_v3_v3(td->iloc, td->loc);
1297 copy_v3_v3(td->center, td->loc);
1299 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1300 else td->flag= TD_USEQUAT;
1302 copy_m3_m3(td->smtx, smtx);
1303 copy_m3_m3(td->mtx, mtx);
1307 /* Radius of MetaElem (mass of MetaElem influence) */
1308 if(ml->flag & MB_SCALE_RAD){
1317 /* expx/expy/expz determine "shape" of some MetaElem types */
1318 tx->size = &ml->expx;
1319 tx->isize[0] = ml->expx;
1320 tx->isize[1] = ml->expy;
1321 tx->isize[2] = ml->expz;
1323 /* quat is used for rotation of MetaElem */
1324 tx->quat = ml->quat;
1325 copy_qt_qt(tx->iquat, ml->quat);
1335 /* ********************* curve/surface ********* */
1337 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1338 TransData *td, *td_near = NULL;
1339 for (td = head; td<=tail; td++) {
1340 if (td->flag & TD_SELECTED) {
1346 dist = len_v3v3(td_near->center, td->center);
1347 if (dist < (td-1)->dist) {
1348 td->dist = (td-1)->dist;
1355 td->dist = MAXFLOAT;
1356 td->flag |= TD_NOTCONNECTED;
1360 for (td = tail; td>=head; td--) {
1361 if (td->flag & TD_SELECTED) {
1367 dist = len_v3v3(td_near->center, td->center);
1368 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1369 td->flag &= ~TD_NOTCONNECTED;
1370 if (dist < (td+1)->dist) {
1371 td->dist = (td+1)->dist;
1381 /* Utility function for getting the handle data from bezier's */
1382 static TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt) {
1383 TransDataCurveHandleFlags *hdata;
1384 td->flag |= TD_BEZTRIPLE;
1385 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1386 hdata->ih1 = bezt->h1;
1387 hdata->h1 = &bezt->h1;
1388 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1389 hdata->h2 = &bezt->h2;
1393 static void createTransCurveVerts(bContext *C, TransInfo *t)
1395 Object *obedit= CTX_data_edit_object(C);
1396 Curve *cu= obedit->data;
1397 TransData *td = NULL;
1401 float mtx[3][3], smtx[3][3];
1403 int count=0, countsel=0;
1404 int propmode = t->flag & T_PROP_EDIT;
1405 short hide_handles = (cu->drawflag & CU_HIDE_HANDLES);
1409 if(cu->editnurb==NULL) return;
1411 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1412 nurbs= curve_editnurbs(cu);
1413 for(nu= nurbs->first; nu; nu= nu->next) {
1414 if(nu->type == CU_BEZIER) {
1415 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1418 if(bezt->f2 & SELECT) countsel+=3;
1419 if(propmode) count+= 3;
1421 if(bezt->f1 & SELECT) countsel++;
1422 if(bezt->f2 & SELECT) countsel++;
1423 if(bezt->f3 & SELECT) countsel++;
1424 if(propmode) count+= 3;
1430 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1432 if(propmode) count++;
1433 if(bp->f1 & SELECT) countsel++;
1438 /* note: in prop mode we need at least 1 selected */
1439 if (countsel==0) return;
1441 if(propmode) t->total = count;
1442 else t->total = countsel;
1443 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1445 copy_m3_m4(mtx, t->obedit->obmat);
1446 invert_m3_m3(smtx, mtx);
1449 for(nu= nurbs->first; nu; nu= nu->next) {
1450 if(nu->type == CU_BEZIER) {
1451 TransData *head, *tail;
1453 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1455 TransDataCurveHandleFlags *hdata = NULL;
1458 ((bezt->f2 & SELECT) && hide_handles) ||
1459 ((bezt->f1 & SELECT) && hide_handles == 0)
1461 copy_v3_v3(td->iloc, bezt->vec[0]);
1462 td->loc= bezt->vec[0];
1463 copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:0]);
1465 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1468 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1474 hdata = initTransDataCurveHandles(td, bezt);
1476 copy_m3_m3(td->smtx, smtx);
1477 copy_m3_m3(td->mtx, mtx);
1484 /* This is the Curve Point, the other two are handles */
1485 if(propmode || (bezt->f2 & SELECT)) {
1486 copy_v3_v3(td->iloc, bezt->vec[1]);
1487 td->loc= bezt->vec[1];
1488 copy_v3_v3(td->center, td->loc);
1489 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1493 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1494 td->val = &(bezt->radius);
1495 td->ival = bezt->radius;
1496 } else if (t->mode==TFM_TILT) {
1497 td->val = &(bezt->alfa);
1498 td->ival = bezt->alfa;
1503 copy_m3_m3(td->smtx, smtx);
1504 copy_m3_m3(td->mtx, mtx);
1506 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1507 /* If the middle is selected but the sides arnt, this is needed */
1508 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1509 hdata = initTransDataCurveHandles(td, bezt);
1517 ((bezt->f2 & SELECT) && hide_handles) ||
1518 ((bezt->f3 & SELECT) && hide_handles == 0)
1520 copy_v3_v3(td->iloc, bezt->vec[2]);
1521 td->loc= bezt->vec[2];
1522 copy_v3_v3(td->center, bezt->vec[(hide_handles || bezt->f2 & SELECT) ? 1:2]);
1524 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1527 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1533 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1534 hdata = initTransDataCurveHandles(td, bezt);
1537 copy_m3_m3(td->smtx, smtx);
1538 copy_m3_m3(td->mtx, mtx);
1545 else if (propmode && head != tail) {
1546 calc_distanceCurveVerts(head, tail-1);
1550 if (propmode && head != tail)
1551 calc_distanceCurveVerts(head, tail-1);
1553 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles
1554 * but for now just dont change handle types */
1555 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1556 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1559 TransData *head, *tail;
1561 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1563 if(propmode || (bp->f1 & SELECT)) {
1564 copy_v3_v3(td->iloc, bp->vec);
1566 copy_v3_v3(td->center, td->loc);
1567 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1571 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1572 td->val = &(bp->radius);
1573 td->ival = bp->radius;
1575 td->val = &(bp->alfa);
1576 td->ival = bp->alfa;
1579 copy_m3_m3(td->smtx, smtx);
1580 copy_m3_m3(td->mtx, mtx);
1587 else if (propmode && head != tail) {
1588 calc_distanceCurveVerts(head, tail-1);
1592 if (propmode && head != tail)
1593 calc_distanceCurveVerts(head, tail-1);
1598 /* ********************* lattice *************** */
1600 static void createTransLatticeVerts(TransInfo *t)
1602 Lattice *latt = ((Lattice*)t->obedit->data)->editlatt->latt;
1603 TransData *td = NULL;
1605 float mtx[3][3], smtx[3][3];
1607 int count=0, countsel=0;
1608 int propmode = t->flag & T_PROP_EDIT;
1611 a = latt->pntsu * latt->pntsv * latt->pntsw;
1614 if(bp->f1 & SELECT) countsel++;
1615 if(propmode) count++;
1620 /* note: in prop mode we need at least 1 selected */
1621 if (countsel==0) return;
1623 if(propmode) t->total = count;
1624 else t->total = countsel;
1625 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1627 copy_m3_m4(mtx, t->obedit->obmat);
1628 invert_m3_m3(smtx, mtx);
1632 a = latt->pntsu * latt->pntsv * latt->pntsw;
1634 if(propmode || (bp->f1 & SELECT)) {
1636 copy_v3_v3(td->iloc, bp->vec);
1638 copy_v3_v3(td->center, td->loc);
1639 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1641 copy_m3_m3(td->smtx, smtx);
1642 copy_m3_m3(td->mtx, mtx);
1655 /* ******************* particle edit **************** */
1656 static void createTransParticleVerts(bContext *C, TransInfo *t)
1658 TransData *td = NULL;
1659 TransDataExtension *tx;
1660 Base *base = CTX_data_active_base(C);
1661 Object *ob = CTX_data_active_object(C);
1662 ParticleEditSettings *pset = PE_settings(t->scene);
1663 PTCacheEdit *edit = PE_get_current(t->scene, ob);
1664 ParticleSystem *psys = NULL;
1665 ParticleSystemModifierData *psmd = NULL;
1666 PTCacheEditPoint *point;
1667 PTCacheEditKey *key;
1669 int i,k, transformparticle;
1670 int count = 0, hasselected = 0;
1671 int propmode = t->flag & T_PROP_EDIT;
1673 if(edit==NULL || t->settings->particle.selectmode==SCE_SELECT_PATH) return;
1678 psmd = psys_get_modifier(ob,psys);
1680 base->flag |= BA_HAS_RECALC_DATA;
1682 for(i=0, point=edit->points; i<edit->totpoint; i++, point++) {
1683 point->flag &= ~PEP_TRANSFORM;
1684 transformparticle= 0;
1686 if((point->flag & PEP_HIDE)==0) {
1687 for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1688 if((key->flag&PEK_HIDE)==0) {
1689 if(key->flag&PEK_SELECT) {
1691 transformparticle= 1;
1694 transformparticle= 1;
1699 if(transformparticle) {
1700 count += point->totkey;
1701 point->flag |= PEP_TRANSFORM;
1705 /* note: in prop mode we need at least 1 selected */
1706 if (hasselected==0) return;
1709 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1711 if(t->mode == TFM_BAKE_TIME)
1712 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1718 invert_m4_m4(ob->imat,ob->obmat);
1720 for(i=0, point=edit->points; i<edit->totpoint; i++, point++) {
1721 TransData *head, *tail;
1724 if(!(point->flag & PEP_TRANSFORM)) continue;
1726 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR))
1727 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1729 for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1730 if(key->flag & PEK_USE_WCO) {
1731 copy_v3_v3(key->world_co, key->co);
1732 mul_m4_v3(mat, key->world_co);
1733 td->loc = key->world_co;
1738 copy_v3_v3(td->iloc, td->loc);
1739 copy_v3_v3(td->center, td->loc);
1741 if(key->flag & PEK_SELECT)
1742 td->flag |= TD_SELECTED;
1744 td->flag |= TD_SKIP;
1749 /* don't allow moving roots */
1750 if(k==0 && pset->flag & PE_LOCK_FIRST && (!psys || !(psys->flag & PSYS_GLOBAL_HAIR)))
1751 td->protectflag |= OB_LOCK_LOC;
1755 if(t->mode == TFM_BAKE_TIME) {
1756 td->val = key->time;
1757 td->ival = *(key->time);
1758 /* abuse size and quat for min/max values */
1759 td->flag |= TD_NO_EXT;
1760 if(k==0) tx->size = NULL;
1761 else tx->size = (key - 1)->time;
1763 if(k == point->totkey - 1) tx->quat = NULL;
1764 else tx->quat = (key + 1)->time;
1772 if (propmode && head != tail)
1773 calc_distanceCurveVerts(head, tail - 1);
1777 void flushTransParticles(TransInfo *t)
1779 Scene *scene = t->scene;
1781 PTCacheEdit *edit = PE_get_current(scene, ob);
1782 ParticleSystem *psys = edit->psys;
1783 ParticleSystemModifierData *psmd = NULL;
1784 PTCacheEditPoint *point;
1785 PTCacheEditKey *key;
1787 float mat[4][4], imat[4][4], co[3];
1788 int i, k, propmode = t->flag & T_PROP_EDIT;
1791 psmd = psys_get_modifier(ob, psys);
1793 /* we do transform in world space, so flush world space position
1794 * back to particle local space (only for hair particles) */
1796 for(i=0, point=edit->points; i<edit->totpoint; i++, point++, td++) {
1797 if(!(point->flag & PEP_TRANSFORM)) continue;
1799 if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
1800 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + i, mat);
1801 invert_m4_m4(imat,mat);
1803 for(k=0, key=point->keys; k<point->totkey; k++, key++) {
1804 copy_v3_v3(co, key->world_co);
1805 mul_m4_v3(imat, co);
1808 /* optimization for proportional edit */
1809 if(!propmode || !compare_v3v3(key->co, co, 0.0001f)) {
1810 copy_v3_v3(key->co, co);
1811 point->flag |= PEP_EDIT_RECALC;
1816 point->flag |= PEP_EDIT_RECALC;
1819 PE_update_object(scene, OBACT, 1);
1822 /* ********************* mesh ****************** */
1824 /* proportional distance based on connectivity */
1825 #define THRESHOLDFACTOR (1.0f-0.0001f)
1827 /*I did this wrong, it should be a breadth-first search
1828 but instead it's a depth-first search, fudged
1829 to report shortest distances. I have no idea how fast
1831 static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[][3], float *dists)
1833 BMVert **queue = NULL;
1834 float *dqueue = NULL;
1835 int *tots = MEM_callocN(sizeof(int)*em->bm->totvert, "tots editmesh_set_connectivity_distance");
1836 BLI_array_declare(queue);
1837 BLI_array_declare(dqueue);
1838 SmallHash svisit, *visit=&svisit;
1844 BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
1850 BLI_smallhash_init(visit);
1852 BM_ITER(v, &viter, em->bm, BM_VERTS_OF_MESH, NULL) {
1853 if (BM_TestHFlag(v, BM_SELECT)==0 || BM_TestHFlag(v, BM_HIDDEN))
1857 BLI_smallhash_insert(visit, (uintptr_t)v, NULL);
1858 BLI_array_append(queue, v);
1859 BLI_array_append(dqueue, 0.0f);
1860 dists[BM_GetIndex(v)] = 0.0f;
1864 while (start < BLI_array_count(queue)) {
1873 BM_ITER(e, &eiter, em->bm, BM_EDGES_OF_VERT, v2) {
1875 v3 = BM_OtherEdgeVert(e, v2);
1877 if (BM_TestHFlag(v3, BM_SELECT) || BM_TestHFlag(v3, BM_HIDDEN))
1880 sub_v3_v3v3(vec, v2->co, v3->co);
1881 mul_m3_v3(mtx, vec);
1883 d2 = d + len_v3(vec);
1885 if (dists[BM_GetIndex(v3)] != FLT_MAX)
1886 dists[BM_GetIndex(v3)] = MIN2(d2, dists[BM_GetIndex(v3)]);
1888 dists[BM_GetIndex(v3)] = d2;
1890 tots[BM_GetIndex(v3)] = 1;
1892 if (BLI_smallhash_haskey(visit, (uintptr_t)v3))
1895 BLI_smallhash_insert(visit, (uintptr_t)v3, NULL);
1897 BLI_array_append(queue, v3);
1898 BLI_array_append(dqueue, d2);
1904 BLI_smallhash_release(visit);
1906 for (i=0; i<em->bm->totvert; i++) {
1908 dists[i] /= (float)tots[i];
1911 BLI_array_free(queue);
1912 BLI_array_free(dqueue);
1916 /* loop-in-a-loop I know, but we need it! (ton) */
1917 static void get_face_center(float *centout, BMesh *bm, BMVert *eve)
1923 float cent[3] = {0.0, 0.0, 0.0};
1925 efa = BMIter_New(&iter, bm, BM_FACES_OF_VERT, eve);
1927 l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, efa);
1928 for ( ; l; l=BMIter_Step(&iter)) {
1929 VECADD(cent, cent, l->v->co);
1932 mul_v3_fl(cent, 1.0f / (float)efa->len);
1935 if (cent[0] == 0.0f && cent[1] == 0.0f && cent[2] == 0.0f) cent[2] = 1.0f;
1936 copy_v3_v3(centout, cent);
1939 #define VertsToTransData(t, td, em, eve, bweight) \
1942 copy_v3_v3(td->center, td->loc);\
1943 if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))\
1944 get_face_center(td->center, em, eve);\
1945 copy_v3_v3(td->iloc, td->loc);\
1946 copy_v3_v3(td->axismtx[2], eve->no);\
1947 td->axismtx[0][0] =\
1948 td->axismtx[0][1] =\
1949 td->axismtx[0][2] =\
1950 td->axismtx[1][0] =\
1951 td->axismtx[1][1] =\
1952 td->axismtx[1][2] = 0.0f;\
1956 if (t->mode == TFM_BWEIGHT) {\
1958 td->ival = bweight ? *(bweight) : 1.0f;\
1962 //way to overwrite what data is edited with transform
1963 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1964 inline void VertsToTransData(TransInfo *t, TransData *td, BMesh *em, BMVert *eve)
1968 // td->loc = key->co;
1972 copy_v3_v3(td->center, td->loc);
1973 if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1974 get_face_center(td->center, em, eve);
1975 copy_v3_v3(td->iloc, td->loc);
1978 copy_v3_v3(td->axismtx[2], eve->no);
1984 td->axismtx[1][2] = 0.0f;
1989 if (t->mode == TFM_BWEIGHT) {
1990 td->val = &(eve->bweight);
1991 td->ival = eve->bweight;
1996 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1998 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
2000 float *vec = userData;
2006 static int modifiers_disable_subsurf_temporary(Object *ob)
2011 for(md=ob->modifiers.first; md; md=md->next)
2012 if(md->type==eModifierType_Subsurf)
2013 if(md->mode & eModifierMode_OnCage) {
2014 md->mode ^= eModifierMode_DisableTemporary;
2021 /* disable subsurf temporal, get mapped cos, and enable it */
2022 static float *get_crazy_mapped_editverts(TransInfo *t)
2024 Mesh *me= t->obedit->data;
2028 /* disable subsurf temporal, get mapped cos, and enable it */
2029 if(modifiers_disable_subsurf_temporary(t->obedit)) {
2030 /* need to make new derivemesh */
2031 makeDerivedMesh(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH, 0);
2034 /* now get the cage */
2035 dm= editbmesh_get_derived_cage(t->scene, t->obedit, me->edit_btmesh, CD_MASK_BAREMESH);
2037 vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_btmesh->bm->totvert, "vertexcos map");
2038 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
2042 /* set back the flag, no new cage needs to be built, transform does it */
2043 modifiers_disable_subsurf_temporary(t->obedit);
2048 #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])
2049 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
2051 float vecu[3], vecv[3];
2054 TAN_MAKE_VEC(vecu, v1, v2);
2055 TAN_MAKE_VEC(vecv, v1, v3);
2056 tri_to_quat( q1,v1, vecu, vecv);
2058 TAN_MAKE_VEC(vecu, def1, def2);
2059 TAN_MAKE_VEC(vecv, def1, def3);
2060 tri_to_quat( q2,def1, vecu, vecv);
2062 sub_qt_qtqt(quat, q2, q1);
2066 static void createTransEditVerts(bContext *C, TransInfo *t)
2068 ToolSettings *ts = CTX_data_tool_settings(C);
2069 TransData *tob = NULL;
2070 BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
2074 BMVert *eve_act = NULL;
2075 float *mappedcos = NULL, *quats= NULL;
2076 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2078 int count=0, countsel=0, a, totleft, *selstate = NULL;
2079 BLI_array_declare(selstate);
2080 int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) : 0;
2082 short selectmode = ts->selectmode;
2084 if (t->flag & T_MIRROR)
2086 EDBM_CacheMirrorVerts(em, TRUE);
2090 /* edge slide forces edge select */
2091 if (t->mode == TFM_EDGE_SLIDE) {
2092 selectmode = SCE_SELECT_EDGE;
2095 /* BMESH_TODO, writing into the index values is BAD!, means we cant
2096 * use the values for vertex mirror - campbell */
2098 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2099 if(selectmode & SCE_SELECT_VERTEX) {
2100 BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
2101 if (BM_Selected(bm, eve)) {
2102 BM_SetHFlag(eve, BM_TMP_TAG);
2105 BM_ClearHFlag(eve, BM_TMP_TAG);
2109 else if(selectmode & SCE_SELECT_EDGE) {
2112 eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
2113 for( ; eve; eve=BMIter_Step(&iter)) BM_ClearHFlag(eve, BM_TMP_TAG);
2115 eed = BMIter_New(&iter, bm, BM_EDGES_OF_MESH, NULL);
2116 for( ; eed; eed=BMIter_Step(&iter)) {
2117 if (BM_Selected(bm, eed)) {
2118 BM_SetHFlag(eed->v1, BM_TMP_TAG);
2119 BM_SetHFlag(eed->v2, BM_TMP_TAG);
2125 eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
2126 for( ; eve; eve=BMIter_Step(&iter)) BM_ClearHFlag(eve, BM_TMP_TAG);
2128 efa = BMIter_New(&iter, bm, BM_FACES_OF_MESH, NULL);
2129 for( ; efa; efa=BMIter_Step(&iter)) {
2130 if (BM_Selected(bm, efa)) {
2134 l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, efa);
2135 for (; l; l=BMIter_Step(&liter)) {
2136 BM_SetHFlag(l->v, BM_TMP_TAG);
2142 /* now we can count. we store selection state in selstate, since
2143 get_crazy_mapped_editverts messes up the index state of the
2145 eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
2146 for(a=0; eve; eve=BMIter_Step(&iter), a++) {
2147 BLI_array_growone(selstate);
2149 if (BM_TestHFlag(eve, BM_TMP_TAG)) {
2153 if(propmode) count++;
2156 /* note: in prop mode we need at least 1 selected */
2157 if (countsel == 0) {
2162 if (em->bm->selected.last) {
2163 BMEditSelection *ese = em->bm->selected.last;
2164 if (ese->htype == BM_VERT) {
2165 eve_act = (BMVert *)ese->data;
2173 /* allocating scratch arrays */
2174 if (propmode & T_PROP_CONNECTED)
2175 dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
2177 else t->total = countsel;
2179 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2181 copy_m3_m4(mtx, t->obedit->obmat);
2182 invert_m3_m3(smtx, mtx);
2184 if(propmode & T_PROP_CONNECTED)
2185 editmesh_set_connectivity_distance(em, mtx, dists);
2187 /* detect CrazySpace [tm] */
2188 if(modifiers_getCageIndex(t->scene, t->obedit, NULL, 1)>=0) {
2189 if(modifiers_isCorrectableDeformed(t->obedit)) {
2190 /* check if we can use deform matrices for modifier from the
2191 start up to stack, they are more accurate than quats */
2192 totleft= editbmesh_get_first_deform_matrices(t->scene, t->obedit, em, &defmats, &defcos);
2194 /* if we still have more modifiers, also do crazyspace
2195 correction with quats, relative to the coordinates after
2196 the modifiers that support deform matrices (defcos) */
2198 mappedcos= crazyspace_get_mapped_editverts(t->scene, t->obedit);
2199 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2200 crazyspace_set_quats_editmesh(em, (float*)defcos, mappedcos, quats); /* BMESH_TODO, abuses vertex index, should use an int array */
2202 MEM_freeN(mappedcos);
2210 /* find out which half we do */
2212 eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
2213 for(a=0; eve; eve=BMIter_Step(&iter), a++) {
2214 if(!BM_TestHFlag(eve, BM_HIDDEN) && selstate[a] && eve->co[0]!=0.0f) {
2225 eve = BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
2226 for(a=0; eve; eve=BMIter_Step(&iter), a++) {
2227 if(!BM_TestHFlag(eve, BM_HIDDEN)) {
2228 if(propmode || selstate[a]) {
2229 float *bweight = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_BWEIGHT);
2231 VertsToTransData(t, tob, bm, eve, bweight);
2234 if(selstate[a]) tob->flag |= TD_SELECTED;
2237 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2240 if (propmode & T_PROP_CONNECTED) {
2241 tob->dist = dists[a];
2243 tob->flag |= TD_NOTCONNECTED;
2244 tob->dist = MAXFLOAT;
2249 if(defmats || (quats && BM_GetIndex(eve) != -1)) {
2250 float mat[3][3], qmat[3][3], imat[3][3];
2252 /* use both or either quat and defmat correction */
2253 if(quats && BM_GetIndex(eve) != -1) {
2254 quat_to_mat3(qmat, quats + 4*BM_GetIndex(eve));
2257 mul_serie_m3(mat, mtx, qmat, defmats[a],
2258 NULL, NULL, NULL, NULL, NULL);
2260 mul_m3_m3m3(mat, mtx, qmat);
2263 mul_m3_m3m3(mat, mtx, defmats[a]);
2265 invert_m3_m3(imat, mat);
2267 copy_m3_m3(tob->smtx, imat);
2268 copy_m3_m3(tob->mtx, mat);
2271 copy_m3_m3(tob->smtx, smtx);
2272 copy_m3_m3(tob->mtx, mtx);
2276 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2277 BMVert *vmir= EDBM_GetMirrorVert(em, eve); //t->obedit, em, eve, tob->iloc, a);
2278 if(vmir && vmir != eve) {
2290 for( a = 0; a < t->total; a++, tob++ )
2292 if (ABS(tob->loc[0]) <= 0.00001f)
2294 tob->flag |= TD_MIRROR_EDGE;
2300 /* crazy space free */
2308 BLI_array_free(selstate);
2310 if (t->flag & T_MIRROR)
2312 EDBM_EndMirrorCache(em);
2317 /* *** NODE EDITOR *** */
2318 void flushTransNodes(TransInfo *t)
2323 /* flush to 2d vector from internally used 3d vector */
2324 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2325 td->loc2d[0]= td->loc[0];
2326 td->loc2d[1]= td->loc[1];
2329 /* handle intersection with noodles */
2331 ED_node_link_intersect_test(t->sa, 1);
2336 /* *** SEQUENCE EDITOR *** */
2338 /* commented _only_ because the meta may have animaion data which
2339 * needs moving too [#28158] */
2341 #define SEQ_TX_NESTED_METAS
2343 void flushTransSeq(TransInfo *t)
2345 ListBase *seqbasep= seq_give_editing(t->scene, FALSE)->seqbasep; /* Editing null check already done */
2346 int a, new_frame, old_start;
2347 TransData *td= NULL;
2348 TransData2D *td2d= NULL;
2349 TransDataSeq *tdsq= NULL;
2354 /* prevent updating the same seq twice
2355 * if the transdata order is changed this will mess up
2356 * but so will TransDataSeq */
2357 Sequence *seq_prev= NULL;
2359 /* flush to 2d vector from internally used 3d vector */
2360 for(a=0, td= t->data, td2d= t->data2d; a<t->total; a++, td++, td2d++) {
2361 tdsq= (TransDataSeq *)td->extra;
2363 old_start = seq->start;
2364 new_frame= (int)floor(td2d->loc[0] + 0.5f);
2366 switch (tdsq->sel_flag) {
2368 #ifdef SEQ_TX_NESTED_METAS
2369 if ((seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */
2370 seq->start= new_frame - tdsq->start_offset;
2372 if (seq->type != SEQ_META && (seq->depth != 0 || seq_tx_test(seq))) /* for meta's, their children move */
2373 seq->start= new_frame - tdsq->start_offset;
2375 if (seq->depth==0) {
2376 seq->machine= (int)floor(td2d->loc[1] + 0.5f);
2377 CLAMP(seq->machine, 1, MAXSEQ);
2380 case SEQ_LEFTSEL: /* no vertical transform */
2381 seq_tx_set_final_left(seq, new_frame);
2382 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2383 seq_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2385 case SEQ_RIGHTSEL: /* no vertical transform */
2386 seq_tx_set_final_right(seq, new_frame);
2387 seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2388 seq_single_fix(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2392 if (seq != seq_prev) {
2394 /* Calculate this strip and all nested strips
2395 * children are ALWAYS transformed first
2396 * so we dont need to do this in another loop. */
2397 calc_sequence(t->scene, seq);
2400 calc_sequence_disp(t->scene, seq);
2403 if(tdsq->sel_flag == SELECT)
2404 seq_offset_animdata(t->scene, seq, seq->start - old_start);
2409 /* need to do the overlap check in a new loop otherwise adjacent strips
2410 * will not be updated and we'll get false positives */
2412 for(a=0, td= t->data, td2d= t->data2d; a<t->total; a++, td++, td2d++) {
2414 tdsq= (TransDataSeq *)td->extra;
2417 if (seq != seq_prev) {
2419 /* test overlap, displayes red outline */
2420 seq->flag &= ~SEQ_OVERLAP;
2421 if( seq_test_overlap(seqbasep, seq) ) {
2422 seq->flag |= SEQ_OVERLAP;
2429 if (t->mode == TFM_SEQ_SLIDE) { /* originally TFM_TIME_EXTEND, transform changes */
2430 /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
2431 seq= seqbasep->first;
2434 if (seq->type == SEQ_META && seq->flag & SELECT)
2435 calc_sequence(t->scene, seq);
2441 /* ********************* UV ****************** */
2443 static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, float *uv, int selected)
2447 ED_space_image_uv_aspect(sima, &aspx, &aspy);
2449 /* uv coords are scaled by aspects. this is needed for rotations and
2450 proportional editing to be consistent with the stretchted uv coords
2451 that are displayed. this also means that for display and numinput,
2452 and when the the uv coords are flushed, these are converted each time */
2453 td2d->loc[0] = uv[0]*aspx;
2454 td2d->loc[1] = uv[1]*aspy;
2455 td2d->loc[2] = 0.0f;
2459 td->loc = td2d->loc;
2460 copy_v3_v3(td->center, td->loc);
2461 copy_v3_v3(td->iloc, td->loc);
2463 memset(td->axismtx, 0, sizeof(td->axismtx));
2464 td->axismtx[2][2] = 1.0f;
2466 td->ext= NULL; td->val= NULL;
2469 td->flag |= TD_SELECTED;
2479 static void createTransUVs(bContext *C, TransInfo *t)
2481 SpaceImage *sima = CTX_wm_space_image(C);
2482 Image *ima = CTX_data_edit_image(C);
2483 Scene *scene = t->scene;
2484 TransData *td = NULL;
2485 TransData2D *td2d = NULL;
2488 BMEditMesh *em = ((Mesh *)t->obedit->data)->edit_btmesh;
2492 int count=0, countsel=0;
2493 int propmode = t->flag & T_PROP_EDIT;
2495 if(!ED_space_image_show_uvedit(sima, t->obedit)) return;
2498 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2499 tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
2501 if(!uvedit_face_visible(scene, ima, efa, tf)) {
2502 BM_ClearHFlag(efa, BM_TMP_TAG);
2506 BM_SetHFlag(efa, BM_TMP_TAG);
2507 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
2508 if (uvedit_uv_selected(em, scene, l))
2516 /* note: in prop mode we need at least 1 selected */
2517 if (countsel==0) return;
2519 t->total= (propmode)? count: countsel;
2520 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2521 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2522 treated just as if they were 3d verts */
2523 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2525 if(sima->flag & SI_CLIP_UV)
2526 t->flag |= T_CLIP_UV;
2531 BM_ITER(efa, &iter, em->bm, BM_FACES_OF_MESH, NULL) {
2532 if (!BM_TestHFlag(efa, BM_TMP_TAG))
2535 tf= CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
2536 BM_ITER(l, &liter, em->bm, BM_LOOPS_OF_FACE, efa) {
2537 if (!propmode && !uvedit_uv_selected(em, scene, l))
2540 luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
2541 UVsToTransData(sima, td++, td2d++, luv->uv, uvedit_uv_selected(em, scene, l));
2545 if (sima->flag & SI_LIVE_UNWRAP)
2546 ED_uvedit_live_unwrap_begin(t->scene, t->obedit);
2549 void flushTransUVs(TransInfo *t)
2551 SpaceImage *sima = t->sa->spacedata.first;
2553 int a, width, height;
2554 float aspx, aspy, invx, invy;
2556 ED_space_image_uv_aspect(sima, &aspx, &aspy);
2557 ED_space_image_size(sima, &width, &height);
2561 /* flush to 2d vector from internally used 3d vector */
2562 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2563 if (!td->loc2d) continue;
2565 td->loc2d[0]= td->loc[0]*invx;
2566 td->loc2d[1]= td->loc[1]*invy;
2568 if((sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2569 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2570 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2575 int clipUVTransform(TransInfo *t, float *vec, int resize)
2578 int a, clipx=1, clipy=1;
2579 float aspx, aspy, min[2], max[2];
2581 ED_space_image_uv_aspect(t->sa->spacedata.first, &aspx, &aspy);
2582 min[0]= min[1]= 0.0f;
2583 max[0]= aspx; max[1]= aspy;
2585 for(a=0, td= t->data; a<t->total; a++, td++) {
2586 DO_MINMAX2(td->loc, min, max);
2590 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2591 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2592 else if(max[0] > aspx && t->center[0] < aspx)
2593 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2597 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2598 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2599 else if(max[1] > aspy && t->center[1] < aspy)
2600 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2607 else if(max[0] > aspx)
2608 vec[0] -= max[0]-aspx;
2614 else if(max[1] > aspy)
2615 vec[1] -= max[1]-aspy;
2620 return (clipx || clipy);
2623 /* ********************* ANIMATION EDITORS (GENERAL) ************************* */
2625 /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */
2626 static short FrameOnMouseSide(char side, float frame, float cframe)
2628 /* both sides, so it doesn't matter */
2629 if (side == 'B') return 1;
2631 /* only on the named side */
2633 return (frame >= cframe) ? 1 : 0;
2635 return (frame <= cframe) ? 1 : 0;
2638 /* ********************* NLA EDITOR ************************* */
2640 static void createTransNlaData(bContext *C, TransInfo *t)
2642 Scene *scene= t->scene;
2643 SpaceNla *snla = NULL;
2644 TransData *td = NULL;
2645 TransDataNla *tdn = NULL;
2648 ListBase anim_data = {NULL, NULL};
2654 /* determine what type of data we are operating on */
2655 if (ANIM_animdata_get_context(C, &ac) == 0)
2657 snla = (SpaceNla *)ac.sl;
2660 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
2661 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2663 /* which side of the current frame should be allowed */
2664 if (t->mode == TFM_TIME_EXTEND) {
2665 /* only side on which mouse is gets transformed */
2666 float xmouse, ymouse;
2668 UI_view2d_region_to_view(&ac.ar->v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
2669 t->frame_side= (xmouse > CFRA) ? 'R' : 'L';
2672 /* normal transform - both sides of current frame are considered */
2673 t->frame_side = 'B';
2676 /* loop 1: count how many strips are selected (consider each strip as 2 points) */
2677 for (ale= anim_data.first; ale; ale= ale->next) {
2678 NlaTrack *nlt= (NlaTrack *)ale->data;
2681 /* make some meta-strips for chains of selected strips */
2682 BKE_nlastrips_make_metas(&nlt->strips, 1);
2684 /* only consider selected strips */
2685 for (strip= nlt->strips.first; strip; strip= strip->next) {
2686 // TODO: we can make strips have handles later on...
2687 /* transition strips can't get directly transformed */
2688 if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2689 if (strip->flag & NLASTRIP_FLAG_SELECT) {
2690 if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA)) count++;
2691 if (FrameOnMouseSide(t->frame_side, strip->end, (float)CFRA)) count++;
2697 /* stop if trying to build list if nothing selected */
2699 /* cleanup temp list */
2700 BLI_freelistN(&anim_data);
2704 /* allocate memory for data */
2707 t->data= MEM_callocN(t->total*sizeof(TransData), "TransData(NLA Editor)");
2709 t->customData= MEM_callocN(t->total*sizeof(TransDataNla), "TransDataNla (NLA Editor)");
2712 /* loop 2: build transdata array */
2713 for (ale= anim_data.first; ale; ale= ale->next) {
2714 /* only if a real NLA-track */
2715 if (ale->type == ANIMTYPE_NLATRACK) {
2716 AnimData *adt = ale->adt;
2717 NlaTrack *nlt= (NlaTrack *)ale->data;
2720 /* only consider selected strips */
2721 for (strip= nlt->strips.first; strip; strip= strip->next) {
2722 // TODO: we can make strips have handles later on...
2723 /* transition strips can't get directly transformed */
2724 if (strip->type != NLASTRIP_TYPE_TRANSITION) {
2725 if (strip->flag & NLASTRIP_FLAG_SELECT) {
2726 /* our transform data is constructed as follows:
2727 * - only the handles on the right side of the current-frame get included
2728 * - td structs are transform-elements operated on by the transform system
2729 * and represent a single handle. The storage/pointer used (val or loc) depends on
2730 * whether we're scaling or transforming. Ultimately though, the handles
2731 * the td writes to will simply be a dummy in tdn
2732 * - for each strip being transformed, a single tdn struct is used, so in some
2733 * cases, there will need to be 1 of these tdn elements in the array skipped...
2735 float center[3], yval;
2737 /* firstly, init tdn settings */
2739 tdn->oldTrack= tdn->nlt= nlt;
2741 tdn->trackIndex= BLI_findindex(&adt->nla_tracks, nlt);
2743 yval= (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
2745 tdn->h1[0]= strip->start;
2747 tdn->h2[0]= strip->end;
2750 center[0]= (float)CFRA;
2754 /* set td's based on which handles are applicable */
2755 if (FrameOnMouseSide(t->frame_side, strip->start, (float)CFRA))
2757 /* just set tdn to assume that it only has one handle for now */
2760 /* now, link the transform data up to this data */
2761 if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
2763 copy_v3_v3(td->iloc, tdn->h1);
2765 /* store all the other gunk that is required by transform */
2766 copy_v3_v3(td->center, center);