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_view3d.h"
125 //#include "BSE_drawipo.h"
126 //#include "BSE_edit.h"
127 //#include "BSE_editipo.h"
128 //#include "BSE_editipo_types.h"
129 //#include "BSE_editaction_types.h"
131 //#include "BDR_drawaction.h" // list of keyframes in action
132 //#include "BDR_editobject.h" // reset_slowparents()
133 //#include "BDR_gpencil.h"
134 //#include "BDR_unwrapper.h"
136 #include "BLI_arithb.h"
137 #include "BLI_blenlib.h"
138 #include "BLI_editVert.h"
140 //#include "editmesh.h"
142 //#include "blendef.h"
144 //#include "mydevice.h"
146 extern ListBase editNurb;
147 extern ListBase editelems;
149 #include "transform.h"
151 #include "BLO_sys_types.h" // for intptr_t support
153 /************ STUBS TO GET COMPILE ************/
154 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
158 /* local function prototype - for Object/Bone Constraints */
159 static short constraints_list_needinv(TransInfo *t, ListBase *list);
160 /* local function prototype - for finding number of keyframes that are selected for editing */
161 static int count_ipo_keys(Ipo *ipo, char side, float cfra);
163 /* ************************** Functions *************************** */
165 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
166 TransData pivot = *head;
167 TransData *ihead = head;
168 TransData *itail = tail;
169 short connected = t->flag & T_PROP_CONNECTED;
174 while ((tail->dist >= pivot.dist) && (head < tail))
178 while ((tail->rdist >= pivot.rdist) && (head < tail))
189 while ((head->dist <= pivot.dist) && (head < tail))
193 while ((head->rdist <= pivot.rdist) && (head < tail))
206 qsort_trans_data(t, ihead, head-1);
209 qsort_trans_data(t, head+1, itail);
213 void sort_trans_data_dist(TransInfo *t) {
214 TransData *start = t->data;
217 while(i < t->total && start->flag & TD_SELECTED) {
221 qsort_trans_data(t, start, t->data + t->total - 1);
224 static void sort_trans_data(TransInfo *t)
226 TransData *sel, *unsel;
231 while (sel > unsel) {
232 while (unsel->flag & TD_SELECTED) {
238 while (!(sel->flag & TD_SELECTED)) {
252 /* distance calculated from not-selected vertex to nearest selected vertex
253 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
254 static void set_prop_dist(TransInfo *t, short with_dist)
259 for(a=0, tob= t->data; a<t->total; a++, tob++) {
261 tob->rdist= 0.0f; // init, it was mallocced
263 if((tob->flag & TD_SELECTED)==0) {
268 tob->rdist = -1.0f; // signal for next loop
270 for (i = 0, td= t->data; i < t->total; i++, td++) {
271 if(td->flag & TD_SELECTED) {
272 VecSubf(vec, tob->center, td->center);
273 Mat3MulVecfl(tob->mtx, vec);
274 dist = Normalize(vec);
275 if (tob->rdist == -1.0f) {
278 else if (dist < tob->rdist) {
282 else break; // by definition transdata has selected items in beginning
285 tob->dist = tob->rdist;
291 /* ************************** CONVERSIONS ************************* */
293 /* ********************* texture space ********* */
295 static void createTransTexspace(bContext *C, TransInfo *t)
297 Scene *scene = CTX_data_scene(C);
305 if (ob == NULL) { // Shouldn't logically happen, but still...
311 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
317 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
318 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
320 td->flag= TD_SELECTED;
321 VECCOPY(td->center, ob->obmat[3]);
324 Mat3CpyMat4(td->mtx, ob->obmat);
325 Mat3CpyMat4(td->axismtx, ob->obmat);
326 Mat3Ortho(td->axismtx);
327 Mat3Inv(td->smtx, td->mtx);
329 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
330 *texflag &= ~AUTOSPACE;
333 VECCOPY(td->iloc, td->loc);
334 VECCOPY(td->ext->irot, td->ext->rot);
335 VECCOPY(td->ext->isize, td->ext->size);
338 /* ********************* edge (for crease) ***** */
340 static void createTransEdge(bContext *C, TransInfo *t) {
341 #if 0 // TRANSFORM_FIX_ME
342 TransData *td = NULL;
343 EditMesh *em = G.editMesh;
345 float mtx[3][3], smtx[3][3];
346 int count=0, countsel=0;
347 int propmode = t->flag & T_PROP_EDIT;
349 for(eed= em->edges.first; eed; eed= eed->next) {
351 if (eed->f & SELECT) countsel++;
352 if (propmode) count++;
366 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
368 Mat3CpyMat4(mtx, G.obedit->obmat);
371 for(eed= em->edges.first; eed; eed= eed->next) {
372 if(eed->h==0 && (eed->f & SELECT || propmode)) {
373 /* need to set center for center calculations */
374 VecAddf(td->center, eed->v1->co, eed->v2->co);
375 VecMulf(td->center, 0.5f);
379 td->flag= TD_SELECTED;
384 Mat3CpyMat3(td->smtx, smtx);
385 Mat3CpyMat3(td->mtx, mtx);
389 if (t->mode == TFM_BWEIGHT) {
390 td->val = &(eed->bweight);
391 td->ival = eed->bweight;
394 td->val = &(eed->crease);
395 td->ival = eed->crease;
404 /* ********************* pose mode ************* */
406 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
408 bConstraint *con= pchan->constraints.first;
410 for(;con; con= con->next) {
411 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
412 bKinematicConstraint *data= con->data;
416 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
423 static short apply_targetless_ik(Object *ob)
425 bPoseChannel *pchan, *parchan, *chanlist[256];
426 bKinematicConstraint *data;
427 int segcount, apply= 0;
429 /* now we got a difficult situation... we have to find the
430 target-less IK pchans, and apply transformation to the all
431 pchans that were in the chain */
433 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
434 data= has_targetless_ik(pchan);
435 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
437 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
440 /* exclude tip from chain? */
441 if(!(data->flag & CONSTRAINT_IK_TIP))
442 parchan= pchan->parent;
446 /* Find the chain's root & count the segments needed */
447 for (; parchan; parchan=parchan->parent){
448 chanlist[segcount]= parchan;
451 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
453 for(;segcount;segcount--) {
455 float rmat[4][4], tmat[4][4], imat[4][4];
457 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
458 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
459 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
460 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
462 parchan= chanlist[segcount-1];
464 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
466 if(parchan->parent) {
467 Bone *parbone= parchan->parent->bone;
468 float offs_bone[4][4];
470 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
471 Mat4CpyMat3(offs_bone, bone->bone_mat);
473 /* The bone's root offset (is in the parent's coordinate system) */
474 VECCOPY(offs_bone[3], bone->head);
476 /* Get the length translation of parent (length along y axis) */
477 offs_bone[3][1]+= parbone->length;
479 /* pose_mat(b-1) * offs_bone */
480 if(parchan->bone->flag & BONE_HINGE) {
481 /* the rotation of the parent restposition */
482 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
484 /* the location of actual parent transform */
485 VECCOPY(rmat[3], offs_bone[3]);
486 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
487 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
489 Mat4MulMat4(tmat, offs_bone, rmat);
491 else if(parchan->bone->flag & BONE_NO_SCALE) {
492 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
496 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
498 Mat4Invert(imat, tmat);
501 Mat4CpyMat3(tmat, bone->bone_mat);
503 VECCOPY(tmat[3], bone->head);
504 Mat4Invert(imat, tmat);
507 Mat4MulMat4(rmat, parchan->pose_mat, imat);
509 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
511 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
513 Mat3CpyMat4(rmat3, rmat);
516 Mat3ToQuat(rmat3, parchan->quat);
518 /* for size, remove rotation */
519 /* causes problems with some constraints (so apply only if needed) */
520 if (data->flag & CONSTRAINT_IK_STRETCH) {
521 QuatToMat3(parchan->quat, qmat);
523 Mat3MulMat3(smat, rmat3, imat);
524 Mat3ToSize(smat, parchan->size);
527 /* causes problems with some constraints (e.g. childof), so disable this */
528 /* as it is IK shouldn't affect location directly */
529 /* VECCOPY(parchan->loc, rmat[3]); */
535 data->flag &= ~CONSTRAINT_IK_AUTO;
542 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
544 Bone *bone= pchan->bone;
545 float pmat[3][3], omat[3][3];
546 float cmat[3][3], tmat[3][3];
549 VECCOPY(vec, pchan->pose_mat[3]);
550 VECCOPY(td->center, vec);
553 td->flag= TD_SELECTED|TD_USEQUAT;
554 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
556 td->flag |= TD_NOCENTER;
559 if (bone->flag & BONE_TRANSFORM_CHILD)
561 td->flag |= TD_NOCENTER;
562 td->flag |= TD_NO_LOC;
565 td->protectflag= pchan->protectflag;
567 td->loc = pchan->loc;
568 VECCOPY(td->iloc, pchan->loc);
571 td->ext->quat= pchan->quat;
572 td->ext->size= pchan->size;
574 QUATCOPY(td->ext->iquat, pchan->quat);
575 VECCOPY(td->ext->isize, pchan->size);
577 /* proper way to get parent transform + own transform + constraints transform */
578 Mat3CpyMat4(omat, ob->obmat);
581 if(pchan->bone->flag & BONE_HINGE)
582 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
584 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
586 if (constraints_list_needinv(t, &pchan->constraints)) {
587 Mat3CpyMat4(tmat, pchan->constinv);
589 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
592 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
595 if (constraints_list_needinv(t, &pchan->constraints)) {
596 Mat3CpyMat4(tmat, pchan->constinv);
598 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
601 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
604 Mat3Inv(td->smtx, td->mtx);
606 /* for axismat we use bone's own transform */
607 Mat3CpyMat4(pmat, pchan->pose_mat);
608 Mat3MulMat3(td->axismtx, omat, pmat);
609 Mat3Ortho(td->axismtx);
611 if(t->mode==TFM_BONESIZE) {
612 bArmature *arm= t->poseobj->data;
614 if(arm->drawtype==ARM_ENVELOPE) {
616 td->val= &bone->dist;
617 td->ival= bone->dist;
620 // abusive storage of scale in the loc pointer :)
621 td->loc= &bone->xwidth;
622 VECCOPY (td->iloc, td->loc);
627 /* in this case we can do target-less IK grabbing */
628 if(t->mode==TFM_TRANSLATION) {
629 bKinematicConstraint *data= has_targetless_ik(pchan);
631 if(data->flag & CONSTRAINT_IK_TIP) {
632 VECCOPY(data->grabtarget, pchan->pose_tail);
635 VECCOPY(data->grabtarget, pchan->pose_head);
637 td->loc = data->grabtarget;
638 VECCOPY(td->iloc, td->loc);
639 data->flag |= CONSTRAINT_IK_AUTO;
641 /* only object matrix correction */
642 Mat3CpyMat3 (td->mtx, omat);
643 Mat3Inv (td->smtx, td->mtx);
647 /* store reference to first constraint */
648 td->con= pchan->constraints.first;
651 static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
653 Bone *bone= lb->first;
655 for(;bone;bone= bone->next) {
656 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
658 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
660 else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
662 bone->flag |= BONE_TRANSFORM_CHILD;
666 bone->flag &= ~BONE_TRANSFORM;
669 bone_children_clear_transflag(t, &bone->childbase);
673 /* sets transform flags in the bones, returns total */
674 static void set_pose_transflags(TransInfo *t, Object *ob)
676 bArmature *arm= ob->data;
683 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
685 if(bone->layer & arm->layer) {
686 if(bone->flag & BONE_SELECTED)
687 bone->flag |= BONE_TRANSFORM;
689 bone->flag &= ~BONE_TRANSFORM;
691 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
692 bone->flag &= ~BONE_TRANSFORM_CHILD;
696 /* make sure no bone can be transformed when a parent is transformed */
697 /* since pchans are depsgraph sorted, the parents are in beginning of list */
698 if(t->mode!=TFM_BONESIZE) {
699 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
701 if(bone->flag & BONE_TRANSFORM)
702 bone_children_clear_transflag(t, &bone->childbase);
705 /* now count, and check if we have autoIK or have to switch from translate to rotate */
708 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
710 if(bone->flag & BONE_TRANSFORM) {
714 if(t->mode==TFM_TRANSLATION) {
715 if( has_targetless_ik(pchan)==NULL ) {
716 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
717 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
720 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
729 /* if there are no translatable bones, do rotation */
730 if(t->mode==TFM_TRANSLATION && !hastranslation)
731 t->mode= TFM_ROTATION;
735 /* -------- Auto-IK ---------- */
737 /* adjust pose-channel's auto-ik chainlen */
738 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
742 /* don't bother to search if no valid constraints */
743 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
746 /* check if pchan has ik-constraint */
747 for (con= pchan->constraints.first; con; con= con->next) {
748 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
749 bKinematicConstraint *data= con->data;
751 /* only accept if a temporary one (for auto-ik) */
752 if (data->flag & CONSTRAINT_IK_TEMP) {
753 /* chainlen is new chainlen, but is limited by maximum chainlen */
754 if ((chainlen==0) || (chainlen > data->max_rootbone))
755 data->rootbone= data->max_rootbone;
757 data->rootbone= chainlen;
763 /* change the chain-length of auto-ik */
764 void transform_autoik_update (TransInfo *t, short mode)
766 short *chainlen= &G.scene->toolsettings->autoik_chainlen;
769 /* mode determines what change to apply to chainlen */
771 /* mode=1 is from WHEELMOUSEDOWN... increases len */
774 else if (mode == -1) {
775 /* mode==-1 is from WHEELMOUSEUP... decreases len */
776 if (*chainlen > 0) (*chainlen)--;
779 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
780 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
783 /* apply to all pose-channels */
784 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
785 pchan_autoik_adjust(pchan, *chainlen);
789 /* frees temporal IKs */
790 static void pose_grab_with_ik_clear(Object *ob)
792 bKinematicConstraint *data;
794 bConstraint *con, *next;
796 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
797 /* clear all temporary lock flags */
798 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
800 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
801 /* remove all temporary IK-constraints added */
802 for (con= pchan->constraints.first; con; con= next) {
804 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
806 if (data->flag & CONSTRAINT_IK_TEMP) {
807 BLI_remlink(&pchan->constraints, con);
808 MEM_freeN(con->data);
812 pchan->constflag |= PCHAN_HAS_IK;
813 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
814 pchan->constflag |= PCHAN_HAS_TARGET;
820 /* adds the IK to pchan - returns if added */
821 static short pose_grab_with_ik_add(bPoseChannel *pchan)
823 bKinematicConstraint *data;
825 bConstraint *targetless = 0;
831 /* Rule: not if there's already an IK on this channel */
832 for (con= pchan->constraints.first; con; con= con->next) {
833 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
834 bKinematicConstraint *data= con->data;
835 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
837 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
838 if (con->enforce!=0.0) {
839 targetless->flag |= CONSTRAINT_IK_AUTO;
843 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0))
849 //con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
850 BLI_addtail(&pchan->constraints, con);
851 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
853 if (targetless) { /* if exists use values from last targetless IK-constraint as base */
854 *data = *((bKinematicConstraint*)targetless->data);
857 data->flag= CONSTRAINT_IK_TIP;
858 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
859 VECCOPY(data->grabtarget, pchan->pose_tail);
862 /* we include only a connected chain */
863 while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
864 /* here, we set ik-settings for bone from pchan->protectflag */
865 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
866 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
867 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
869 /* now we count this pchan as being included */
871 pchan= pchan->parent;
874 /* make a copy of maximum chain-length */
875 data->max_rootbone= data->rootbone;
880 /* bone is a candidate to get IK, but we don't do it if it has children connected */
881 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
884 short wentdeeper=0, added=0;
886 /* go deeper if children & children are connected */
887 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
888 if (bonec->flag & BONE_CONNECTED) {
890 added+= pose_grab_with_ik_children(pose, bonec);
894 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
896 added+= pose_grab_with_ik_add(pchan);
902 /* main call which adds temporal IK chains */
903 static short pose_grab_with_ik(Object *ob)
906 bPoseChannel *pchan, *parent;
910 if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
915 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
916 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
917 if (pchan->bone->layer & arm->layer) {
918 if (pchan->bone->flag & BONE_SELECTED) {
919 /* Rule: no IK for solitatry (unconnected) bones */
920 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
921 if (bonec->flag & BONE_CONNECTED) {
925 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
928 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
930 /* only adds if there's no IK yet (and no parent bone was selected) */
931 for (parent= pchan->parent; parent; parent= parent->parent) {
932 if (parent->bone->flag & BONE_SELECTED)
936 tot_ik += pose_grab_with_ik_add(pchan);
939 /* rule: go over the children and add IK to the tips */
940 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
946 return (tot_ik) ? 1 : 0;
950 /* only called with pose mode active object now */
951 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
958 TransDataExtension *tdx;
964 /* check validity of state */
965 arm=get_armature (ob);
966 if (arm==NULL || ob->pose==NULL) return;
968 if (arm->flag & ARM_RESTPOS) {
969 if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
970 notice("Pose edit not possible while Rest Position is enabled");
974 if (!(ob->lay & G.vd->lay)) return;
976 /* do we need to add temporal IK chains? */
977 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
978 ik_on= pose_grab_with_ik(ob);
979 if (ik_on) t->flag |= T_AUTOIK;
982 /* set flags and count total (warning, can change transform to rotate) */
983 set_pose_transflags(t, ob);
985 if(t->total==0) return;
988 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
990 /* make sure the lock is set OK, unlock can be accidentally saved? */
991 ob->pose->flag |= POSE_LOCKED;
992 ob->pose->flag &= ~POSE_DO_UNLOCK;
994 /* init trans data */
995 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
996 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
997 for(i=0; i<t->total; i++, td++, tdx++) {
1003 /* use pose channels to fill trans data */
1005 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1006 if(pchan->bone->flag & BONE_TRANSFORM) {
1007 add_pose_transdata(t, pchan, ob, td);
1012 if(td != (t->data+t->total)) printf("Bone selection count error\n");
1014 /* initialise initial auto=ik chainlen's? */
1015 if (ik_on) transform_autoik_update(t, 0);
1019 /* ********************* armature ************** */
1021 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1026 bArmature *arm= G.obedit->data;
1028 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1031 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
1032 if(ebo->layer & arm->layer) {
1033 if (t->mode==TFM_BONESIZE) {
1034 if (ebo->flag & BONE_SELECTED)
1037 else if (t->mode==TFM_BONE_ROLL) {
1038 if (ebo->flag & BONE_SELECTED)
1042 if (ebo->flag & BONE_TIPSEL)
1044 if (ebo->flag & BONE_ROOTSEL)
1050 if (!t->total) return;
1052 Mat3CpyMat4(mtx, G.obedit->obmat);
1055 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1057 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1058 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1060 if(ebo->layer & arm->layer) {
1061 if (t->mode==TFM_BONE_ENVELOPE) {
1063 if (ebo->flag & BONE_ROOTSEL){
1064 td->val= &ebo->rad_head;
1067 VECCOPY (td->center, ebo->head);
1068 td->flag= TD_SELECTED;
1070 Mat3CpyMat3(td->smtx, smtx);
1071 Mat3CpyMat3(td->mtx, mtx);
1079 if (ebo->flag & BONE_TIPSEL){
1080 td->val= &ebo->rad_tail;
1082 VECCOPY (td->center, ebo->tail);
1083 td->flag= TD_SELECTED;
1085 Mat3CpyMat3(td->smtx, smtx);
1086 Mat3CpyMat3(td->mtx, mtx);
1096 else if (t->mode==TFM_BONESIZE) {
1097 if (ebo->flag & BONE_SELECTED) {
1098 if(arm->drawtype==ARM_ENVELOPE) {
1100 td->val= &ebo->dist;
1101 td->ival= ebo->dist;
1104 // abusive storage of scale in the loc pointer :)
1105 td->loc= &ebo->xwidth;
1106 VECCOPY (td->iloc, td->loc);
1109 VECCOPY (td->center, ebo->head);
1110 td->flag= TD_SELECTED;
1112 /* use local bone matrix */
1113 VecSubf(delta, ebo->tail, ebo->head);
1114 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1115 Mat3MulMat3(td->mtx, mtx, bonemat);
1116 Mat3Inv(td->smtx, td->mtx);
1118 Mat3CpyMat3(td->axismtx, td->mtx);
1119 Mat3Ortho(td->axismtx);
1127 else if (t->mode==TFM_BONE_ROLL) {
1128 if (ebo->flag & BONE_SELECTED) {
1130 td->val= &(ebo->roll);
1131 td->ival= ebo->roll;
1133 VECCOPY (td->center, ebo->head);
1134 td->flag= TD_SELECTED;
1143 if (ebo->flag & BONE_TIPSEL){
1144 VECCOPY (td->iloc, ebo->tail);
1145 VECCOPY (td->center, td->iloc);
1147 td->flag= TD_SELECTED;
1148 if (ebo->flag & BONE_EDITMODE_LOCKED)
1149 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1151 Mat3CpyMat3(td->smtx, smtx);
1152 Mat3CpyMat3(td->mtx, mtx);
1154 VecSubf(delta, ebo->tail, ebo->head);
1155 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1157 if ((ebo->flag & BONE_ROOTSEL) == 0)
1168 if (ebo->flag & BONE_ROOTSEL){
1169 VECCOPY (td->iloc, ebo->head);
1170 VECCOPY (td->center, td->iloc);
1172 td->flag= TD_SELECTED;
1173 if (ebo->flag & BONE_EDITMODE_LOCKED)
1174 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1176 Mat3CpyMat3(td->smtx, smtx);
1177 Mat3CpyMat3(td->mtx, mtx);
1179 VecSubf(delta, ebo->tail, ebo->head);
1180 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1182 td->extra = ebo; /* to fix roll */
1196 /* ********************* meta elements ********* */
1198 static void createTransMBallVerts(bContext *C, TransInfo *t)
1204 TransDataExtension *tx;
1205 float mtx[3][3], smtx[3][3];
1206 int count=0, countsel=0;
1207 int propmode = t->flag & T_PROP_EDIT;
1210 for(ml= editelems.first; ml; ml= ml->next) {
1211 if(ml->flag & SELECT) countsel++;
1212 if(propmode) count++;
1215 /* note: in prop mode we need at least 1 selected */
1216 if (countsel==0) return;
1218 if(propmode) t->total = count;
1219 else t->total = countsel;
1221 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1222 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1224 Mat3CpyMat4(mtx, G.obedit->obmat);
1227 for(ml= editelems.first; ml; ml= ml->next) {
1228 if(propmode || (ml->flag & SELECT)) {
1230 VECCOPY(td->iloc, td->loc);
1231 VECCOPY(td->center, td->loc);
1233 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1234 else td->flag= TD_USEQUAT;
1236 Mat3CpyMat3(td->smtx, smtx);
1237 Mat3CpyMat3(td->mtx, mtx);
1242 /* Radius of MetaElem (mass of MetaElem influence) */
1243 if(ml->flag & MB_SCALE_RAD){
1252 /* expx/expy/expz determine "shape" of some MetaElem types */
1253 tx->size = &ml->expx;
1254 tx->isize[0] = ml->expx;
1255 tx->isize[1] = ml->expy;
1256 tx->isize[2] = ml->expz;
1258 /* quat is used for rotation of MetaElem */
1259 tx->quat = ml->quat;
1260 QUATCOPY(tx->iquat, ml->quat);
1271 /* ********************* curve/surface ********* */
1273 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1274 TransData *td, *td_near = NULL;
1275 for (td = head; td<=tail; td++) {
1276 if (td->flag & TD_SELECTED) {
1282 dist = VecLenf(td_near->center, td->center);
1283 if (dist < (td-1)->dist) {
1284 td->dist = (td-1)->dist;
1291 td->dist = MAXFLOAT;
1292 td->flag |= TD_NOTCONNECTED;
1296 for (td = tail; td>=head; td--) {
1297 if (td->flag & TD_SELECTED) {
1303 dist = VecLenf(td_near->center, td->center);
1304 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1305 td->flag &= ~TD_NOTCONNECTED;
1306 if (dist < (td+1)->dist) {
1307 td->dist = (td+1)->dist;
1317 /* Utility function for getting the handle data from bezier's */
1318 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1319 TransDataCurveHandleFlags *hdata;
1320 td->flag |= TD_BEZTRIPLE;
1321 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1322 hdata->ih1 = bezt->h1;
1323 hdata->h1 = &bezt->h1;
1324 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1325 hdata->h2 = &bezt->h2;
1329 static void createTransCurveVerts(bContext *C, TransInfo *t)
1333 TransData *td = NULL;
1337 float mtx[3][3], smtx[3][3];
1339 int count=0, countsel=0;
1340 int propmode = t->flag & T_PROP_EDIT;
1342 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1343 for(nu= editNurb.first; nu; nu= nu->next) {
1344 if((nu->type & 7)==CU_BEZIER) {
1345 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1347 if (G.f & G_HIDDENHANDLES) {
1348 if(bezt->f2 & SELECT) countsel+=3;
1349 if(propmode) count+= 3;
1351 if(bezt->f1 & SELECT) countsel++;
1352 if(bezt->f2 & SELECT) countsel++;
1353 if(bezt->f3 & SELECT) countsel++;
1354 if(propmode) count+= 3;
1360 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1362 if(propmode) count++;
1363 if(bp->f1 & SELECT) countsel++;
1368 /* note: in prop mode we need at least 1 selected */
1369 if (countsel==0) return;
1371 if(propmode) t->total = count;
1372 else t->total = countsel;
1373 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1375 Mat3CpyMat4(mtx, G.obedit->obmat);
1379 for(nu= editNurb.first; nu; nu= nu->next) {
1380 if((nu->type & 7)==CU_BEZIER) {
1381 TransData *head, *tail;
1383 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1385 TransDataCurveHandleFlags *hdata = NULL;
1388 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1389 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1391 VECCOPY(td->iloc, bezt->vec[0]);
1392 td->loc= bezt->vec[0];
1393 VECCOPY(td->center, bezt->vec[1]);
1394 if (G.f & G_HIDDENHANDLES) {
1395 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1398 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1405 hdata = initTransDataCurveHandes(td, bezt);
1407 Mat3CpyMat3(td->smtx, smtx);
1408 Mat3CpyMat3(td->mtx, mtx);
1415 /* This is the Curve Point, the other two are handles */
1416 if(propmode || (bezt->f2 & SELECT)) {
1417 VECCOPY(td->iloc, bezt->vec[1]);
1418 td->loc= bezt->vec[1];
1419 VECCOPY(td->center, td->loc);
1420 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1425 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1426 td->val = &(bezt->radius);
1427 td->ival = bezt->radius;
1428 } else if (t->mode==TFM_TILT) {
1429 td->val = &(bezt->alfa);
1430 td->ival = bezt->alfa;
1435 Mat3CpyMat3(td->smtx, smtx);
1436 Mat3CpyMat3(td->mtx, mtx);
1438 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1439 /* If the middle is selected but the sides arnt, this is needed */
1440 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1441 hdata = initTransDataCurveHandes(td, bezt);
1449 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1450 ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1452 VECCOPY(td->iloc, bezt->vec[2]);
1453 td->loc= bezt->vec[2];
1454 VECCOPY(td->center, bezt->vec[1]);
1455 if (G.f & G_HIDDENHANDLES) {
1456 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1459 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1466 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1467 hdata = initTransDataCurveHandes(td, bezt);
1470 Mat3CpyMat3(td->smtx, smtx);
1471 Mat3CpyMat3(td->mtx, mtx);
1478 else if (propmode && head != tail) {
1479 calc_distanceCurveVerts(head, tail-1);
1483 if (propmode && head != tail)
1484 calc_distanceCurveVerts(head, tail-1);
1486 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1487 * but for now just dont change handle types */
1488 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1489 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1492 TransData *head, *tail;
1494 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1496 if(propmode || (bp->f1 & SELECT)) {
1497 VECCOPY(td->iloc, bp->vec);
1499 VECCOPY(td->center, td->loc);
1500 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1505 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1506 td->val = &(bp->radius);
1507 td->ival = bp->radius;
1509 td->val = &(bp->alfa);
1510 td->ival = bp->alfa;
1513 Mat3CpyMat3(td->smtx, smtx);
1514 Mat3CpyMat3(td->mtx, mtx);
1521 else if (propmode && head != tail) {
1522 calc_distanceCurveVerts(head, tail-1);
1526 if (propmode && head != tail)
1527 calc_distanceCurveVerts(head, tail-1);
1533 /* ********************* lattice *************** */
1535 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1539 TransData *td = NULL;
1541 float mtx[3][3], smtx[3][3];
1543 int count=0, countsel=0;
1544 int propmode = t->flag & T_PROP_EDIT;
1547 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1550 if(bp->f1 & SELECT) countsel++;
1551 if(propmode) count++;
1556 /* note: in prop mode we need at least 1 selected */
1557 if (countsel==0) return;
1559 if(propmode) t->total = count;
1560 else t->total = countsel;
1561 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1563 Mat3CpyMat4(mtx, G.obedit->obmat);
1568 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1570 if(propmode || (bp->f1 & SELECT)) {
1572 VECCOPY(td->iloc, bp->vec);
1574 VECCOPY(td->center, td->loc);
1575 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1577 Mat3CpyMat3(td->smtx, smtx);
1578 Mat3CpyMat3(td->mtx, mtx);
1593 /* ******************* particle edit **************** */
1594 static void createTransParticleVerts(bContext *C, TransInfo *t)
1598 TransData *td = NULL;
1599 TransDataExtension *tx;
1600 Base *base = BASACT;
1602 ParticleSystem *psys = PE_get_current(ob);
1603 ParticleSystemModifierData *psmd = NULL;
1604 ParticleEditSettings *pset = PE_settings();
1605 ParticleData *pa = NULL;
1607 ParticleEditKey *key;
1609 int i,k, totpart, transformparticle;
1610 int count = 0, hasselected = 0;
1611 int propmode = t->flag & T_PROP_EDIT;
1613 if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1615 psmd = psys_get_modifier(ob,psys);
1618 totpart = psys->totpart;
1619 base->flag |= BA_HAS_RECALC_DATA;
1621 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1622 pa->flag &= ~PARS_TRANSFORM;
1623 transformparticle= 0;
1625 if((pa->flag & PARS_HIDE)==0) {
1626 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1627 if((key->flag&PEK_HIDE)==0) {
1628 if(key->flag&PEK_SELECT) {
1630 transformparticle= 1;
1633 transformparticle= 1;
1638 if(transformparticle) {
1639 count += pa->totkey;
1640 pa->flag |= PARS_TRANSFORM;
1644 /* note: in prop mode we need at least 1 selected */
1645 if (hasselected==0) return;
1648 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1650 if(t->mode == TFM_BAKE_TIME)
1651 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1657 Mat4Invert(ob->imat,ob->obmat);
1659 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1660 TransData *head, *tail;
1663 if(!(pa->flag & PARS_TRANSFORM)) continue;
1665 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1667 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1668 VECCOPY(key->world_co, key->co);
1669 Mat4MulVecfl(mat, key->world_co);
1670 td->loc = key->world_co;
1672 VECCOPY(td->iloc, td->loc);
1673 VECCOPY(td->center, td->loc);
1675 if(key->flag & PEK_SELECT)
1676 td->flag |= TD_SELECTED;
1678 td->flag |= TD_SKIP;
1683 /* don't allow moving roots */
1684 if(k==0 && pset->flag & PE_LOCK_FIRST)
1685 td->protectflag |= OB_LOCK_LOC;
1690 if(t->mode == TFM_BAKE_TIME) {
1691 td->val = key->time;
1692 td->ival = *(key->time);
1693 /* abuse size and quat for min/max values */
1694 td->flag |= TD_NO_EXT;
1695 if(k==0) tx->size = 0;
1696 else tx->size = (key - 1)->time;
1698 if(k == pa->totkey - 1) tx->quat = 0;
1699 else tx->quat = (key + 1)->time;
1707 if (propmode && head != tail)
1708 calc_distanceCurveVerts(head, tail - 1);
1713 void flushTransParticles(TransInfo *t)
1715 #if 0 // TRANSFORM_FIX_ME
1716 Scene *scene = t->scene;
1718 ParticleSystem *psys = PE_get_current(ob);
1719 ParticleSystemModifierData *psmd;
1721 ParticleEditKey *key;
1723 float mat[4][4], imat[4][4], co[3];
1724 int i, k, propmode = t->flag & T_PROP_EDIT;
1726 psmd = psys_get_modifier(ob, psys);
1728 /* we do transform in world space, so flush world space position
1729 * back to particle local space */
1731 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1732 if(!(pa->flag & PARS_TRANSFORM)) continue;
1734 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1735 Mat4Invert(imat,mat);
1737 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1738 VECCOPY(co, key->world_co);
1739 Mat4MulVecfl(imat, co);
1741 /* optimization for proportional edit */
1742 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1743 VECCOPY(key->co, co);
1744 pa->flag |= PARS_EDIT_RECALC;
1749 PE_update_object(OBACT, 1);
1753 /* ********************* mesh ****************** */
1755 /* proportional distance based on connectivity */
1756 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1757 #define E_NEAR(a) (nears[((a)->tmp.l)])
1758 #define THRESHOLD 0.0001f
1759 static void editmesh_set_connectivity_distance(int total, float *vectors, EditVert **nears)
1761 EditMesh *em = G.editMesh;
1766 /* f2 flag is used for 'selection' */
1767 /* tmp.l is offset on scratch array */
1768 for(eve= em->verts.first; eve; eve= eve->next) {
1772 if(eve->f & SELECT) {
1775 E_VEC(eve)[0] = 0.0f;
1776 E_VEC(eve)[1] = 0.0f;
1777 E_VEC(eve)[2] = 0.0f;
1786 /* Floodfill routine */
1788 At worst this is n*n of complexity where n is number of edges
1789 Best case would be n if the list is ordered perfectly.
1790 Estimate is n log n in average (so not too bad)
1795 for(eed= em->edges.first; eed; eed= eed->next) {
1797 EditVert *v1= eed->v1, *v2= eed->v2;
1798 float *vec2 = E_VEC(v2);
1799 float *vec1 = E_VEC(v1);
1801 if (v1->f2 + v2->f2 == 4)
1807 float len1 = VecLength(vec1);
1808 float len2 = VecLength(vec2);
1810 /* for v2 if not selected */
1812 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1813 lenn = VecLength(nvec);
1815 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1816 VECCOPY(vec2, nvec);
1817 E_NEAR(v2) = E_NEAR(v1);
1821 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1822 VECCOPY(vec2, vec1);
1823 E_NEAR(v2) = E_NEAR(v1);
1827 /* for v1 if not selected */
1829 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1830 lenn = VecLength(nvec);
1832 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1833 VECCOPY(vec1, nvec);
1834 E_NEAR(v1) = E_NEAR(v2);
1838 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1839 VECCOPY(vec1, vec2);
1840 E_NEAR(v1) = E_NEAR(v2);
1847 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1849 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1850 VECCOPY(vec2, vec1);
1852 E_NEAR(v2) = E_NEAR(v1);
1858 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1860 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1861 VECCOPY(vec1, vec2);
1863 E_NEAR(v1) = E_NEAR(v2);
1871 /* loop-in-a-loop I know, but we need it! (ton) */
1872 static void get_face_center(float *cent, EditVert *eve)
1874 EditMesh *em = G.editMesh;
1877 for(efa= em->faces.first; efa; efa= efa->next)
1879 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1882 VECCOPY(cent, efa->cent);
1886 //way to overwrite what data is edited with transform
1887 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1888 static void VertsToTransData(TransData *td, EditVert *eve)
1892 // td->loc = key->co;
1896 VECCOPY(td->center, td->loc);
1898 // if(G.vd->around==V3D_LOCAL && (G.scene->selectmode & SCE_SELECT_FACE))
1899 // get_face_center(td->center, eve);
1900 VECCOPY(td->iloc, td->loc);
1903 VECCOPY(td->axismtx[2], eve->no);
1909 td->axismtx[1][2] = 0.0f;
1915 if (BIF_GetTransInfo()->mode == TFM_BWEIGHT) {
1916 td->val = &(eve->bweight);
1917 td->ival = eve->bweight;
1922 td->verse = (void*)eve->vvert;
1923 td->flag |= TD_VERSE_VERT;
1926 td->flag &= ~TD_VERSE_VERT;
1930 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1932 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1934 float *vec = userData;
1940 static int modifiers_disable_subsurf_temporary(Object *ob)
1945 for(md=ob->modifiers.first; md; md=md->next)
1946 if(md->type==eModifierType_Subsurf)
1947 if(md->mode & eModifierMode_OnCage) {
1948 md->mode ^= eModifierMode_DisableTemporary;
1955 /* disable subsurf temporal, get mapped cos, and enable it */
1956 static float *get_crazy_mapped_editverts(void)
1961 /* disable subsurf temporal, get mapped cos, and enable it */
1962 if(modifiers_disable_subsurf_temporary(G.obedit)) {
1963 /* need to make new derivemesh */
1964 makeDerivedMesh(G.obedit, CD_MASK_BAREMESH);
1967 /* now get the cage */
1968 dm= editmesh_get_derived_cage(CD_MASK_BAREMESH);
1970 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1971 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1975 /* set back the flag, no new cage needs to be built, transform does it */
1976 modifiers_disable_subsurf_temporary(G.obedit);
1981 #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])
1982 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1984 float vecu[3], vecv[3];
1987 TAN_MAKE_VEC(vecu, v1, v2);
1988 TAN_MAKE_VEC(vecv, v1, v3);
1989 triatoquat(v1, vecu, vecv, q1);
1991 TAN_MAKE_VEC(vecu, def1, def2);
1992 TAN_MAKE_VEC(vecv, def1, def3);
1993 triatoquat(def1, vecu, vecv, q2);
1995 QuatSub(quat, q2, q1);
1999 static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats)
2001 EditMesh *em = G.editMesh;
2002 EditVert *eve, *prev;
2004 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2007 /* two abused locations in vertices */
2008 for(eve= em->verts.first; eve; eve= eve->next, index++) {
2010 eve->prev= (EditVert *)index;
2013 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2014 for(efa= em->faces.first; efa; efa= efa->next) {
2016 /* retrieve mapped coordinates */
2017 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2018 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2019 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2021 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2022 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2023 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2025 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2026 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2027 efa->v2->tmp.p= (void*)quats;
2032 v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2033 co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2035 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2036 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2037 efa->v1->tmp.p= (void*)quats;
2040 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2041 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2042 efa->v3->tmp.p= (void*)quats;
2045 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2046 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2047 efa->v4->tmp.p= (void*)quats;
2052 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2053 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2054 efa->v1->tmp.p= (void*)quats;
2057 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2058 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2059 efa->v3->tmp.p= (void*)quats;
2065 /* restore abused prev pointer */
2066 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2071 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2077 tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2079 for (i=0,v=bm->verts.first;v;v=v->next) {
2080 if ( (vtd = BME_get_transdata(td,v)) ) {
2081 tob->loc = vtd->loc;
2082 tob->val = &vtd->factor;
2083 VECCOPY(tob->iloc,vtd->co);
2084 VECCOPY(tob->center,vtd->org);
2085 VECCOPY(tob->axismtx[0],vtd->vec);
2086 tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2091 /* since td is a memarena, it can hold more transdata than actual elements
2092 * (i.e. we can't depend on td->len to determine the number of actual elements) */
2096 static void createTransEditVerts(bContext *C, TransInfo *t)
2100 TransData *tob = NULL;
2101 EditMesh *em = G.editMesh;
2103 EditVert **nears = NULL;
2104 EditVert *eve_act = NULL;
2105 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2106 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2107 int count=0, countsel=0, a, totleft;
2108 int propmode = t->flag & T_PROP_EDIT;
2111 if ((t->context & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2116 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2117 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2118 for(eve= em->verts.first; eve; eve= eve->next) {
2119 if(eve->h==0 && (eve->f & SELECT))
2125 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2127 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2128 for(eed= em->edges.first; eed; eed= eed->next) {
2129 if(eed->h==0 && (eed->f & SELECT))
2130 eed->v1->f1= eed->v2->f1= SELECT;
2135 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2136 for(efa= em->faces.first; efa; efa= efa->next) {
2137 if(efa->h==0 && (efa->f & SELECT)) {
2138 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2139 if(efa->v4) efa->v4->f1= SELECT;
2144 /* now we can count */
2145 for(eve= em->verts.first; eve; eve= eve->next) {
2147 if(eve->f1) countsel++;
2148 if(propmode) count++;
2152 /* note: in prop mode we need at least 1 selected */
2153 if (countsel==0) return;
2156 if (G.editMesh->selected.last) {
2157 EditSelection *ese = G.editMesh->selected.last;
2158 if ( ese->type == EDITVERT ) {
2159 eve_act = (EditVert *)ese->data;
2167 /* allocating scratch arrays */
2168 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2169 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2171 else t->total = countsel;
2172 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2174 Mat3CpyMat4(mtx, G.obedit->obmat);
2177 if(propmode) editmesh_set_connectivity_distance(t->total, vectors, nears);
2179 /* detect CrazySpace [tm] */
2181 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
2182 if(modifiers_isDeformed(G.obedit)) {
2183 /* check if we can use deform matrices for modifier from the
2184 start up to stack, they are more accurate than quats */
2185 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
2187 /* if we still have more modifiers, also do crazyspace
2188 correction with quats, relative to the coordinates after
2189 the modifiers that support deform matrices (defcos) */
2191 mappedcos= get_crazy_mapped_editverts();
2192 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2193 set_crazyspace_quats((float*)defcos, mappedcos, quats);
2195 MEM_freeN(mappedcos);
2204 /* find out which half we do */
2206 for (eve=em->verts.first; eve; eve=eve->next) {
2207 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2215 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2217 if(propmode || eve->f1) {
2218 VertsToTransData(tob, eve);
2221 if(eve->f1) tob->flag |= TD_SELECTED;
2224 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2229 VECCOPY(vec, E_VEC(eve));
2230 Mat3MulVecfl(mtx, vec);
2231 tob->dist= VecLength(vec);
2234 tob->flag |= TD_NOTCONNECTED;
2235 tob->dist = MAXFLOAT;
2240 if(defmats || (quats && eve->tmp.p)) {
2241 float mat[3][3], imat[3][3], qmat[3][3];
2243 /* use both or either quat and defmat correction */
2244 if(quats && eve->tmp.f) {
2245 QuatToMat3(eve->tmp.p, qmat);
2248 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2249 NULL, NULL, NULL, NULL, NULL);
2251 Mat3MulMat3(mat, mtx, qmat);
2254 Mat3MulMat3(mat, mtx, defmats[a]);
2258 Mat3CpyMat3(tob->smtx, imat);
2259 Mat3CpyMat3(tob->mtx, mat);
2262 Mat3CpyMat3(tob->smtx, smtx);
2263 Mat3CpyMat3(tob->mtx, mtx);
2267 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2268 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
2269 if(vmir != eve) tob->extra = vmir;
2279 /* crazy space free */
2287 /* ********************* UV ****************** */
2289 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2293 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2295 /* uv coords are scaled by aspects. this is needed for rotations and
2296 proportional editing to be consistent with the stretchted uv coords
2297 that are displayed. this also means that for display and numinput,
2298 and when the the uv coords are flushed, these are converted each time */
2299 td2d->loc[0] = uv[0]*aspx;
2300 td2d->loc[1] = uv[1]*aspy;
2301 td2d->loc[2] = 0.0f;
2305 td->loc = td2d->loc;
2306 VECCOPY(td->center, td->loc);
2307 VECCOPY(td->iloc, td->loc);
2309 memset(td->axismtx, 0, sizeof(td->axismtx));
2310 td->axismtx[2][2] = 1.0f;
2312 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2315 td->flag |= TD_SELECTED;
2325 static void createTransUVs(bContext *C, TransInfo *t)
2329 TransData *td = NULL;
2330 TransData2D *td2d = NULL;
2332 int count=0, countsel=0;
2333 int propmode = t->flag & T_PROP_EDIT;
2334 int efa_s1,efa_s2,efa_s3,efa_s4;
2336 EditMesh *em = G.editMesh;
2339 if(is_uv_tface_editing_allowed()==0) return;
2342 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2343 for (efa= em->faces.first; efa; efa= efa->next) {
2344 /* store face pointer for second loop, prevent second lookup */
2345 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2346 if (simaFaceDraw_Check(efa, tf)) {
2349 efa_s1 = simaUVSel_Check(efa, tf, 0);
2350 efa_s2 = simaUVSel_Check(efa, tf, 1);
2351 efa_s3 = simaUVSel_Check(efa, tf, 2);
2353 efa_s4 = simaUVSel_Check(efa, tf, 3);
2354 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2355 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2358 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2359 if (efa_s1) countsel++;
2360 if (efa_s2) countsel++;
2361 if (efa_s3) countsel++;
2368 for (efa= em->faces.first; efa; efa= efa->next) {
2369 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2370 if (simaFaceDraw_Check(efa, tf)) {
2373 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2374 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2375 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2376 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2378 count += (efa->v4)? 4: 3;
2385 /* note: in prop mode we need at least 1 selected */
2386 if (countsel==0) return;
2388 t->total= (propmode)? count: countsel;
2389 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2390 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2391 treated just as if they were 3d verts */
2392 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2394 if(G.sima->flag & SI_CLIP_UV)
2395 t->flag |= T_CLIP_UV;
2400 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2401 for (efa= em->faces.first; efa; efa= efa->next) {
2402 tf=(MTFace *)efa->tmp.p;
2404 efa_s1 = simaUVSel_Check(efa, tf, 0);
2405 efa_s2 = simaUVSel_Check(efa, tf, 1);
2406 efa_s3 = simaUVSel_Check(efa, tf, 2);
2409 efa_s4 = simaUVSel_Check(efa, tf, 3);
2411 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2412 /* all corners of this quad need their edges moved. so we must store TD for each */
2414 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2415 if (!efa_s1) td->flag |= TD_SKIP;
2418 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2419 if (!efa_s2) td->flag |= TD_SKIP;
2422 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2423 if (!efa_s3) td->flag |= TD_SKIP;
2426 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2427 if (!efa_s4) td->flag |= TD_SKIP;
2431 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2432 if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2433 if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2434 if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2439 for (efa= em->faces.first; efa; efa= efa->next) {
2440 /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2441 if (simaFaceDraw_Check(efa, tf)) {*/
2442 if ((tf=(MTFace *)efa->tmp.p)) {
2444 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2445 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2446 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2448 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2450 if(simaUVSel_Check(efa, tf, 0)) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2451 if(simaUVSel_Check(efa, tf, 1)) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2452 if(simaUVSel_Check(efa, tf, 2)) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2453 if(efa->v4 && simaUVSel_Check(efa, tf, 3)) UVsToTransData(td++, td2d++, tf->uv[3], 1);
2459 if (G.sima->flag & SI_LIVE_UNWRAP)
2460 unwrap_lscm_live_begin();
2464 void flushTransUVs(TransInfo *t)
2466 #if 0 // TRANSFORM_FIX_ME
2468 int a, width, height;
2470 EditMesh *em = G.editMesh;
2471 float aspx, aspy, invx, invy;
2473 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2474 transform_width_height_tface_uv(&width, &height);
2478 /* flush to 2d vector from internally used 3d vector */
2479 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2480 td->loc2d[0]= td->loc[0]*invx;
2481 td->loc2d[1]= td->loc[1]*invy;
2483 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2484 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2485 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2489 if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL))
2490 be_square_tface_uv(em);
2492 /* this is overkill if G.sima->lock is not set, but still needed */
2493 object_uvs_changed(ob);
2497 int clipUVTransform(TransInfo *t, float *vec, int resize)
2499 #if 0 // TRANSFORM_FIX_ME
2501 int a, clipx=1, clipy=1;
2502 float aspx, aspy, min[2], max[2];
2504 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2505 min[0]= min[1]= 0.0f;
2506 max[0]= aspx; max[1]= aspy;
2508 for(a=0, td= t->data; a<t->total; a++, td++) {
2509 DO_MINMAX2(td->loc, min, max);
2513 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2514 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2515 else if(max[0] > aspx && t->center[0] < aspx)
2516 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2520 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2521 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2522 else if(max[1] > aspy && t->center[1] < aspy)
2523 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2530 else if(max[0] > aspx)
2531 vec[0] -= max[0]-aspx;
2537 else if(max[1] > aspy)
2538 vec[1] -= max[1]-aspy;
2543 return (clipx || clipy);
2548 /* ********************* IPO EDITOR ************************* */
2550 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2551 * due to bad globals that would need to be imported specially for this
2553 static void createTransIpoData(bContext *C, TransInfo *t)
2557 /* in editipo.c due to some globals that are defined in that file... */
2558 make_ipo_transdata(t);
2562 /* this function is called on recalcData to apply the transforms applied
2563 * to the transdata on to the actual keyframe data
2565 void flushTransIpoData(TransInfo *t)
2567 #if 0 // TRANSFORM_FIX_ME
2571 /* flush to 2d vector from internally used 3d vector */
2572 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2573 /* we need to unapply the nla-scaling from the time in some situations */
2575 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2577 td->loc2d[0]= td->loc[0];
2579 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2580 if ((t->data[a].flag & TD_TIMEONLY)==0)
2581 td->loc2d[1]= td->loc[1];
2586 /* ********************* ACTION/NLA EDITOR ****************** */
2588 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2589 * any other gp-frames which may reside on that frame (that are not selected).
2590 * It also makes sure gp-frames are still stored in chronological order after
2593 static void posttrans_gpd_clean (bGPdata *gpd)
2597 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2598 ListBase sel_buffer = {NULL, NULL};
2599 bGPDframe *gpf, *gpfn;
2600 bGPDframe *gfs, *gfsn;
2602 /* loop 1: loop through and isolate selected gp-frames to buffer
2603 * (these need to be sorted as they are isolated)
2605 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2609 if (gpf->flag & GP_FRAME_SELECT) {
2610 BLI_remlink(&gpl->frames, gpf);
2612 /* find place to add them in buffer
2613 * - go backwards as most frames will still be in order,
2614 * so doing it this way will be faster
2616 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2617 /* if current (gpf) occurs after this one in buffer, add! */
2618 if (gfs->framenum < gpf->framenum) {
2619 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2625 BLI_addhead(&sel_buffer, gpf);
2629 /* error checking: it is unlikely, but may be possible to have none selected */
2630 if (sel_buffer.first == NULL)
2633 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2634 if (gpl->frames.first == NULL) {
2635 gpl->frames.first= sel_buffer.first;
2636 gpl->frames.last= sel_buffer.last;
2641 /* loop 2: remove duplicates of frames in buffers */
2642 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2645 /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2646 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2649 /* if this buffer frame needs to go before current, add it! */
2650 if (gfs->framenum < gpf->framenum) {
2651 /* transfer buffer frame to frames list (before current) */
2652 BLI_remlink(&sel_buffer, gfs);
2653 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2655 /* if this buffer frame is on same frame, replace current with it and stop */
2656 else if (gfs->framenum == gpf->framenum) {
2657 /* transfer buffer frame to frames list (before current) */
2658 BLI_remlink(&sel_buffer, gfs);
2659 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2661 /* get rid of current frame */
2663 //gpencil_layer_delframe(gpl, gpf);
2668 /* if anything is still in buffer, append to end */
2669 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2672 BLI_remlink(&sel_buffer, gfs);
2673 BLI_addtail(&gpl->frames, gfs);
2678 /* Called by special_aftertrans_update to make sure selected keyframes replace
2679 * any other keyframes which may reside on that frame (that is not selected).
2681 static void posttrans_ipo_clean (Ipo *ipo)
2683 #if 0 // TRANSFORM_FIX_ME
2687 /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
2688 for (icu= ipo->curve.first; icu; icu= icu->next) {
2689 float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2690 int len, index; /* number of frames in cache, item index */
2692 /* allocate memory for the cache */
2693 // TODO: investigate using GHash for this instead?
2694 if (icu->totvert == 0)
2696 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2700 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
2701 * as there is no guarantee what order the keyframes are exactly, even though
2702 * they have been sorted by time.
2705 /* Loop 1: find selected keyframes */
2706 for (i = 0; i < icu->totvert; i++) {
2707 BezTriple *bezt= &icu->bezt[i];
2709 if (BEZSELECTED(bezt)) {
2710 selcache[index]= bezt->vec[1][0];
2716 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2718 for (i = 0; i < icu->totvert; i++) {
2719 BezTriple *bezt= &icu->bezt[i];
2721 if (BEZSELECTED(bezt) == 0) {
2722 /* check beztriple should be removed according to cache */
2723 for (index= 0; index < len; index++) {
2724 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2725 delete_icu_key(icu, i, 0);
2728 else if (bezt->vec[1][0] > selcache[index])
2734 testhandles_ipocurve(icu);
2738 MEM_freeN(selcache);
2743 /* Called by special_aftertrans_update to make sure selected keyframes replace
2744 * any other keyframes which may reside on that frame (that is not selected).
2745 * remake_action_ipos should have already been called
2747 static void posttrans_action_clean (bAction *act)
2749 #if 0 // TRANSFORM_FIX_ME
2750 ListBase act_data = {NULL, NULL};
2755 filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
2756 actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
2758 /* loop through relevant data, removing keyframes from the ipo-blocks that were attached