4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
42 #include "MEM_guardedalloc.h"
44 #include "DNA_action_types.h"
45 #include "DNA_armature_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_effect_types.h"
49 #include "DNA_image_types.h"
50 #include "DNA_ipo_types.h"
51 #include "DNA_key_types.h"
52 #include "DNA_lamp_types.h"
53 #include "DNA_lattice_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_meshdata_types.h"
56 #include "DNA_meta_types.h"
57 #include "DNA_modifier_types.h"
58 #include "DNA_nla_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_object_force.h"
61 #include "DNA_particle_types.h"
62 #include "DNA_scene_types.h"
63 #include "DNA_screen_types.h"
64 #include "DNA_space_types.h"
65 #include "DNA_texture_types.h"
66 #include "DNA_view3d_types.h"
67 #include "DNA_world_types.h"
68 #include "DNA_userdef_types.h"
69 #include "DNA_property_types.h"
70 #include "DNA_vfont_types.h"
71 #include "DNA_constraint_types.h"
72 #include "DNA_listBase.h"
73 #include "DNA_gpencil_types.h"
75 #include "BKE_action.h"
76 #include "BKE_armature.h"
77 #include "BKE_blender.h"
78 #include "BKE_cloth.h"
79 #include "BKE_curve.h"
80 #include "BKE_constraint.h"
81 #include "BKE_depsgraph.h"
82 #include "BKE_displist.h"
83 #include "BKE_DerivedMesh.h"
84 #include "BKE_effect.h"
86 #include "BKE_global.h"
88 #include "BKE_lattice.h"
91 #include "BKE_mball.h"
93 #include "BKE_modifier.h"
94 #include "BKE_object.h"
95 #include "BKE_particle.h"
96 #include "BKE_pointcache.h"
97 #include "BKE_softbody.h"
98 #include "BKE_utildefines.h"
99 #include "BKE_bmesh.h"
100 #include "BKE_context.h"
102 //#include "BIF_editaction.h"
103 //#include "BIF_editview.h"
104 //#include "BIF_editlattice.h"
105 //#include "BIF_editconstraint.h"
106 #include "BIF_editarmature.h"
107 //#include "BIF_editmesh.h"
108 //#include "BIF_editnla.h"
109 //#include "BIF_editsima.h"
110 //#include "BIF_editparticle.h"
112 //#include "BIF_keyframing.h"
113 //#include "BIF_poseobject.h"
114 //#include "BIF_meshtools.h"
115 //#include "BIF_mywindow.h"
116 //#include "BIF_resources.h"
117 #include "BIF_retopo.h"
118 //#include "BIF_screen.h"
119 //#include "BIF_space.h"
120 //#include "BIF_toolbox.h"
122 #include "ED_types.h"
123 #include "ED_anim_api.h"
124 #include "ED_keyframing.h"
125 #include "ED_keyframes_edit.h"
126 #include "ED_view3d.h"
128 #include "UI_view2d.h"
130 //#include "BSE_drawipo.h"
131 //#include "BSE_edit.h"
132 //#include "BSE_editipo.h"
133 //#include "BSE_editipo_types.h"
134 //#include "BSE_editaction_types.h"
136 //#include "BDR_drawaction.h" // list of keyframes in action
137 //#include "BDR_editobject.h" // reset_slowparents()
138 //#include "BDR_gpencil.h"
139 //#include "BDR_unwrapper.h"
141 #include "BLI_arithb.h"
142 #include "BLI_blenlib.h"
143 #include "BLI_editVert.h"
145 //#include "editmesh.h"
147 //#include "blendef.h"
149 //#include "mydevice.h"
151 extern ListBase editNurb;
152 extern ListBase editelems;
154 #include "transform.h"
156 #include "BLO_sys_types.h" // for intptr_t support
158 /************ STUBS TO GET COMPILE ************/
159 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
163 /* local function prototype - for Object/Bone Constraints */
164 static short constraints_list_needinv(TransInfo *t, ListBase *list);
165 /* local function prototype - for finding number of keyframes that are selected for editing */
166 static int count_ipo_keys(Ipo *ipo, char side, float cfra);
168 /* ************************** Functions *************************** */
170 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
171 TransData pivot = *head;
172 TransData *ihead = head;
173 TransData *itail = tail;
174 short connected = t->flag & T_PROP_CONNECTED;
179 while ((tail->dist >= pivot.dist) && (head < tail))
183 while ((tail->rdist >= pivot.rdist) && (head < tail))
194 while ((head->dist <= pivot.dist) && (head < tail))
198 while ((head->rdist <= pivot.rdist) && (head < tail))
211 qsort_trans_data(t, ihead, head-1);
214 qsort_trans_data(t, head+1, itail);
218 void sort_trans_data_dist(TransInfo *t) {
219 TransData *start = t->data;
222 while(i < t->total && start->flag & TD_SELECTED) {
226 qsort_trans_data(t, start, t->data + t->total - 1);
229 static void sort_trans_data(TransInfo *t)
231 TransData *sel, *unsel;
236 while (sel > unsel) {
237 while (unsel->flag & TD_SELECTED) {
243 while (!(sel->flag & TD_SELECTED)) {
257 /* distance calculated from not-selected vertex to nearest selected vertex
258 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
259 static void set_prop_dist(TransInfo *t, short with_dist)
264 for(a=0, tob= t->data; a<t->total; a++, tob++) {
266 tob->rdist= 0.0f; // init, it was mallocced
268 if((tob->flag & TD_SELECTED)==0) {
273 tob->rdist = -1.0f; // signal for next loop
275 for (i = 0, td= t->data; i < t->total; i++, td++) {
276 if(td->flag & TD_SELECTED) {
277 VecSubf(vec, tob->center, td->center);
278 Mat3MulVecfl(tob->mtx, vec);
279 dist = Normalize(vec);
280 if (tob->rdist == -1.0f) {
283 else if (dist < tob->rdist) {
287 else break; // by definition transdata has selected items in beginning
290 tob->dist = tob->rdist;
296 /* ************************** CONVERSIONS ************************* */
298 /* ********************* texture space ********* */
300 static void createTransTexspace(bContext *C, TransInfo *t)
302 Scene *scene = CTX_data_scene(C);
310 if (ob == NULL) { // Shouldn't logically happen, but still...
316 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
322 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
323 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
325 td->flag= TD_SELECTED;
326 VECCOPY(td->center, ob->obmat[3]);
329 Mat3CpyMat4(td->mtx, ob->obmat);
330 Mat3CpyMat4(td->axismtx, ob->obmat);
331 Mat3Ortho(td->axismtx);
332 Mat3Inv(td->smtx, td->mtx);
334 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
335 *texflag &= ~AUTOSPACE;
338 VECCOPY(td->iloc, td->loc);
339 VECCOPY(td->ext->irot, td->ext->rot);
340 VECCOPY(td->ext->isize, td->ext->size);
343 /* ********************* edge (for crease) ***** */
345 static void createTransEdge(bContext *C, TransInfo *t) {
346 #if 0 // TRANSFORM_FIX_ME
347 TransData *td = NULL;
348 EditMesh *em = G.editMesh;
350 float mtx[3][3], smtx[3][3];
351 int count=0, countsel=0;
352 int propmode = t->flag & T_PROP_EDIT;
354 for(eed= em->edges.first; eed; eed= eed->next) {
356 if (eed->f & SELECT) countsel++;
357 if (propmode) count++;
371 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
373 Mat3CpyMat4(mtx, G.obedit->obmat);
376 for(eed= em->edges.first; eed; eed= eed->next) {
377 if(eed->h==0 && (eed->f & SELECT || propmode)) {
378 /* need to set center for center calculations */
379 VecAddf(td->center, eed->v1->co, eed->v2->co);
380 VecMulf(td->center, 0.5f);
384 td->flag= TD_SELECTED;
389 Mat3CpyMat3(td->smtx, smtx);
390 Mat3CpyMat3(td->mtx, mtx);
394 if (t->mode == TFM_BWEIGHT) {
395 td->val = &(eed->bweight);
396 td->ival = eed->bweight;
399 td->val = &(eed->crease);
400 td->ival = eed->crease;
409 /* ********************* pose mode ************* */
411 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
413 bConstraint *con= pchan->constraints.first;
415 for(;con; con= con->next) {
416 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
417 bKinematicConstraint *data= con->data;
421 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
428 static short apply_targetless_ik(Object *ob)
430 bPoseChannel *pchan, *parchan, *chanlist[256];
431 bKinematicConstraint *data;
432 int segcount, apply= 0;
434 /* now we got a difficult situation... we have to find the
435 target-less IK pchans, and apply transformation to the all
436 pchans that were in the chain */
438 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
439 data= has_targetless_ik(pchan);
440 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
442 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
445 /* exclude tip from chain? */
446 if(!(data->flag & CONSTRAINT_IK_TIP))
447 parchan= pchan->parent;
451 /* Find the chain's root & count the segments needed */
452 for (; parchan; parchan=parchan->parent){
453 chanlist[segcount]= parchan;
456 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
458 for(;segcount;segcount--) {
460 float rmat[4][4], tmat[4][4], imat[4][4];
462 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
463 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
464 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
465 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
467 parchan= chanlist[segcount-1];
469 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
471 if(parchan->parent) {
472 Bone *parbone= parchan->parent->bone;
473 float offs_bone[4][4];
475 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
476 Mat4CpyMat3(offs_bone, bone->bone_mat);
478 /* The bone's root offset (is in the parent's coordinate system) */
479 VECCOPY(offs_bone[3], bone->head);
481 /* Get the length translation of parent (length along y axis) */
482 offs_bone[3][1]+= parbone->length;
484 /* pose_mat(b-1) * offs_bone */
485 if(parchan->bone->flag & BONE_HINGE) {
486 /* the rotation of the parent restposition */
487 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
489 /* the location of actual parent transform */
490 VECCOPY(rmat[3], offs_bone[3]);
491 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
492 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
494 Mat4MulMat4(tmat, offs_bone, rmat);
496 else if(parchan->bone->flag & BONE_NO_SCALE) {
497 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
501 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
503 Mat4Invert(imat, tmat);
506 Mat4CpyMat3(tmat, bone->bone_mat);
508 VECCOPY(tmat[3], bone->head);
509 Mat4Invert(imat, tmat);
512 Mat4MulMat4(rmat, parchan->pose_mat, imat);
514 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
516 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
518 Mat3CpyMat4(rmat3, rmat);
521 Mat3ToQuat(rmat3, parchan->quat);
523 /* for size, remove rotation */
524 /* causes problems with some constraints (so apply only if needed) */
525 if (data->flag & CONSTRAINT_IK_STRETCH) {
526 QuatToMat3(parchan->quat, qmat);
528 Mat3MulMat3(smat, rmat3, imat);
529 Mat3ToSize(smat, parchan->size);
532 /* causes problems with some constraints (e.g. childof), so disable this */
533 /* as it is IK shouldn't affect location directly */
534 /* VECCOPY(parchan->loc, rmat[3]); */
540 data->flag &= ~CONSTRAINT_IK_AUTO;
547 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
549 Bone *bone= pchan->bone;
550 float pmat[3][3], omat[3][3];
551 float cmat[3][3], tmat[3][3];
554 VECCOPY(vec, pchan->pose_mat[3]);
555 VECCOPY(td->center, vec);
558 td->flag= TD_SELECTED|TD_USEQUAT;
559 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
561 td->flag |= TD_NOCENTER;
564 if (bone->flag & BONE_TRANSFORM_CHILD)
566 td->flag |= TD_NOCENTER;
567 td->flag |= TD_NO_LOC;
570 td->protectflag= pchan->protectflag;
572 td->loc = pchan->loc;
573 VECCOPY(td->iloc, pchan->loc);
576 td->ext->quat= pchan->quat;
577 td->ext->size= pchan->size;
579 QUATCOPY(td->ext->iquat, pchan->quat);
580 VECCOPY(td->ext->isize, pchan->size);
582 /* proper way to get parent transform + own transform + constraints transform */
583 Mat3CpyMat4(omat, ob->obmat);
586 if(pchan->bone->flag & BONE_HINGE)
587 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
589 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
591 if (constraints_list_needinv(t, &pchan->constraints)) {
592 Mat3CpyMat4(tmat, pchan->constinv);
594 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
597 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
600 if (constraints_list_needinv(t, &pchan->constraints)) {
601 Mat3CpyMat4(tmat, pchan->constinv);
603 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
606 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
609 Mat3Inv(td->smtx, td->mtx);
611 /* for axismat we use bone's own transform */
612 Mat3CpyMat4(pmat, pchan->pose_mat);
613 Mat3MulMat3(td->axismtx, omat, pmat);
614 Mat3Ortho(td->axismtx);
616 if(t->mode==TFM_BONESIZE) {
617 bArmature *arm= t->poseobj->data;
619 if(arm->drawtype==ARM_ENVELOPE) {
621 td->val= &bone->dist;
622 td->ival= bone->dist;
625 // abusive storage of scale in the loc pointer :)
626 td->loc= &bone->xwidth;
627 VECCOPY (td->iloc, td->loc);
632 /* in this case we can do target-less IK grabbing */
633 if(t->mode==TFM_TRANSLATION) {
634 bKinematicConstraint *data= has_targetless_ik(pchan);
636 if(data->flag & CONSTRAINT_IK_TIP) {
637 VECCOPY(data->grabtarget, pchan->pose_tail);
640 VECCOPY(data->grabtarget, pchan->pose_head);
642 td->loc = data->grabtarget;
643 VECCOPY(td->iloc, td->loc);
644 data->flag |= CONSTRAINT_IK_AUTO;
646 /* only object matrix correction */
647 Mat3CpyMat3 (td->mtx, omat);
648 Mat3Inv (td->smtx, td->mtx);
652 /* store reference to first constraint */
653 td->con= pchan->constraints.first;
656 static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
658 Bone *bone= lb->first;
660 for(;bone;bone= bone->next) {
661 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
663 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
665 else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
667 bone->flag |= BONE_TRANSFORM_CHILD;
671 bone->flag &= ~BONE_TRANSFORM;
674 bone_children_clear_transflag(t, &bone->childbase);
678 /* sets transform flags in the bones, returns total */
679 static void set_pose_transflags(TransInfo *t, Object *ob)
681 bArmature *arm= ob->data;
688 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
690 if(bone->layer & arm->layer) {
691 if(bone->flag & BONE_SELECTED)
692 bone->flag |= BONE_TRANSFORM;
694 bone->flag &= ~BONE_TRANSFORM;
696 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
697 bone->flag &= ~BONE_TRANSFORM_CHILD;
701 /* make sure no bone can be transformed when a parent is transformed */
702 /* since pchans are depsgraph sorted, the parents are in beginning of list */
703 if(t->mode!=TFM_BONESIZE) {
704 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
706 if(bone->flag & BONE_TRANSFORM)
707 bone_children_clear_transflag(t, &bone->childbase);
710 /* now count, and check if we have autoIK or have to switch from translate to rotate */
713 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
715 if(bone->flag & BONE_TRANSFORM) {
719 if(t->mode==TFM_TRANSLATION) {
720 if( has_targetless_ik(pchan)==NULL ) {
721 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
722 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
725 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
734 /* if there are no translatable bones, do rotation */
735 if(t->mode==TFM_TRANSLATION && !hastranslation)
736 t->mode= TFM_ROTATION;
740 /* -------- Auto-IK ---------- */
742 /* adjust pose-channel's auto-ik chainlen */
743 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
747 /* don't bother to search if no valid constraints */
748 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
751 /* check if pchan has ik-constraint */
752 for (con= pchan->constraints.first; con; con= con->next) {
753 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
754 bKinematicConstraint *data= con->data;
756 /* only accept if a temporary one (for auto-ik) */
757 if (data->flag & CONSTRAINT_IK_TEMP) {
758 /* chainlen is new chainlen, but is limited by maximum chainlen */
759 if ((chainlen==0) || (chainlen > data->max_rootbone))
760 data->rootbone= data->max_rootbone;
762 data->rootbone= chainlen;
768 /* change the chain-length of auto-ik */
769 void transform_autoik_update (TransInfo *t, short mode)
771 short *chainlen= &G.scene->toolsettings->autoik_chainlen;
774 /* mode determines what change to apply to chainlen */
776 /* mode=1 is from WHEELMOUSEDOWN... increases len */
779 else if (mode == -1) {
780 /* mode==-1 is from WHEELMOUSEUP... decreases len */
781 if (*chainlen > 0) (*chainlen)--;
784 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
785 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
788 /* apply to all pose-channels */
789 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
790 pchan_autoik_adjust(pchan, *chainlen);
794 /* frees temporal IKs */
795 static void pose_grab_with_ik_clear(Object *ob)
797 bKinematicConstraint *data;
799 bConstraint *con, *next;
801 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
802 /* clear all temporary lock flags */
803 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
805 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
806 /* remove all temporary IK-constraints added */
807 for (con= pchan->constraints.first; con; con= next) {
809 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
811 if (data->flag & CONSTRAINT_IK_TEMP) {
812 BLI_remlink(&pchan->constraints, con);
813 MEM_freeN(con->data);
817 pchan->constflag |= PCHAN_HAS_IK;
818 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
819 pchan->constflag |= PCHAN_HAS_TARGET;
825 /* adds the IK to pchan - returns if added */
826 static short pose_grab_with_ik_add(bPoseChannel *pchan)
828 bKinematicConstraint *data;
830 bConstraint *targetless = 0;
836 /* Rule: not if there's already an IK on this channel */
837 for (con= pchan->constraints.first; con; con= con->next) {
838 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
839 bKinematicConstraint *data= con->data;
840 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
842 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
843 if (con->enforce!=0.0) {
844 targetless->flag |= CONSTRAINT_IK_AUTO;
848 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0))
854 //con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
855 BLI_addtail(&pchan->constraints, con);
856 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
858 if (targetless) { /* if exists use values from last targetless IK-constraint as base */
859 *data = *((bKinematicConstraint*)targetless->data);
862 data->flag= CONSTRAINT_IK_TIP;
863 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
864 VECCOPY(data->grabtarget, pchan->pose_tail);
867 /* we include only a connected chain */
868 while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
869 /* here, we set ik-settings for bone from pchan->protectflag */
870 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
871 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
872 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
874 /* now we count this pchan as being included */
876 pchan= pchan->parent;
879 /* make a copy of maximum chain-length */
880 data->max_rootbone= data->rootbone;
885 /* bone is a candidate to get IK, but we don't do it if it has children connected */
886 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
889 short wentdeeper=0, added=0;
891 /* go deeper if children & children are connected */
892 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
893 if (bonec->flag & BONE_CONNECTED) {
895 added+= pose_grab_with_ik_children(pose, bonec);
899 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
901 added+= pose_grab_with_ik_add(pchan);
907 /* main call which adds temporal IK chains */
908 static short pose_grab_with_ik(Object *ob)
911 bPoseChannel *pchan, *parent;
915 if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
920 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
921 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
922 if (pchan->bone->layer & arm->layer) {
923 if (pchan->bone->flag & BONE_SELECTED) {
924 /* Rule: no IK for solitatry (unconnected) bones */
925 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
926 if (bonec->flag & BONE_CONNECTED) {
930 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
933 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
935 /* only adds if there's no IK yet (and no parent bone was selected) */
936 for (parent= pchan->parent; parent; parent= parent->parent) {
937 if (parent->bone->flag & BONE_SELECTED)
941 tot_ik += pose_grab_with_ik_add(pchan);
944 /* rule: go over the children and add IK to the tips */
945 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
951 return (tot_ik) ? 1 : 0;
955 /* only called with pose mode active object now */
956 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
963 TransDataExtension *tdx;
969 /* check validity of state */
970 arm=get_armature (ob);
971 if (arm==NULL || ob->pose==NULL) return;
973 if (arm->flag & ARM_RESTPOS) {
974 if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
975 notice("Pose edit not possible while Rest Position is enabled");
979 if (!(ob->lay & G.vd->lay)) return;
981 /* do we need to add temporal IK chains? */
982 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
983 ik_on= pose_grab_with_ik(ob);
984 if (ik_on) t->flag |= T_AUTOIK;
987 /* set flags and count total (warning, can change transform to rotate) */
988 set_pose_transflags(t, ob);
990 if(t->total==0) return;
993 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
995 /* make sure the lock is set OK, unlock can be accidentally saved? */
996 ob->pose->flag |= POSE_LOCKED;
997 ob->pose->flag &= ~POSE_DO_UNLOCK;
999 /* init trans data */
1000 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
1001 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
1002 for(i=0; i<t->total; i++, td++, tdx++) {
1008 /* use pose channels to fill trans data */
1010 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1011 if(pchan->bone->flag & BONE_TRANSFORM) {
1012 add_pose_transdata(t, pchan, ob, td);
1017 if(td != (t->data+t->total)) printf("Bone selection count error\n");
1019 /* initialise initial auto=ik chainlen's? */
1020 if (ik_on) transform_autoik_update(t, 0);
1024 /* ********************* armature ************** */
1026 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1031 bArmature *arm= G.obedit->data;
1033 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1036 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
1037 if(ebo->layer & arm->layer) {
1038 if (t->mode==TFM_BONESIZE) {
1039 if (ebo->flag & BONE_SELECTED)
1042 else if (t->mode==TFM_BONE_ROLL) {
1043 if (ebo->flag & BONE_SELECTED)
1047 if (ebo->flag & BONE_TIPSEL)
1049 if (ebo->flag & BONE_ROOTSEL)
1055 if (!t->total) return;
1057 Mat3CpyMat4(mtx, G.obedit->obmat);
1060 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1062 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1063 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1065 if(ebo->layer & arm->layer) {
1066 if (t->mode==TFM_BONE_ENVELOPE) {
1068 if (ebo->flag & BONE_ROOTSEL){
1069 td->val= &ebo->rad_head;
1072 VECCOPY (td->center, ebo->head);
1073 td->flag= TD_SELECTED;
1075 Mat3CpyMat3(td->smtx, smtx);
1076 Mat3CpyMat3(td->mtx, mtx);
1084 if (ebo->flag & BONE_TIPSEL){
1085 td->val= &ebo->rad_tail;
1087 VECCOPY (td->center, ebo->tail);
1088 td->flag= TD_SELECTED;
1090 Mat3CpyMat3(td->smtx, smtx);
1091 Mat3CpyMat3(td->mtx, mtx);
1101 else if (t->mode==TFM_BONESIZE) {
1102 if (ebo->flag & BONE_SELECTED) {
1103 if(arm->drawtype==ARM_ENVELOPE) {
1105 td->val= &ebo->dist;
1106 td->ival= ebo->dist;
1109 // abusive storage of scale in the loc pointer :)
1110 td->loc= &ebo->xwidth;
1111 VECCOPY (td->iloc, td->loc);
1114 VECCOPY (td->center, ebo->head);
1115 td->flag= TD_SELECTED;
1117 /* use local bone matrix */
1118 VecSubf(delta, ebo->tail, ebo->head);
1119 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1120 Mat3MulMat3(td->mtx, mtx, bonemat);
1121 Mat3Inv(td->smtx, td->mtx);
1123 Mat3CpyMat3(td->axismtx, td->mtx);
1124 Mat3Ortho(td->axismtx);
1132 else if (t->mode==TFM_BONE_ROLL) {
1133 if (ebo->flag & BONE_SELECTED) {
1135 td->val= &(ebo->roll);
1136 td->ival= ebo->roll;
1138 VECCOPY (td->center, ebo->head);
1139 td->flag= TD_SELECTED;
1148 if (ebo->flag & BONE_TIPSEL){
1149 VECCOPY (td->iloc, ebo->tail);
1150 VECCOPY (td->center, td->iloc);
1152 td->flag= TD_SELECTED;
1153 if (ebo->flag & BONE_EDITMODE_LOCKED)
1154 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1156 Mat3CpyMat3(td->smtx, smtx);
1157 Mat3CpyMat3(td->mtx, mtx);
1159 VecSubf(delta, ebo->tail, ebo->head);
1160 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1162 if ((ebo->flag & BONE_ROOTSEL) == 0)
1173 if (ebo->flag & BONE_ROOTSEL){
1174 VECCOPY (td->iloc, ebo->head);
1175 VECCOPY (td->center, td->iloc);
1177 td->flag= TD_SELECTED;
1178 if (ebo->flag & BONE_EDITMODE_LOCKED)
1179 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1181 Mat3CpyMat3(td->smtx, smtx);
1182 Mat3CpyMat3(td->mtx, mtx);
1184 VecSubf(delta, ebo->tail, ebo->head);
1185 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1187 td->extra = ebo; /* to fix roll */
1201 /* ********************* meta elements ********* */
1203 static void createTransMBallVerts(bContext *C, TransInfo *t)
1209 TransDataExtension *tx;
1210 float mtx[3][3], smtx[3][3];
1211 int count=0, countsel=0;
1212 int propmode = t->flag & T_PROP_EDIT;
1215 for(ml= editelems.first; ml; ml= ml->next) {
1216 if(ml->flag & SELECT) countsel++;
1217 if(propmode) count++;
1220 /* note: in prop mode we need at least 1 selected */
1221 if (countsel==0) return;
1223 if(propmode) t->total = count;
1224 else t->total = countsel;
1226 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1227 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1229 Mat3CpyMat4(mtx, G.obedit->obmat);
1232 for(ml= editelems.first; ml; ml= ml->next) {
1233 if(propmode || (ml->flag & SELECT)) {
1235 VECCOPY(td->iloc, td->loc);
1236 VECCOPY(td->center, td->loc);
1238 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1239 else td->flag= TD_USEQUAT;
1241 Mat3CpyMat3(td->smtx, smtx);
1242 Mat3CpyMat3(td->mtx, mtx);
1247 /* Radius of MetaElem (mass of MetaElem influence) */
1248 if(ml->flag & MB_SCALE_RAD){
1257 /* expx/expy/expz determine "shape" of some MetaElem types */
1258 tx->size = &ml->expx;
1259 tx->isize[0] = ml->expx;
1260 tx->isize[1] = ml->expy;
1261 tx->isize[2] = ml->expz;
1263 /* quat is used for rotation of MetaElem */
1264 tx->quat = ml->quat;
1265 QUATCOPY(tx->iquat, ml->quat);
1276 /* ********************* curve/surface ********* */
1278 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1279 TransData *td, *td_near = NULL;
1280 for (td = head; td<=tail; td++) {
1281 if (td->flag & TD_SELECTED) {
1287 dist = VecLenf(td_near->center, td->center);
1288 if (dist < (td-1)->dist) {
1289 td->dist = (td-1)->dist;
1296 td->dist = MAXFLOAT;
1297 td->flag |= TD_NOTCONNECTED;
1301 for (td = tail; td>=head; td--) {
1302 if (td->flag & TD_SELECTED) {
1308 dist = VecLenf(td_near->center, td->center);
1309 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1310 td->flag &= ~TD_NOTCONNECTED;
1311 if (dist < (td+1)->dist) {
1312 td->dist = (td+1)->dist;
1322 /* Utility function for getting the handle data from bezier's */
1323 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1324 TransDataCurveHandleFlags *hdata;
1325 td->flag |= TD_BEZTRIPLE;
1326 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1327 hdata->ih1 = bezt->h1;
1328 hdata->h1 = &bezt->h1;
1329 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1330 hdata->h2 = &bezt->h2;
1334 static void createTransCurveVerts(bContext *C, TransInfo *t)
1338 TransData *td = NULL;
1342 float mtx[3][3], smtx[3][3];
1344 int count=0, countsel=0;
1345 int propmode = t->flag & T_PROP_EDIT;
1347 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1348 for(nu= editNurb.first; nu; nu= nu->next) {
1349 if((nu->type & 7)==CU_BEZIER) {
1350 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1352 if (G.f & G_HIDDENHANDLES) {
1353 if(bezt->f2 & SELECT) countsel+=3;
1354 if(propmode) count+= 3;
1356 if(bezt->f1 & SELECT) countsel++;
1357 if(bezt->f2 & SELECT) countsel++;
1358 if(bezt->f3 & SELECT) countsel++;
1359 if(propmode) count+= 3;
1365 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1367 if(propmode) count++;
1368 if(bp->f1 & SELECT) countsel++;
1373 /* note: in prop mode we need at least 1 selected */
1374 if (countsel==0) return;
1376 if(propmode) t->total = count;
1377 else t->total = countsel;
1378 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1380 Mat3CpyMat4(mtx, G.obedit->obmat);
1384 for(nu= editNurb.first; nu; nu= nu->next) {
1385 if((nu->type & 7)==CU_BEZIER) {
1386 TransData *head, *tail;
1388 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1390 TransDataCurveHandleFlags *hdata = NULL;
1393 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1394 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1396 VECCOPY(td->iloc, bezt->vec[0]);
1397 td->loc= bezt->vec[0];
1398 VECCOPY(td->center, bezt->vec[1]);
1399 if (G.f & G_HIDDENHANDLES) {
1400 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1403 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1410 hdata = initTransDataCurveHandes(td, bezt);
1412 Mat3CpyMat3(td->smtx, smtx);
1413 Mat3CpyMat3(td->mtx, mtx);
1420 /* This is the Curve Point, the other two are handles */
1421 if(propmode || (bezt->f2 & SELECT)) {
1422 VECCOPY(td->iloc, bezt->vec[1]);
1423 td->loc= bezt->vec[1];
1424 VECCOPY(td->center, td->loc);
1425 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1430 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1431 td->val = &(bezt->radius);
1432 td->ival = bezt->radius;
1433 } else if (t->mode==TFM_TILT) {
1434 td->val = &(bezt->alfa);
1435 td->ival = bezt->alfa;
1440 Mat3CpyMat3(td->smtx, smtx);
1441 Mat3CpyMat3(td->mtx, mtx);
1443 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1444 /* If the middle is selected but the sides arnt, this is needed */
1445 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1446 hdata = initTransDataCurveHandes(td, bezt);
1454 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1455 ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1457 VECCOPY(td->iloc, bezt->vec[2]);
1458 td->loc= bezt->vec[2];
1459 VECCOPY(td->center, bezt->vec[1]);
1460 if (G.f & G_HIDDENHANDLES) {
1461 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1464 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1471 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1472 hdata = initTransDataCurveHandes(td, bezt);
1475 Mat3CpyMat3(td->smtx, smtx);
1476 Mat3CpyMat3(td->mtx, mtx);
1483 else if (propmode && head != tail) {
1484 calc_distanceCurveVerts(head, tail-1);
1488 if (propmode && head != tail)
1489 calc_distanceCurveVerts(head, tail-1);
1491 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1492 * but for now just dont change handle types */
1493 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1494 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1497 TransData *head, *tail;
1499 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1501 if(propmode || (bp->f1 & SELECT)) {
1502 VECCOPY(td->iloc, bp->vec);
1504 VECCOPY(td->center, td->loc);
1505 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1510 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1511 td->val = &(bp->radius);
1512 td->ival = bp->radius;
1514 td->val = &(bp->alfa);
1515 td->ival = bp->alfa;
1518 Mat3CpyMat3(td->smtx, smtx);
1519 Mat3CpyMat3(td->mtx, mtx);
1526 else if (propmode && head != tail) {
1527 calc_distanceCurveVerts(head, tail-1);
1531 if (propmode && head != tail)
1532 calc_distanceCurveVerts(head, tail-1);
1538 /* ********************* lattice *************** */
1540 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1544 TransData *td = NULL;
1546 float mtx[3][3], smtx[3][3];
1548 int count=0, countsel=0;
1549 int propmode = t->flag & T_PROP_EDIT;
1552 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1555 if(bp->f1 & SELECT) countsel++;
1556 if(propmode) count++;
1561 /* note: in prop mode we need at least 1 selected */
1562 if (countsel==0) return;
1564 if(propmode) t->total = count;
1565 else t->total = countsel;
1566 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1568 Mat3CpyMat4(mtx, G.obedit->obmat);
1573 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1575 if(propmode || (bp->f1 & SELECT)) {
1577 VECCOPY(td->iloc, bp->vec);
1579 VECCOPY(td->center, td->loc);
1580 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1582 Mat3CpyMat3(td->smtx, smtx);
1583 Mat3CpyMat3(td->mtx, mtx);
1598 /* ******************* particle edit **************** */
1599 static void createTransParticleVerts(bContext *C, TransInfo *t)
1603 TransData *td = NULL;
1604 TransDataExtension *tx;
1605 Base *base = BASACT;
1607 ParticleSystem *psys = PE_get_current(ob);
1608 ParticleSystemModifierData *psmd = NULL;
1609 ParticleEditSettings *pset = PE_settings();
1610 ParticleData *pa = NULL;
1612 ParticleEditKey *key;
1614 int i,k, totpart, transformparticle;
1615 int count = 0, hasselected = 0;
1616 int propmode = t->flag & T_PROP_EDIT;
1618 if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1620 psmd = psys_get_modifier(ob,psys);
1623 totpart = psys->totpart;
1624 base->flag |= BA_HAS_RECALC_DATA;
1626 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1627 pa->flag &= ~PARS_TRANSFORM;
1628 transformparticle= 0;
1630 if((pa->flag & PARS_HIDE)==0) {
1631 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1632 if((key->flag&PEK_HIDE)==0) {
1633 if(key->flag&PEK_SELECT) {
1635 transformparticle= 1;
1638 transformparticle= 1;
1643 if(transformparticle) {
1644 count += pa->totkey;
1645 pa->flag |= PARS_TRANSFORM;
1649 /* note: in prop mode we need at least 1 selected */
1650 if (hasselected==0) return;
1653 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1655 if(t->mode == TFM_BAKE_TIME)
1656 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1662 Mat4Invert(ob->imat,ob->obmat);
1664 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1665 TransData *head, *tail;
1668 if(!(pa->flag & PARS_TRANSFORM)) continue;
1670 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1672 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1673 VECCOPY(key->world_co, key->co);
1674 Mat4MulVecfl(mat, key->world_co);
1675 td->loc = key->world_co;
1677 VECCOPY(td->iloc, td->loc);
1678 VECCOPY(td->center, td->loc);
1680 if(key->flag & PEK_SELECT)
1681 td->flag |= TD_SELECTED;
1683 td->flag |= TD_SKIP;
1688 /* don't allow moving roots */
1689 if(k==0 && pset->flag & PE_LOCK_FIRST)
1690 td->protectflag |= OB_LOCK_LOC;
1695 if(t->mode == TFM_BAKE_TIME) {
1696 td->val = key->time;
1697 td->ival = *(key->time);
1698 /* abuse size and quat for min/max values */
1699 td->flag |= TD_NO_EXT;
1700 if(k==0) tx->size = 0;
1701 else tx->size = (key - 1)->time;
1703 if(k == pa->totkey - 1) tx->quat = 0;
1704 else tx->quat = (key + 1)->time;
1712 if (propmode && head != tail)
1713 calc_distanceCurveVerts(head, tail - 1);
1718 void flushTransParticles(TransInfo *t)
1720 #if 0 // TRANSFORM_FIX_ME
1721 Scene *scene = t->scene;
1723 ParticleSystem *psys = PE_get_current(ob);
1724 ParticleSystemModifierData *psmd;
1726 ParticleEditKey *key;
1728 float mat[4][4], imat[4][4], co[3];
1729 int i, k, propmode = t->flag & T_PROP_EDIT;
1731 psmd = psys_get_modifier(ob, psys);
1733 /* we do transform in world space, so flush world space position
1734 * back to particle local space */
1736 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1737 if(!(pa->flag & PARS_TRANSFORM)) continue;
1739 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1740 Mat4Invert(imat,mat);
1742 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1743 VECCOPY(co, key->world_co);
1744 Mat4MulVecfl(imat, co);
1746 /* optimization for proportional edit */
1747 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1748 VECCOPY(key->co, co);
1749 pa->flag |= PARS_EDIT_RECALC;
1754 PE_update_object(OBACT, 1);
1758 /* ********************* mesh ****************** */
1760 /* proportional distance based on connectivity */
1761 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1762 #define E_NEAR(a) (nears[((a)->tmp.l)])
1763 #define THRESHOLD 0.0001f
1764 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1766 EditMesh *em = G.editMesh;
1771 /* f2 flag is used for 'selection' */
1772 /* tmp.l is offset on scratch array */
1773 for(eve= em->verts.first; eve; eve= eve->next) {
1777 if(eve->f & SELECT) {
1780 E_VEC(eve)[0] = 0.0f;
1781 E_VEC(eve)[1] = 0.0f;
1782 E_VEC(eve)[2] = 0.0f;
1791 /* Floodfill routine */
1793 At worst this is n*n of complexity where n is number of edges
1794 Best case would be n if the list is ordered perfectly.
1795 Estimate is n log n in average (so not too bad)
1800 for(eed= em->edges.first; eed; eed= eed->next) {
1802 EditVert *v1= eed->v1, *v2= eed->v2;
1803 float *vec2 = E_VEC(v2);
1804 float *vec1 = E_VEC(v1);
1806 if (v1->f2 + v2->f2 == 4)
1812 float len1 = VecLength(vec1);
1813 float len2 = VecLength(vec2);
1815 /* for v2 if not selected */
1817 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1818 lenn = VecLength(nvec);
1820 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1821 VECCOPY(vec2, nvec);
1822 E_NEAR(v2) = E_NEAR(v1);
1826 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1827 VECCOPY(vec2, vec1);
1828 E_NEAR(v2) = E_NEAR(v1);
1832 /* for v1 if not selected */
1834 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1835 lenn = VecLength(nvec);
1837 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1838 VECCOPY(vec1, nvec);
1839 E_NEAR(v1) = E_NEAR(v2);
1843 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1844 VECCOPY(vec1, vec2);
1845 E_NEAR(v1) = E_NEAR(v2);
1852 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1854 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1855 VECCOPY(vec2, vec1);
1857 E_NEAR(v2) = E_NEAR(v1);
1863 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1865 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1866 VECCOPY(vec1, vec2);
1868 E_NEAR(v1) = E_NEAR(v2);
1876 /* loop-in-a-loop I know, but we need it! (ton) */
1877 static void get_face_center(float *cent, EditVert *eve)
1879 EditMesh *em = G.editMesh;
1882 for(efa= em->faces.first; efa; efa= efa->next)
1884 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1887 VECCOPY(cent, efa->cent);
1891 //way to overwrite what data is edited with transform
1892 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1893 static void VertsToTransData(TransData *td, EditVert *eve)
1897 // td->loc = key->co;
1901 VECCOPY(td->center, td->loc);
1903 // if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1904 // get_face_center(td->center, eve);
1905 VECCOPY(td->iloc, td->loc);
1908 VECCOPY(td->axismtx[2], eve->no);
1914 td->axismtx[1][2] = 0.0f;
1920 if (BIF_GetTransInfo()->mode == TFM_BWEIGHT) {
1921 td->val = &(eve->bweight);
1922 td->ival = eve->bweight;
1927 td->verse = (void*)eve->vvert;
1928 td->flag |= TD_VERSE_VERT;
1931 td->flag &= ~TD_VERSE_VERT;
1935 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1937 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1939 float *vec = userData;
1945 static int modifiers_disable_subsurf_temporary(Object *ob)
1950 for(md=ob->modifiers.first; md; md=md->next)
1951 if(md->type==eModifierType_Subsurf)
1952 if(md->mode & eModifierMode_OnCage) {
1953 md->mode ^= eModifierMode_DisableTemporary;
1960 /* disable subsurf temporal, get mapped cos, and enable it */
1961 static float *get_crazy_mapped_editverts(void)
1966 /* disable subsurf temporal, get mapped cos, and enable it */
1967 if(modifiers_disable_subsurf_temporary(G.obedit)) {
1968 /* need to make new derivemesh */
1969 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1972 /* now get the cage */
1973 dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1975 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1976 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1980 /* set back the flag, no new cage needs to be built, transform does it */
1981 modifiers_disable_subsurf_temporary(G.obedit);
1986 #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])
1987 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1989 float vecu[3], vecv[3];
1992 TAN_MAKE_VEC(vecu, v1, v2);
1993 TAN_MAKE_VEC(vecv, v1, v3);
1994 triatoquat(v1, vecu, vecv, q1);
1996 TAN_MAKE_VEC(vecu, def1, def2);
1997 TAN_MAKE_VEC(vecv, def1, def3);
1998 triatoquat(def1, vecu, vecv, q2);
2000 QuatSub(quat, q2, q1);
2004 static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
2006 EditMesh *em = G.editMesh;
2007 EditVert *eve, *prev;
2009 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2012 /* two abused locations in vertices */
2013 for(eve= em->verts.first; eve; eve= eve->next, index++) {
2015 eve->prev= (EditVert *)index;
2018 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2019 for(efa= em->faces.first; efa; efa= efa->next) {
2021 /* retrieve mapped coordinates */
2022 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2023 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2024 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2026 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2027 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2028 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2030 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2031 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2032 efa->v2->tmp.p= (void*)quats;
2037 v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2038 co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2040 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2041 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2042 efa->v1->tmp.p= (void*)quats;
2045 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2046 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2047 efa->v3->tmp.p= (void*)quats;
2050 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2051 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2052 efa->v4->tmp.p= (void*)quats;
2057 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2058 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2059 efa->v1->tmp.p= (void*)quats;
2062 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2063 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2064 efa->v3->tmp.p= (void*)quats;
2070 /* restore abused prev pointer */
2071 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2076 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2082 tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2084 for (i=0,v=bm->verts.first;v;v=v->next) {
2085 if ( (vtd = BME_get_transdata(td,v)) ) {
2086 tob->loc = vtd->loc;
2087 tob->val = &vtd->factor;
2088 VECCOPY(tob->iloc,vtd->co);
2089 VECCOPY(tob->center,vtd->org);
2090 VECCOPY(tob->axismtx[0],vtd->vec);
2091 tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2096 /* since td is a memarena, it can hold more transdata than actual elements
2097 * (i.e. we can't depend on td->len to determine the number of actual elements) */
2101 static void createTransEditVerts(bContext *C, TransInfo *t)
2105 TransData *tob = NULL;
2106 EditMesh *em = G.editMesh;
2108 EditVert **nears = NULL;
2109 EditVert *eve_act = NULL;
2110 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2111 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2112 int count=0, countsel=0, a, totleft;
2113 int propmode = t->flag & T_PROP_EDIT;
2116 if ((t->options & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2121 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2122 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2123 for(eve= em->verts.first; eve; eve= eve->next) {
2124 if(eve->h==0 && (eve->f & SELECT))
2130 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2132 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2133 for(eed= em->edges.first; eed; eed= eed->next) {
2134 if(eed->h==0 && (eed->f & SELECT))
2135 eed->v1->f1= eed->v2->f1= SELECT;
2140 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2141 for(efa= em->faces.first; efa; efa= efa->next) {
2142 if(efa->h==0 && (efa->f & SELECT)) {
2143 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2144 if(efa->v4) efa->v4->f1= SELECT;
2149 /* now we can count */
2150 for(eve= em->verts.first; eve; eve= eve->next) {
2152 if(eve->f1) countsel++;
2153 if(propmode) count++;
2157 /* note: in prop mode we need at least 1 selected */
2158 if (countsel==0) return;
2161 if (G.editMesh->selected.last) {
2162 EditSelection *ese = G.editMesh->selected.last;
2163 if ( ese->type == EDITVERT ) {
2164 eve_act = (EditVert *)ese->data;
2172 /* allocating scratch arrays */
2173 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2174 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2176 else t->total = countsel;
2177 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2179 Mat3CpyMat4(mtx, G.obedit->obmat);
2182 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
2184 /* detect CrazySpace [tm] */
2186 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
2187 if(modifiers_isDeformed(G.obedit)) {
2188 /* check if we can use deform matrices for modifier from the
2189 start up to stack, they are more accurate than quats */
2190 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
2192 /* if we still have more modifiers, also do crazyspace
2193 correction with quats, relative to the coordinates after
2194 the modifiers that support deform matrices (defcos) */
2196 mappedcos= get_crazy_mapped_editverts();
2197 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2198 set_crazyspace_quats((float*)defcos, mappedcos, quats);
2200 MEM_freeN(mappedcos);
2209 /* find out which half we do */
2211 for (eve=em->verts.first; eve; eve=eve->next) {
2212 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2220 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2222 if(propmode || eve->f1) {
2223 VertsToTransData(tob, eve);
2226 if(eve->f1) tob->flag |= TD_SELECTED;
2229 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2234 VECCOPY(vec, E_VEC(eve));
2235 Mat3MulVecfl(mtx, vec);
2236 tob->dist= VecLength(vec);
2239 tob->flag |= TD_NOTCONNECTED;
2240 tob->dist = MAXFLOAT;
2245 if(defmats || (quats && eve->tmp.p)) {
2246 float mat[3][3], imat[3][3], qmat[3][3];
2248 /* use both or either quat and defmat correction */
2249 if(quats && eve->tmp.f) {
2250 QuatToMat3(eve->tmp.p, qmat);
2253 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2254 NULL, NULL, NULL, NULL, NULL);
2256 Mat3MulMat3(mat, mtx, qmat);
2259 Mat3MulMat3(mat, mtx, defmats[a]);
2263 Mat3CpyMat3(tob->smtx, imat);
2264 Mat3CpyMat3(tob->mtx, mat);
2267 Mat3CpyMat3(tob->smtx, smtx);
2268 Mat3CpyMat3(tob->mtx, mtx);
2272 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2273 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
2274 if(vmir != eve) tob->extra = vmir;
2284 /* crazy space free */
2292 /* ********************* UV ****************** */
2294 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2298 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2300 /* uv coords are scaled by aspects. this is needed for rotations and
2301 proportional editing to be consistent with the stretchted uv coords
2302 that are displayed. this also means that for display and numinput,
2303 and when the the uv coords are flushed, these are converted each time */
2304 td2d->loc[0] = uv[0]*aspx;
2305 td2d->loc[1] = uv[1]*aspy;
2306 td2d->loc[2] = 0.0f;
2310 td->loc = td2d->loc;
2311 VECCOPY(td->center, td->loc);
2312 VECCOPY(td->iloc, td->loc);
2314 memset(td->axismtx, 0, sizeof(td->axismtx));
2315 td->axismtx[2][2] = 1.0f;
2317 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2320 td->flag |= TD_SELECTED;
2330 static void createTransUVs(bContext *C, TransInfo *t)
2334 TransData *td = NULL;
2335 TransData2D *td2d = NULL;
2337 int count=0, countsel=0;
2338 int propmode = t->flag & T_PROP_EDIT;
2339 int efa_s1,efa_s2,efa_s3,efa_s4;
2341 EditMesh *em = G.editMesh;
2344 if(is_uv_tface_editing_allowed()==0) return;
2347 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2348 for (efa= em->faces.first; efa; efa= efa->next) {
2349 /* store face pointer for second loop, prevent second lookup */
2350 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2351 if (simaFaceDraw_Check(efa, tf)) {
2354 efa_s1 = simaUVSel_Check(efa, tf, 0);
2355 efa_s2 = simaUVSel_Check(efa, tf, 1);
2356 efa_s3 = simaUVSel_Check(efa, tf, 2);
2358 efa_s4 = simaUVSel_Check(efa, tf, 3);
2359 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2360 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2363 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2364 if (efa_s1) countsel++;
2365 if (efa_s2) countsel++;
2366 if (efa_s3) countsel++;
2373 for (efa= em->faces.first; efa; efa= efa->next) {
2374 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2375 if (simaFaceDraw_Check(efa, tf)) {
2378 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2379 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2380 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2381 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2383 count += (efa->v4)? 4: 3;
2390 /* note: in prop mode we need at least 1 selected */
2391 if (countsel==0) return;
2393 t->total= (propmode)? count: countsel;
2394 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2395 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2396 treated just as if they were 3d verts */
2397 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2399 if(G.sima->flag & SI_CLIP_UV)
2400 t->flag |= T_CLIP_UV;
2405 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2406 for (efa= em->faces.first; efa; efa= efa->next) {
2407 tf=(MTFace *)efa->tmp.p;
2409 efa_s1 = simaUVSel_Check(efa, tf, 0);
2410 efa_s2 = simaUVSel_Check(efa, tf, 1);
2411 efa_s3 = simaUVSel_Check(efa, tf, 2);
2414 efa_s4 = simaUVSel_Check(efa, tf, 3);
2416 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2417 /* all corners of this quad need their edges moved. so we must store TD for each */
2419 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2420 if (!efa_s1) td->flag |= TD_SKIP;
2423 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2424 if (!efa_s2) td->flag |= TD_SKIP;
2427 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2428 if (!efa_s3) td->flag |= TD_SKIP;
2431 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2432 if (!efa_s4) td->flag |= TD_SKIP;
2436 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2437 if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2438 if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2439 if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2444 for (efa= em->faces.first; efa; efa= efa->next) {
2445 /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2446 if (simaFaceDraw_Check(efa, tf)) {*/
2447 if ((tf=(MTFace *)efa->tmp.p)) {
2449 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2450 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2451 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2453 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2455 if(simaUVSel_Check(efa, tf, 0)) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2456 if(simaUVSel_Check(efa, tf, 1)) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2457 if(simaUVSel_Check(efa, tf, 2)) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2458 if(efa->v4 && simaUVSel_Check(efa, tf, 3)) UVsToTransData(td++, td2d++, tf->uv[3], 1);
2464 if (G.sima->flag & SI_LIVE_UNWRAP)
2465 unwrap_lscm_live_begin();
2469 void flushTransUVs(TransInfo *t)
2471 #if 0 // TRANSFORM_FIX_ME
2473 int a, width, height;
2475 EditMesh *em = G.editMesh;
2476 float aspx, aspy, invx, invy;
2478 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2479 transform_width_height_tface_uv(&width, &height);
2483 /* flush to 2d vector from internally used 3d vector */
2484 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2485 td->loc2d[0]= td->loc[0]*invx;
2486 td->loc2d[1]= td->loc[1]*invy;
2488 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2489 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2490 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2494 if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL))
2495 be_square_tface_uv(em);
2497 /* this is overkill if G.sima->lock is not set, but still needed */
2498 object_uvs_changed(ob);
2502 int clipUVTransform(TransInfo *t, float *vec, int resize)
2504 #if 0 // TRANSFORM_FIX_ME
2506 int a, clipx=1, clipy=1;
2507 float aspx, aspy, min[2], max[2];
2509 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2510 min[0]= min[1]= 0.0f;
2511 max[0]= aspx; max[1]= aspy;
2513 for(a=0, td= t->data; a<t->total; a++, td++) {
2514 DO_MINMAX2(td->loc, min, max);
2518 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2519 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2520 else if(max[0] > aspx && t->center[0] < aspx)
2521 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2525 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2526 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2527 else if(max[1] > aspy && t->center[1] < aspy)
2528 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2535 else if(max[0] > aspx)
2536 vec[0] -= max[0]-aspx;
2542 else if(max[1] > aspy)
2543 vec[1] -= max[1]-aspy;
2548 return (clipx || clipy);
2553 /* ********************* IPO EDITOR ************************* */
2555 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2556 * due to bad globals that would need to be imported specially for this
2558 static void createTransIpoData(bContext *C, TransInfo *t)
2562 /* in editipo.c due to some globals that are defined in that file... */
2563 make_ipo_transdata(t);
2567 /* this function is called on recalcData to apply the transforms applied
2568 * to the transdata on to the actual keyframe data
2570 void flushTransIpoData(TransInfo *t)
2572 #if 0 // TRANSFORM_FIX_ME
2576 /* flush to 2d vector from internally used 3d vector */
2577 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2578 /* we need to unapply the nla-scaling from the time in some situations */
2580 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2582 td->loc2d[0]= td->loc[0];
2584 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2585 if ((t->data[a].flag & TD_TIMEONLY)==0)
2586 td->loc2d[1]= td->loc[1];
2591 /* ********************* ACTION/NLA EDITOR ****************** */
2593 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2594 * any other gp-frames which may reside on that frame (that are not selected).
2595 * It also makes sure gp-frames are still stored in chronological order after
2598 static void posttrans_gpd_clean (bGPdata *gpd)
2602 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2603 ListBase sel_buffer = {NULL, NULL};
2604 bGPDframe *gpf, *gpfn;
2605 bGPDframe *gfs, *gfsn;
2607 /* loop 1: loop through and isolate selected gp-frames to buffer
2608 * (these need to be sorted as they are isolated)
2610 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2614 if (gpf->flag & GP_FRAME_SELECT) {
2615 BLI_remlink(&gpl->frames, gpf);
2617 /* find place to add them in buffer
2618 * - go backwards as most frames will still be in order,
2619 * so doing it this way will be faster
2621 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2622 /* if current (gpf) occurs after this one in buffer, add! */
2623 if (gfs->framenum < gpf->framenum) {
2624 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2630 BLI_addhead(&sel_buffer, gpf);
2634 /* error checking: it is unlikely, but may be possible to have none selected */
2635 if (sel_buffer.first == NULL)
2638 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2639 if (gpl->frames.first == NULL) {
2640 gpl->frames.first= sel_buffer.first;
2641 gpl->frames.last= sel_buffer.last;
2646 /* loop 2: remove duplicates of frames in buffers */
2647 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2650 /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2651 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2654 /* if this buffer frame needs to go before current, add it! */
2655 if (gfs->framenum < gpf->framenum) {
2656 /* transfer buffer frame to frames list (before current) */
2657 BLI_remlink(&sel_buffer, gfs);
2658 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2660 /* if this buffer frame is on same frame, replace current with it and stop */
2661 else if (gfs->framenum == gpf->framenum) {
2662 /* transfer buffer frame to frames list (before current) */
2663 BLI_remlink(&sel_buffer, gfs);
2664 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2666 /* get rid of current frame */
2668 //gpencil_layer_delframe(gpl, gpf);
2673 /* if anything is still in buffer, append to end */
2674 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2677 BLI_remlink(&sel_buffer, gfs);
2678 BLI_addtail(&gpl->frames, gfs);
2683 /* Called by special_aftertrans_update to make sure selected keyframes replace
2684 * any other keyframes which may reside on that frame (that is not selected).
2686 static void posttrans_ipo_clean (Ipo *ipo)
2691 /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
2692 for (icu= ipo->curve.first; icu; icu= icu->next) {
2693 float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2694 int len, index; /* number of frames in cache, item index */
2696 /* allocate memory for the cache */
2697 // TODO: investigate using GHash for this instead?
2698 if (icu->totvert == 0)
2700 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2704 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
2705 * as there is no guarantee what order the keyframes are exactly, even though
2706 * they have been sorted by time.
2709 /* Loop 1: find selected keyframes */
2710 for (i = 0; i < icu->totvert; i++) {
2711 BezTriple *bezt= &icu->bezt[i];
2713 if (BEZSELECTED(bezt)) {
2714 selcache[index]= bezt->vec[1][0];
2720 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2722 for (i = 0; i < icu->totvert; i++) {
2723 BezTriple *bezt= &icu->bezt[i];
2725 if (BEZSELECTED(bezt) == 0) {
2726 /* check beztriple should be removed according to cache */
2727 for (index= 0; index < len; index++) {
2728 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2729 delete_icu_key(icu, i, 0);
2732 else if (bezt->vec[1][0] > selcache[index])
2738 testhandles_ipocurve(icu);
2742 MEM_freeN(selcache);
2746 /* Called by special_aftertrans_update to make sure selected keyframes replace
2747 * any other keyframes which may reside on that frame (that is not selected).
2748 * remake_action_ipos should have already been called
2750 static void posttrans_action_clean (bAnimContext *ac, bAction *act)
2752 ListBase anim_data = {NULL, NULL};
2757 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
2758 ANIM_animdata_filter(&anim_data, filter, act, ANIMCONT_ACTION);