4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
38 #include "MEM_guardedalloc.h"
40 #include "DNA_action_types.h"
41 #include "DNA_armature_types.h"
42 #include "DNA_camera_types.h"
43 #include "DNA_curve_types.h"
44 #include "DNA_effect_types.h"
45 #include "DNA_image_types.h"
46 #include "DNA_ipo_types.h"
47 #include "DNA_key_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_modifier_types.h"
54 #include "DNA_nla_types.h"
55 #include "DNA_node_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_object_force.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_texture_types.h"
63 #include "DNA_view3d_types.h"
64 #include "DNA_world_types.h"
65 #include "DNA_userdef_types.h"
66 #include "DNA_property_types.h"
67 #include "DNA_vfont_types.h"
68 #include "DNA_constraint_types.h"
69 #include "DNA_listBase.h"
70 #include "DNA_gpencil_types.h"
72 #include "BKE_action.h"
73 #include "BKE_armature.h"
74 #include "BKE_blender.h"
75 #include "BKE_cloth.h"
76 #include "BKE_curve.h"
77 #include "BKE_constraint.h"
78 #include "BKE_depsgraph.h"
79 #include "BKE_displist.h"
80 #include "BKE_DerivedMesh.h"
81 #include "BKE_effect.h"
83 #include "BKE_global.h"
85 #include "BKE_lattice.h"
88 #include "BKE_mball.h"
90 #include "BKE_modifier.h"
91 #include "BKE_object.h"
92 #include "BKE_particle.h"
93 #include "BKE_pointcache.h"
94 #include "BKE_softbody.h"
95 #include "BKE_utildefines.h"
96 #include "BKE_bmesh.h"
97 #include "BKE_context.h"
99 //#include "BIF_editaction.h"
100 //#include "BIF_editview.h"
101 //#include "BIF_editlattice.h"
102 //#include "BIF_editconstraint.h"
103 #include "BIF_editarmature.h"
104 //#include "BIF_editmesh.h"
105 //#include "BIF_editnla.h"
106 //#include "BIF_editsima.h"
107 //#include "BIF_editparticle.h"
109 //#include "BIF_keyframing.h"
110 //#include "BIF_poseobject.h"
111 //#include "BIF_meshtools.h"
112 //#include "BIF_mywindow.h"
113 //#include "BIF_resources.h"
114 #include "BIF_retopo.h"
115 //#include "BIF_screen.h"
116 //#include "BIF_space.h"
117 //#include "BIF_toolbox.h"
119 #include "ED_types.h"
120 #include "ED_anim_api.h"
121 #include "ED_keyframing.h"
122 #include "ED_keyframes_edit.h"
123 #include "ED_view3d.h"
126 #include "UI_view2d.h"
128 //#include "BSE_drawipo.h"
129 //#include "BSE_edit.h"
130 //#include "BSE_editipo.h"
131 //#include "BSE_editipo_types.h"
132 //#include "BSE_editaction_types.h"
134 //#include "BDR_drawaction.h" // list of keyframes in action
135 //#include "BDR_editobject.h" // reset_slowparents()
136 //#include "BDR_gpencil.h"
137 //#include "BDR_unwrapper.h"
139 #include "BLI_arithb.h"
140 #include "BLI_blenlib.h"
141 #include "BLI_editVert.h"
143 //#include "editmesh.h"
145 //#include "blendef.h"
147 //#include "mydevice.h"
149 extern ListBase editNurb;
150 extern ListBase editelems;
152 #include "transform.h"
154 #include "BLO_sys_types.h" // for intptr_t support
156 /************ STUBS TO GET COMPILE ************/
157 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
161 /* local function prototype - for Object/Bone Constraints */
162 static short constraints_list_needinv(TransInfo *t, ListBase *list);
163 /* local function prototype - for finding number of keyframes that are selected for editing */
164 static int count_ipo_keys(Ipo *ipo, char side, float cfra);
166 /* ************************** Functions *************************** */
168 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
169 TransData pivot = *head;
170 TransData *ihead = head;
171 TransData *itail = tail;
172 short connected = t->flag & T_PROP_CONNECTED;
177 while ((tail->dist >= pivot.dist) && (head < tail))
181 while ((tail->rdist >= pivot.rdist) && (head < tail))
192 while ((head->dist <= pivot.dist) && (head < tail))
196 while ((head->rdist <= pivot.rdist) && (head < tail))
209 qsort_trans_data(t, ihead, head-1);
212 qsort_trans_data(t, head+1, itail);
216 void sort_trans_data_dist(TransInfo *t) {
217 TransData *start = t->data;
220 while(i < t->total && start->flag & TD_SELECTED) {
224 qsort_trans_data(t, start, t->data + t->total - 1);
227 static void sort_trans_data(TransInfo *t)
229 TransData *sel, *unsel;
234 while (sel > unsel) {
235 while (unsel->flag & TD_SELECTED) {
241 while (!(sel->flag & TD_SELECTED)) {
255 /* distance calculated from not-selected vertex to nearest selected vertex
256 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
257 static void set_prop_dist(TransInfo *t, short with_dist)
262 for(a=0, tob= t->data; a<t->total; a++, tob++) {
264 tob->rdist= 0.0f; // init, it was mallocced
266 if((tob->flag & TD_SELECTED)==0) {
271 tob->rdist = -1.0f; // signal for next loop
273 for (i = 0, td= t->data; i < t->total; i++, td++) {
274 if(td->flag & TD_SELECTED) {
275 VecSubf(vec, tob->center, td->center);
276 Mat3MulVecfl(tob->mtx, vec);
277 dist = Normalize(vec);
278 if (tob->rdist == -1.0f) {
281 else if (dist < tob->rdist) {
285 else break; // by definition transdata has selected items in beginning
288 tob->dist = tob->rdist;
294 /* ************************** CONVERSIONS ************************* */
296 /* ********************* texture space ********* */
298 static void createTransTexspace(bContext *C, TransInfo *t)
300 Scene *scene = CTX_data_scene(C);
308 if (ob == NULL) { // Shouldn't logically happen, but still...
314 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
320 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
321 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
323 td->flag= TD_SELECTED;
324 VECCOPY(td->center, ob->obmat[3]);
327 Mat3CpyMat4(td->mtx, ob->obmat);
328 Mat3CpyMat4(td->axismtx, ob->obmat);
329 Mat3Ortho(td->axismtx);
330 Mat3Inv(td->smtx, td->mtx);
332 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
333 *texflag &= ~AUTOSPACE;
336 VECCOPY(td->iloc, td->loc);
337 VECCOPY(td->ext->irot, td->ext->rot);
338 VECCOPY(td->ext->isize, td->ext->size);
341 /* ********************* edge (for crease) ***** */
343 static void createTransEdge(bContext *C, TransInfo *t) {
344 #if 0 // TRANSFORM_FIX_ME
345 TransData *td = NULL;
347 float mtx[3][3], smtx[3][3];
348 int count=0, countsel=0;
349 int propmode = t->flag & T_PROP_EDIT;
351 for(eed= em->edges.first; eed; eed= eed->next) {
353 if (eed->f & SELECT) countsel++;
354 if (propmode) count++;
368 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
370 Mat3CpyMat4(mtx, t->obedit->obmat);
373 for(eed= em->edges.first; eed; eed= eed->next) {
374 if(eed->h==0 && (eed->f & SELECT || propmode)) {
375 /* need to set center for center calculations */
376 VecAddf(td->center, eed->v1->co, eed->v2->co);
377 VecMulf(td->center, 0.5f);
381 td->flag= TD_SELECTED;
386 Mat3CpyMat3(td->smtx, smtx);
387 Mat3CpyMat3(td->mtx, mtx);
391 if (t->mode == TFM_BWEIGHT) {
392 td->val = &(eed->bweight);
393 td->ival = eed->bweight;
396 td->val = &(eed->crease);
397 td->ival = eed->crease;
406 /* ********************* pose mode ************* */
408 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
410 bConstraint *con= pchan->constraints.first;
412 for(;con; con= con->next) {
413 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
414 bKinematicConstraint *data= con->data;
418 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
425 static short apply_targetless_ik(Object *ob)
427 bPoseChannel *pchan, *parchan, *chanlist[256];
428 bKinematicConstraint *data;
429 int segcount, apply= 0;
431 /* now we got a difficult situation... we have to find the
432 target-less IK pchans, and apply transformation to the all
433 pchans that were in the chain */
435 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
436 data= has_targetless_ik(pchan);
437 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
439 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
442 /* exclude tip from chain? */
443 if(!(data->flag & CONSTRAINT_IK_TIP))
444 parchan= pchan->parent;
448 /* Find the chain's root & count the segments needed */
449 for (; parchan; parchan=parchan->parent){
450 chanlist[segcount]= parchan;
453 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
455 for(;segcount;segcount--) {
457 float rmat[4][4], tmat[4][4], imat[4][4];
459 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
460 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
461 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
462 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
464 parchan= chanlist[segcount-1];
466 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
468 if(parchan->parent) {
469 Bone *parbone= parchan->parent->bone;
470 float offs_bone[4][4];
472 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
473 Mat4CpyMat3(offs_bone, bone->bone_mat);
475 /* The bone's root offset (is in the parent's coordinate system) */
476 VECCOPY(offs_bone[3], bone->head);
478 /* Get the length translation of parent (length along y axis) */
479 offs_bone[3][1]+= parbone->length;
481 /* pose_mat(b-1) * offs_bone */
482 if(parchan->bone->flag & BONE_HINGE) {
483 /* the rotation of the parent restposition */
484 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
486 /* the location of actual parent transform */
487 VECCOPY(rmat[3], offs_bone[3]);
488 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
489 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
491 Mat4MulMat4(tmat, offs_bone, rmat);
493 else if(parchan->bone->flag & BONE_NO_SCALE) {
494 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
498 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
500 Mat4Invert(imat, tmat);
503 Mat4CpyMat3(tmat, bone->bone_mat);
505 VECCOPY(tmat[3], bone->head);
506 Mat4Invert(imat, tmat);
509 Mat4MulMat4(rmat, parchan->pose_mat, imat);
511 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
513 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
515 Mat3CpyMat4(rmat3, rmat);
518 Mat3ToQuat(rmat3, parchan->quat);
520 /* for size, remove rotation */
521 /* causes problems with some constraints (so apply only if needed) */
522 if (data->flag & CONSTRAINT_IK_STRETCH) {
523 QuatToMat3(parchan->quat, qmat);
525 Mat3MulMat3(smat, rmat3, imat);
526 Mat3ToSize(smat, parchan->size);
529 /* causes problems with some constraints (e.g. childof), so disable this */
530 /* as it is IK shouldn't affect location directly */
531 /* VECCOPY(parchan->loc, rmat[3]); */
537 data->flag &= ~CONSTRAINT_IK_AUTO;
544 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
546 Bone *bone= pchan->bone;
547 float pmat[3][3], omat[3][3];
548 float cmat[3][3], tmat[3][3];
551 VECCOPY(vec, pchan->pose_mat[3]);
552 VECCOPY(td->center, vec);
555 td->flag= TD_SELECTED|TD_USEQUAT;
556 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
558 td->flag |= TD_NOCENTER;
561 if (bone->flag & BONE_TRANSFORM_CHILD)
563 td->flag |= TD_NOCENTER;
564 td->flag |= TD_NO_LOC;
567 td->protectflag= pchan->protectflag;
569 td->loc = pchan->loc;
570 VECCOPY(td->iloc, pchan->loc);
573 td->ext->quat= pchan->quat;
574 td->ext->size= pchan->size;
576 QUATCOPY(td->ext->iquat, pchan->quat);
577 VECCOPY(td->ext->isize, pchan->size);
579 /* proper way to get parent transform + own transform + constraints transform */
580 Mat3CpyMat4(omat, ob->obmat);
583 if(pchan->bone->flag & BONE_HINGE)
584 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
586 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
588 if (constraints_list_needinv(t, &pchan->constraints)) {
589 Mat3CpyMat4(tmat, pchan->constinv);
591 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
594 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
597 if (constraints_list_needinv(t, &pchan->constraints)) {
598 Mat3CpyMat4(tmat, pchan->constinv);
600 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
603 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
606 Mat3Inv(td->smtx, td->mtx);
608 /* for axismat we use bone's own transform */
609 Mat3CpyMat4(pmat, pchan->pose_mat);
610 Mat3MulMat3(td->axismtx, omat, pmat);
611 Mat3Ortho(td->axismtx);
613 if(t->mode==TFM_BONESIZE) {
614 bArmature *arm= t->poseobj->data;
616 if(arm->drawtype==ARM_ENVELOPE) {
618 td->val= &bone->dist;
619 td->ival= bone->dist;
622 // abusive storage of scale in the loc pointer :)
623 td->loc= &bone->xwidth;
624 VECCOPY (td->iloc, td->loc);
629 /* in this case we can do target-less IK grabbing */
630 if(t->mode==TFM_TRANSLATION) {
631 bKinematicConstraint *data= has_targetless_ik(pchan);
633 if(data->flag & CONSTRAINT_IK_TIP) {
634 VECCOPY(data->grabtarget, pchan->pose_tail);
637 VECCOPY(data->grabtarget, pchan->pose_head);
639 td->loc = data->grabtarget;
640 VECCOPY(td->iloc, td->loc);
641 data->flag |= CONSTRAINT_IK_AUTO;
643 /* only object matrix correction */
644 Mat3CpyMat3 (td->mtx, omat);
645 Mat3Inv (td->smtx, td->mtx);
649 /* store reference to first constraint */
650 td->con= pchan->constraints.first;
653 static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
655 Bone *bone= lb->first;
657 for(;bone;bone= bone->next) {
658 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
660 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
662 else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
664 bone->flag |= BONE_TRANSFORM_CHILD;
668 bone->flag &= ~BONE_TRANSFORM;
671 bone_children_clear_transflag(t, &bone->childbase);
675 /* sets transform flags in the bones, returns total */
676 static void set_pose_transflags(TransInfo *t, Object *ob)
678 bArmature *arm= ob->data;
685 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
687 if(bone->layer & arm->layer) {
688 if(bone->flag & BONE_SELECTED)
689 bone->flag |= BONE_TRANSFORM;
691 bone->flag &= ~BONE_TRANSFORM;
693 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
694 bone->flag &= ~BONE_TRANSFORM_CHILD;
698 /* make sure no bone can be transformed when a parent is transformed */
699 /* since pchans are depsgraph sorted, the parents are in beginning of list */
700 if(t->mode!=TFM_BONESIZE) {
701 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
703 if(bone->flag & BONE_TRANSFORM)
704 bone_children_clear_transflag(t, &bone->childbase);
707 /* now count, and check if we have autoIK or have to switch from translate to rotate */
710 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
712 if(bone->flag & BONE_TRANSFORM) {
716 if(t->mode==TFM_TRANSLATION) {
717 if( has_targetless_ik(pchan)==NULL ) {
718 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
719 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
722 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
731 /* if there are no translatable bones, do rotation */
732 if(t->mode==TFM_TRANSLATION && !hastranslation)
733 t->mode= TFM_ROTATION;
737 /* -------- Auto-IK ---------- */
739 /* adjust pose-channel's auto-ik chainlen */
740 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
744 /* don't bother to search if no valid constraints */
745 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
748 /* check if pchan has ik-constraint */
749 for (con= pchan->constraints.first; con; con= con->next) {
750 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
751 bKinematicConstraint *data= con->data;
753 /* only accept if a temporary one (for auto-ik) */
754 if (data->flag & CONSTRAINT_IK_TEMP) {
755 /* chainlen is new chainlen, but is limited by maximum chainlen */
756 if ((chainlen==0) || (chainlen > data->max_rootbone))
757 data->rootbone= data->max_rootbone;
759 data->rootbone= chainlen;
765 /* change the chain-length of auto-ik */
766 void transform_autoik_update (TransInfo *t, short mode)
768 short *chainlen= &G.scene->toolsettings->autoik_chainlen;
771 /* mode determines what change to apply to chainlen */
773 /* mode=1 is from WHEELMOUSEDOWN... increases len */
776 else if (mode == -1) {
777 /* mode==-1 is from WHEELMOUSEUP... decreases len */
778 if (*chainlen > 0) (*chainlen)--;
781 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
782 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
785 /* apply to all pose-channels */
786 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
787 pchan_autoik_adjust(pchan, *chainlen);
791 /* frees temporal IKs */
792 static void pose_grab_with_ik_clear(Object *ob)
794 bKinematicConstraint *data;
796 bConstraint *con, *next;
798 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
799 /* clear all temporary lock flags */
800 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
802 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
803 /* remove all temporary IK-constraints added */
804 for (con= pchan->constraints.first; con; con= next) {
806 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
808 if (data->flag & CONSTRAINT_IK_TEMP) {
809 BLI_remlink(&pchan->constraints, con);
810 MEM_freeN(con->data);
814 pchan->constflag |= PCHAN_HAS_IK;
815 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
816 pchan->constflag |= PCHAN_HAS_TARGET;
822 /* adds the IK to pchan - returns if added */
823 static short pose_grab_with_ik_add(bPoseChannel *pchan)
825 bKinematicConstraint *data;
827 bConstraint *targetless = 0;
833 /* Rule: not if there's already an IK on this channel */
834 for (con= pchan->constraints.first; con; con= con->next) {
835 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
836 bKinematicConstraint *data= con->data;
837 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
839 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
840 if (con->enforce!=0.0) {
841 targetless->flag |= CONSTRAINT_IK_AUTO;
845 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0))
851 //con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
852 BLI_addtail(&pchan->constraints, con);
853 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
855 if (targetless) { /* if exists use values from last targetless IK-constraint as base */
856 *data = *((bKinematicConstraint*)targetless->data);
859 data->flag= CONSTRAINT_IK_TIP;
860 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
861 VECCOPY(data->grabtarget, pchan->pose_tail);
864 /* we include only a connected chain */
865 while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
866 /* here, we set ik-settings for bone from pchan->protectflag */
867 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
868 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
869 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
871 /* now we count this pchan as being included */
873 pchan= pchan->parent;
876 /* make a copy of maximum chain-length */
877 data->max_rootbone= data->rootbone;
882 /* bone is a candidate to get IK, but we don't do it if it has children connected */
883 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
886 short wentdeeper=0, added=0;
888 /* go deeper if children & children are connected */
889 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
890 if (bonec->flag & BONE_CONNECTED) {
892 added+= pose_grab_with_ik_children(pose, bonec);
896 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
898 added+= pose_grab_with_ik_add(pchan);
904 /* main call which adds temporal IK chains */
905 static short pose_grab_with_ik(Object *ob)
908 bPoseChannel *pchan, *parent;
912 if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
917 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
918 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
919 if (pchan->bone->layer & arm->layer) {
920 if (pchan->bone->flag & BONE_SELECTED) {
921 /* Rule: no IK for solitatry (unconnected) bones */
922 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
923 if (bonec->flag & BONE_CONNECTED) {
927 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
930 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
932 /* only adds if there's no IK yet (and no parent bone was selected) */
933 for (parent= pchan->parent; parent; parent= parent->parent) {
934 if (parent->bone->flag & BONE_SELECTED)
938 tot_ik += pose_grab_with_ik_add(pchan);
941 /* rule: go over the children and add IK to the tips */
942 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
948 return (tot_ik) ? 1 : 0;
952 /* only called with pose mode active object now */
953 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
960 TransDataExtension *tdx;
966 /* check validity of state */
967 arm=get_armature (ob);
968 if (arm==NULL || ob->pose==NULL) return;
970 if (arm->flag & ARM_RESTPOS) {
971 if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
972 notice("Pose edit not possible while Rest Position is enabled");
976 if (!(ob->lay & G.vd->lay)) return;
978 /* do we need to add temporal IK chains? */
979 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
980 ik_on= pose_grab_with_ik(ob);
981 if (ik_on) t->flag |= T_AUTOIK;
984 /* set flags and count total (warning, can change transform to rotate) */
985 set_pose_transflags(t, ob);
987 if(t->total==0) return;
990 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
992 /* make sure the lock is set OK, unlock can be accidentally saved? */
993 ob->pose->flag |= POSE_LOCKED;
994 ob->pose->flag &= ~POSE_DO_UNLOCK;
996 /* init trans data */
997 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
998 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
999 for(i=0; i<t->total; i++, td++, tdx++) {
1005 /* use pose channels to fill trans data */
1007 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1008 if(pchan->bone->flag & BONE_TRANSFORM) {
1009 add_pose_transdata(t, pchan, ob, td);
1014 if(td != (t->data+t->total)) printf("Bone selection count error\n");
1016 /* initialise initial auto=ik chainlen's? */
1017 if (ik_on) transform_autoik_update(t, 0);
1021 /* ********************* armature ************** */
1023 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1028 bArmature *arm= t->obedit->data;
1030 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1033 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
1034 if(ebo->layer & arm->layer) {
1035 if (t->mode==TFM_BONESIZE) {
1036 if (ebo->flag & BONE_SELECTED)
1039 else if (t->mode==TFM_BONE_ROLL) {
1040 if (ebo->flag & BONE_SELECTED)
1044 if (ebo->flag & BONE_TIPSEL)
1046 if (ebo->flag & BONE_ROOTSEL)
1052 if (!t->total) return;
1054 Mat3CpyMat4(mtx, t->obedit->obmat);
1057 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1059 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1060 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1062 if(ebo->layer & arm->layer) {
1063 if (t->mode==TFM_BONE_ENVELOPE) {
1065 if (ebo->flag & BONE_ROOTSEL){
1066 td->val= &ebo->rad_head;
1069 VECCOPY (td->center, ebo->head);
1070 td->flag= TD_SELECTED;
1072 Mat3CpyMat3(td->smtx, smtx);
1073 Mat3CpyMat3(td->mtx, mtx);
1081 if (ebo->flag & BONE_TIPSEL){
1082 td->val= &ebo->rad_tail;
1084 VECCOPY (td->center, ebo->tail);
1085 td->flag= TD_SELECTED;
1087 Mat3CpyMat3(td->smtx, smtx);
1088 Mat3CpyMat3(td->mtx, mtx);
1098 else if (t->mode==TFM_BONESIZE) {
1099 if (ebo->flag & BONE_SELECTED) {
1100 if(arm->drawtype==ARM_ENVELOPE) {
1102 td->val= &ebo->dist;
1103 td->ival= ebo->dist;
1106 // abusive storage of scale in the loc pointer :)
1107 td->loc= &ebo->xwidth;
1108 VECCOPY (td->iloc, td->loc);
1111 VECCOPY (td->center, ebo->head);
1112 td->flag= TD_SELECTED;
1114 /* use local bone matrix */
1115 VecSubf(delta, ebo->tail, ebo->head);
1116 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1117 Mat3MulMat3(td->mtx, mtx, bonemat);
1118 Mat3Inv(td->smtx, td->mtx);
1120 Mat3CpyMat3(td->axismtx, td->mtx);
1121 Mat3Ortho(td->axismtx);
1129 else if (t->mode==TFM_BONE_ROLL) {
1130 if (ebo->flag & BONE_SELECTED) {
1132 td->val= &(ebo->roll);
1133 td->ival= ebo->roll;
1135 VECCOPY (td->center, ebo->head);
1136 td->flag= TD_SELECTED;
1145 if (ebo->flag & BONE_TIPSEL){
1146 VECCOPY (td->iloc, ebo->tail);
1147 VECCOPY (td->center, td->iloc);
1149 td->flag= TD_SELECTED;
1150 if (ebo->flag & BONE_EDITMODE_LOCKED)
1151 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1153 Mat3CpyMat3(td->smtx, smtx);
1154 Mat3CpyMat3(td->mtx, mtx);
1156 VecSubf(delta, ebo->tail, ebo->head);
1157 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1159 if ((ebo->flag & BONE_ROOTSEL) == 0)
1170 if (ebo->flag & BONE_ROOTSEL){
1171 VECCOPY (td->iloc, ebo->head);
1172 VECCOPY (td->center, td->iloc);
1174 td->flag= TD_SELECTED;
1175 if (ebo->flag & BONE_EDITMODE_LOCKED)
1176 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1178 Mat3CpyMat3(td->smtx, smtx);
1179 Mat3CpyMat3(td->mtx, mtx);
1181 VecSubf(delta, ebo->tail, ebo->head);
1182 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1184 td->extra = ebo; /* to fix roll */
1198 /* ********************* meta elements ********* */
1200 static void createTransMBallVerts(bContext *C, TransInfo *t)
1206 TransDataExtension *tx;
1207 float mtx[3][3], smtx[3][3];
1208 int count=0, countsel=0;
1209 int propmode = t->flag & T_PROP_EDIT;
1212 for(ml= editelems.first; ml; ml= ml->next) {
1213 if(ml->flag & SELECT) countsel++;
1214 if(propmode) count++;
1217 /* note: in prop mode we need at least 1 selected */
1218 if (countsel==0) return;
1220 if(propmode) t->total = count;
1221 else t->total = countsel;
1223 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1224 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1226 Mat3CpyMat4(mtx, t->obedit->obmat);
1229 for(ml= editelems.first; ml; ml= ml->next) {
1230 if(propmode || (ml->flag & SELECT)) {
1232 VECCOPY(td->iloc, td->loc);
1233 VECCOPY(td->center, td->loc);
1235 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1236 else td->flag= TD_USEQUAT;
1238 Mat3CpyMat3(td->smtx, smtx);
1239 Mat3CpyMat3(td->mtx, mtx);
1244 /* Radius of MetaElem (mass of MetaElem influence) */
1245 if(ml->flag & MB_SCALE_RAD){
1254 /* expx/expy/expz determine "shape" of some MetaElem types */
1255 tx->size = &ml->expx;
1256 tx->isize[0] = ml->expx;
1257 tx->isize[1] = ml->expy;
1258 tx->isize[2] = ml->expz;
1260 /* quat is used for rotation of MetaElem */
1261 tx->quat = ml->quat;
1262 QUATCOPY(tx->iquat, ml->quat);
1273 /* ********************* curve/surface ********* */
1275 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1276 TransData *td, *td_near = NULL;
1277 for (td = head; td<=tail; td++) {
1278 if (td->flag & TD_SELECTED) {
1284 dist = VecLenf(td_near->center, td->center);
1285 if (dist < (td-1)->dist) {
1286 td->dist = (td-1)->dist;
1293 td->dist = MAXFLOAT;
1294 td->flag |= TD_NOTCONNECTED;
1298 for (td = tail; td>=head; td--) {
1299 if (td->flag & TD_SELECTED) {
1305 dist = VecLenf(td_near->center, td->center);
1306 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1307 td->flag &= ~TD_NOTCONNECTED;
1308 if (dist < (td+1)->dist) {
1309 td->dist = (td+1)->dist;
1319 /* Utility function for getting the handle data from bezier's */
1320 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1321 TransDataCurveHandleFlags *hdata;
1322 td->flag |= TD_BEZTRIPLE;
1323 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1324 hdata->ih1 = bezt->h1;
1325 hdata->h1 = &bezt->h1;
1326 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1327 hdata->h2 = &bezt->h2;
1331 static void createTransCurveVerts(bContext *C, TransInfo *t)
1335 TransData *td = NULL;
1339 float mtx[3][3], smtx[3][3];
1341 int count=0, countsel=0;
1342 int propmode = t->flag & T_PROP_EDIT;
1344 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1345 for(nu= editNurb.first; nu; nu= nu->next) {
1346 if((nu->type & 7)==CU_BEZIER) {
1347 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1349 if (G.f & G_HIDDENHANDLES) {
1350 if(bezt->f2 & SELECT) countsel+=3;
1351 if(propmode) count+= 3;
1353 if(bezt->f1 & SELECT) countsel++;
1354 if(bezt->f2 & SELECT) countsel++;
1355 if(bezt->f3 & SELECT) countsel++;
1356 if(propmode) count+= 3;
1362 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1364 if(propmode) count++;
1365 if(bp->f1 & SELECT) countsel++;
1370 /* note: in prop mode we need at least 1 selected */
1371 if (countsel==0) return;
1373 if(propmode) t->total = count;
1374 else t->total = countsel;
1375 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1377 Mat3CpyMat4(mtx, t->obedit->obmat);
1381 for(nu= editNurb.first; nu; nu= nu->next) {
1382 if((nu->type & 7)==CU_BEZIER) {
1383 TransData *head, *tail;
1385 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1387 TransDataCurveHandleFlags *hdata = NULL;
1390 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1391 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1393 VECCOPY(td->iloc, bezt->vec[0]);
1394 td->loc= bezt->vec[0];
1395 VECCOPY(td->center, bezt->vec[1]);
1396 if (G.f & G_HIDDENHANDLES) {
1397 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1400 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1407 hdata = initTransDataCurveHandes(td, bezt);
1409 Mat3CpyMat3(td->smtx, smtx);
1410 Mat3CpyMat3(td->mtx, mtx);
1417 /* This is the Curve Point, the other two are handles */
1418 if(propmode || (bezt->f2 & SELECT)) {
1419 VECCOPY(td->iloc, bezt->vec[1]);
1420 td->loc= bezt->vec[1];
1421 VECCOPY(td->center, td->loc);
1422 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1427 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1428 td->val = &(bezt->radius);
1429 td->ival = bezt->radius;
1430 } else if (t->mode==TFM_TILT) {
1431 td->val = &(bezt->alfa);
1432 td->ival = bezt->alfa;
1437 Mat3CpyMat3(td->smtx, smtx);
1438 Mat3CpyMat3(td->mtx, mtx);
1440 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1441 /* If the middle is selected but the sides arnt, this is needed */
1442 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1443 hdata = initTransDataCurveHandes(td, bezt);
1451 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1452 ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1454 VECCOPY(td->iloc, bezt->vec[2]);
1455 td->loc= bezt->vec[2];
1456 VECCOPY(td->center, bezt->vec[1]);
1457 if (G.f & G_HIDDENHANDLES) {
1458 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1461 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1468 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1469 hdata = initTransDataCurveHandes(td, bezt);
1472 Mat3CpyMat3(td->smtx, smtx);
1473 Mat3CpyMat3(td->mtx, mtx);
1480 else if (propmode && head != tail) {
1481 calc_distanceCurveVerts(head, tail-1);
1485 if (propmode && head != tail)
1486 calc_distanceCurveVerts(head, tail-1);
1488 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1489 * but for now just dont change handle types */
1490 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1491 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1494 TransData *head, *tail;
1496 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1498 if(propmode || (bp->f1 & SELECT)) {
1499 VECCOPY(td->iloc, bp->vec);
1501 VECCOPY(td->center, td->loc);
1502 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1507 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1508 td->val = &(bp->radius);
1509 td->ival = bp->radius;
1511 td->val = &(bp->alfa);
1512 td->ival = bp->alfa;
1515 Mat3CpyMat3(td->smtx, smtx);
1516 Mat3CpyMat3(td->mtx, mtx);
1523 else if (propmode && head != tail) {
1524 calc_distanceCurveVerts(head, tail-1);
1528 if (propmode && head != tail)
1529 calc_distanceCurveVerts(head, tail-1);
1535 /* ********************* lattice *************** */
1537 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1541 TransData *td = NULL;
1543 float mtx[3][3], smtx[3][3];
1545 int count=0, countsel=0;
1546 int propmode = t->flag & T_PROP_EDIT;
1549 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1552 if(bp->f1 & SELECT) countsel++;
1553 if(propmode) count++;
1558 /* note: in prop mode we need at least 1 selected */
1559 if (countsel==0) return;
1561 if(propmode) t->total = count;
1562 else t->total = countsel;
1563 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1565 Mat3CpyMat4(mtx, t->obedit->obmat);
1570 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1572 if(propmode || (bp->f1 & SELECT)) {
1574 VECCOPY(td->iloc, bp->vec);
1576 VECCOPY(td->center, td->loc);
1577 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1579 Mat3CpyMat3(td->smtx, smtx);
1580 Mat3CpyMat3(td->mtx, mtx);
1595 /* ******************* particle edit **************** */
1596 static void createTransParticleVerts(bContext *C, TransInfo *t)
1600 TransData *td = NULL;
1601 TransDataExtension *tx;
1602 Base *base = BASACT;
1604 ParticleSystem *psys = PE_get_current(ob);
1605 ParticleSystemModifierData *psmd = NULL;
1606 ParticleEditSettings *pset = PE_settings();
1607 ParticleData *pa = NULL;
1609 ParticleEditKey *key;
1611 int i,k, totpart, transformparticle;
1612 int count = 0, hasselected = 0;
1613 int propmode = t->flag & T_PROP_EDIT;
1615 if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1617 psmd = psys_get_modifier(ob,psys);
1620 totpart = psys->totpart;
1621 base->flag |= BA_HAS_RECALC_DATA;
1623 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1624 pa->flag &= ~PARS_TRANSFORM;
1625 transformparticle= 0;
1627 if((pa->flag & PARS_HIDE)==0) {
1628 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1629 if((key->flag&PEK_HIDE)==0) {
1630 if(key->flag&PEK_SELECT) {
1632 transformparticle= 1;
1635 transformparticle= 1;
1640 if(transformparticle) {
1641 count += pa->totkey;
1642 pa->flag |= PARS_TRANSFORM;
1646 /* note: in prop mode we need at least 1 selected */
1647 if (hasselected==0) return;
1650 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1652 if(t->mode == TFM_BAKE_TIME)
1653 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1659 Mat4Invert(ob->imat,ob->obmat);
1661 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1662 TransData *head, *tail;
1665 if(!(pa->flag & PARS_TRANSFORM)) continue;
1667 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1669 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1670 VECCOPY(key->world_co, key->co);
1671 Mat4MulVecfl(mat, key->world_co);
1672 td->loc = key->world_co;
1674 VECCOPY(td->iloc, td->loc);
1675 VECCOPY(td->center, td->loc);
1677 if(key->flag & PEK_SELECT)
1678 td->flag |= TD_SELECTED;
1680 td->flag |= TD_SKIP;
1685 /* don't allow moving roots */
1686 if(k==0 && pset->flag & PE_LOCK_FIRST)
1687 td->protectflag |= OB_LOCK_LOC;
1692 if(t->mode == TFM_BAKE_TIME) {
1693 td->val = key->time;
1694 td->ival = *(key->time);
1695 /* abuse size and quat for min/max values */
1696 td->flag |= TD_NO_EXT;
1697 if(k==0) tx->size = 0;
1698 else tx->size = (key - 1)->time;
1700 if(k == pa->totkey - 1) tx->quat = 0;
1701 else tx->quat = (key + 1)->time;
1709 if (propmode && head != tail)
1710 calc_distanceCurveVerts(head, tail - 1);
1715 void flushTransParticles(TransInfo *t)
1717 #if 0 // TRANSFORM_FIX_ME
1718 Scene *scene = t->scene;
1720 ParticleSystem *psys = PE_get_current(ob);
1721 ParticleSystemModifierData *psmd;
1723 ParticleEditKey *key;
1725 float mat[4][4], imat[4][4], co[3];
1726 int i, k, propmode = t->flag & T_PROP_EDIT;
1728 psmd = psys_get_modifier(ob, psys);
1730 /* we do transform in world space, so flush world space position
1731 * back to particle local space */
1733 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1734 if(!(pa->flag & PARS_TRANSFORM)) continue;
1736 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1737 Mat4Invert(imat,mat);
1739 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1740 VECCOPY(co, key->world_co);
1741 Mat4MulVecfl(imat, co);
1743 /* optimization for proportional edit */
1744 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1745 VECCOPY(key->co, co);
1746 pa->flag |= PARS_EDIT_RECALC;
1751 PE_update_object(OBACT, 1);
1755 /* ********************* mesh ****************** */
1757 /* proportional distance based on connectivity */
1758 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1759 #define E_NEAR(a) (nears[((a)->tmp.l)])
1760 #define THRESHOLD 0.0001f
1761 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1767 /* f2 flag is used for 'selection' */
1768 /* tmp.l is offset on scratch array */
1769 for(eve= em->verts.first; eve; eve= eve->next) {
1773 if(eve->f & SELECT) {
1776 E_VEC(eve)[0] = 0.0f;
1777 E_VEC(eve)[1] = 0.0f;
1778 E_VEC(eve)[2] = 0.0f;
1787 /* Floodfill routine */
1789 At worst this is n*n of complexity where n is number of edges
1790 Best case would be n if the list is ordered perfectly.
1791 Estimate is n log n in average (so not too bad)
1796 for(eed= em->edges.first; eed; eed= eed->next) {
1798 EditVert *v1= eed->v1, *v2= eed->v2;
1799 float *vec2 = E_VEC(v2);
1800 float *vec1 = E_VEC(v1);
1802 if (v1->f2 + v2->f2 == 4)
1808 float len1 = VecLength(vec1);
1809 float len2 = VecLength(vec2);
1811 /* for v2 if not selected */
1813 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1814 lenn = VecLength(nvec);
1816 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1817 VECCOPY(vec2, nvec);
1818 E_NEAR(v2) = E_NEAR(v1);
1822 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1823 VECCOPY(vec2, vec1);
1824 E_NEAR(v2) = E_NEAR(v1);
1828 /* for v1 if not selected */
1830 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1831 lenn = VecLength(nvec);
1833 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1834 VECCOPY(vec1, nvec);
1835 E_NEAR(v1) = E_NEAR(v2);
1839 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1840 VECCOPY(vec1, vec2);
1841 E_NEAR(v1) = E_NEAR(v2);
1848 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1850 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1851 VECCOPY(vec2, vec1);
1853 E_NEAR(v2) = E_NEAR(v1);
1859 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1861 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1862 VECCOPY(vec1, vec2);
1864 E_NEAR(v1) = E_NEAR(v2);
1872 /* loop-in-a-loop I know, but we need it! (ton) */
1873 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
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(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1892 // td->loc = key->co;
1896 VECCOPY(td->center, td->loc);
1897 if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1898 get_face_center(td->center, em, eve);
1899 VECCOPY(td->iloc, td->loc);
1902 VECCOPY(td->axismtx[2], eve->no);
1908 td->axismtx[1][2] = 0.0f;
1914 if (t->mode == TFM_BWEIGHT) {
1915 td->val = &(eve->bweight);
1916 td->ival = eve->bweight;
1921 td->verse = (void*)eve->vvert;
1922 td->flag |= TD_VERSE_VERT;
1925 td->flag &= ~TD_VERSE_VERT;
1929 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1931 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1933 float *vec = userData;
1939 static int modifiers_disable_subsurf_temporary(Object *ob)
1944 for(md=ob->modifiers.first; md; md=md->next)
1945 if(md->type==eModifierType_Subsurf)
1946 if(md->mode & eModifierMode_OnCage) {
1947 md->mode ^= eModifierMode_DisableTemporary;
1954 /* disable subsurf temporal, get mapped cos, and enable it */
1955 static float *get_crazy_mapped_editverts(TransInfo *t)
1957 Mesh *me= t->obedit->data;
1961 /* disable subsurf temporal, get mapped cos, and enable it */
1962 if(modifiers_disable_subsurf_temporary(t->obedit)) {
1963 /* need to make new derivemesh */
1964 makeDerivedMesh(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1967 /* now get the cage */
1968 dm= editmesh_get_derived_cage(t->obedit, me->edit_mesh, 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(t->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(EditMesh *em, float *origcos, float *mappedcos, float *quats)
2001 EditVert *eve, *prev;
2003 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2006 /* two abused locations in vertices */
2007 for(eve= em->verts.first; eve; eve= eve->next, index++) {
2009 eve->prev= (EditVert *)index;
2012 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2013 for(efa= em->faces.first; efa; efa= efa->next) {
2015 /* retrieve mapped coordinates */
2016 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2017 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2018 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2020 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2021 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2022 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2024 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2025 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2026 efa->v2->tmp.p= (void*)quats;
2031 v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2032 co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2034 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2035 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2036 efa->v1->tmp.p= (void*)quats;
2039 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2040 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2041 efa->v3->tmp.p= (void*)quats;
2044 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2045 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2046 efa->v4->tmp.p= (void*)quats;
2051 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2052 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2053 efa->v1->tmp.p= (void*)quats;
2056 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2057 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2058 efa->v3->tmp.p= (void*)quats;
2064 /* restore abused prev pointer */
2065 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2070 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2076 tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2078 for (i=0,v=bm->verts.first;v;v=v->next) {
2079 if ( (vtd = BME_get_transdata(td,v)) ) {
2080 tob->loc = vtd->loc;
2081 tob->val = &vtd->factor;
2082 VECCOPY(tob->iloc,vtd->co);
2083 VECCOPY(tob->center,vtd->org);
2084 VECCOPY(tob->axismtx[0],vtd->vec);
2085 tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2090 /* since td is a memarena, it can hold more transdata than actual elements
2091 * (i.e. we can't depend on td->len to determine the number of actual elements) */
2095 static void createTransEditVerts(bContext *C, TransInfo *t)
2097 Scene *scene = CTX_data_scene(C);
2098 TransData *tob = NULL;
2099 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2101 EditVert **nears = NULL;
2102 EditVert *eve_act = NULL;
2103 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2104 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2105 int count=0, countsel=0, a, totleft;
2106 int propmode = t->flag & T_PROP_EDIT;
2109 if ((t->options & CTX_NO_MIRROR) == 0 && (scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2114 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2115 if(scene->selectmode & SCE_SELECT_VERTEX) {
2116 for(eve= em->verts.first; eve; eve= eve->next) {
2117 if(eve->h==0 && (eve->f & SELECT))
2123 else if(scene->selectmode & SCE_SELECT_EDGE) {
2125 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2126 for(eed= em->edges.first; eed; eed= eed->next) {
2127 if(eed->h==0 && (eed->f & SELECT))
2128 eed->v1->f1= eed->v2->f1= SELECT;
2133 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2134 for(efa= em->faces.first; efa; efa= efa->next) {
2135 if(efa->h==0 && (efa->f & SELECT)) {
2136 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2137 if(efa->v4) efa->v4->f1= SELECT;
2142 /* now we can count */
2143 for(eve= em->verts.first; eve; eve= eve->next) {
2145 if(eve->f1) countsel++;
2146 if(propmode) count++;
2150 /* note: in prop mode we need at least 1 selected */
2151 if (countsel==0) return;
2154 if (em->selected.last) {
2155 EditSelection *ese = em->selected.last;
2156 if ( ese->type == EDITVERT ) {
2157 eve_act = (EditVert *)ese->data;
2165 /* allocating scratch arrays */
2166 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2167 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2169 else t->total = countsel;
2170 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2172 Mat3CpyMat4(mtx, t->obedit->obmat);
2175 if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2177 /* detect CrazySpace [tm] */
2179 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2180 if(modifiers_isDeformed(t->obedit)) {
2181 /* check if we can use deform matrices for modifier from the
2182 start up to stack, they are more accurate than quats */
2183 totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
2185 /* if we still have more modifiers, also do crazyspace
2186 correction with quats, relative to the coordinates after
2187 the modifiers that support deform matrices (defcos) */
2189 mappedcos= get_crazy_mapped_editverts(t);
2190 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2191 set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2193 MEM_freeN(mappedcos);
2202 /* find out which half we do */
2204 for (eve=em->verts.first; eve; eve=eve->next) {
2205 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2213 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2215 if(propmode || eve->f1) {
2216 VertsToTransData(t, tob, em, eve);
2219 if(eve->f1) tob->flag |= TD_SELECTED;
2222 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2227 VECCOPY(vec, E_VEC(eve));
2228 Mat3MulVecfl(mtx, vec);
2229 tob->dist= VecLength(vec);
2232 tob->flag |= TD_NOTCONNECTED;
2233 tob->dist = MAXFLOAT;
2238 if(defmats || (quats && eve->tmp.p)) {
2239 float mat[3][3], imat[3][3], qmat[3][3];
2241 /* use both or either quat and defmat correction */
2242 if(quats && eve->tmp.f) {
2243 QuatToMat3(eve->tmp.p, qmat);
2246 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2247 NULL, NULL, NULL, NULL, NULL);
2249 Mat3MulMat3(mat, mtx, qmat);
2252 Mat3MulMat3(mat, mtx, defmats[a]);
2256 Mat3CpyMat3(tob->smtx, imat);
2257 Mat3CpyMat3(tob->mtx, mat);
2260 Mat3CpyMat3(tob->smtx, smtx);
2261 Mat3CpyMat3(tob->mtx, mtx);
2265 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2266 EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */
2267 if(vmir != eve) tob->extra = vmir;
2277 /* crazy space free */
2284 /* ********************* UV ****************** */
2286 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2290 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2292 /* uv coords are scaled by aspects. this is needed for rotations and
2293 proportional editing to be consistent with the stretchted uv coords
2294 that are displayed. this also means that for display and numinput,
2295 and when the the uv coords are flushed, these are converted each time */
2296 td2d->loc[0] = uv[0]*aspx;
2297 td2d->loc[1] = uv[1]*aspy;
2298 td2d->loc[2] = 0.0f;
2302 td->loc = td2d->loc;
2303 VECCOPY(td->center, td->loc);
2304 VECCOPY(td->iloc, td->loc);
2306 memset(td->axismtx, 0, sizeof(td->axismtx));
2307 td->axismtx[2][2] = 1.0f;
2309 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2312 td->flag |= TD_SELECTED;
2322 static void createTransUVs(bContext *C, TransInfo *t)
2326 TransData *td = NULL;
2327 TransData2D *td2d = NULL;
2329 int count=0, countsel=0;
2330 int propmode = t->flag & T_PROP_EDIT;
2331 int efa_s1,efa_s2,efa_s3,efa_s4;
2333 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2336 if(is_uv_tface_editing_allowed()==0) return;
2339 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2340 for (efa= em->faces.first; efa; efa= efa->next) {
2341 /* store face pointer for second loop, prevent second lookup */
2342 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2343 if (simaFaceDraw_Check(efa, tf)) {
2346 efa_s1 = simaUVSel_Check(efa, tf, 0);
2347 efa_s2 = simaUVSel_Check(efa, tf, 1);
2348 efa_s3 = simaUVSel_Check(efa, tf, 2);
2350 efa_s4 = simaUVSel_Check(efa, tf, 3);
2351 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2352 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2355 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2356 if (efa_s1) countsel++;
2357 if (efa_s2) countsel++;
2358 if (efa_s3) countsel++;
2365 for (efa= em->faces.first; efa; efa= efa->next) {
2366 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2367 if (simaFaceDraw_Check(efa, tf)) {
2370 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2371 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2372 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2373 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2375 count += (efa->v4)? 4: 3;
2382 /* note: in prop mode we need at least 1 selected */
2383 if (countsel==0) return;
2385 t->total= (propmode)? count: countsel;
2386 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2387 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2388 treated just as if they were 3d verts */
2389 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2391 if(G.sima->flag & SI_CLIP_UV)
2392 t->flag |= T_CLIP_UV;
2397 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2398 for (efa= em->faces.first; efa; efa= efa->next) {
2399 tf=(MTFace *)efa->tmp.p;
2401 efa_s1 = simaUVSel_Check(efa, tf, 0);
2402 efa_s2 = simaUVSel_Check(efa, tf, 1);
2403 efa_s3 = simaUVSel_Check(efa, tf, 2);
2406 efa_s4 = simaUVSel_Check(efa, tf, 3);
2408 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2409 /* all corners of this quad need their edges moved. so we must store TD for each */
2411 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2412 if (!efa_s1) td->flag |= TD_SKIP;
2415 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2416 if (!efa_s2) td->flag |= TD_SKIP;
2419 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2420 if (!efa_s3) td->flag |= TD_SKIP;
2423 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2424 if (!efa_s4) td->flag |= TD_SKIP;
2428 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2429 if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2430 if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2431 if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2436 for (efa= em->faces.first; efa; efa= efa->next) {
2437 /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2438 if (simaFaceDraw_Check(efa, tf)) {*/
2439 if ((tf=(MTFace *)efa->tmp.p)) {
2441 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2442 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2443 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2445 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2447 if(simaUVSel_Check(efa, tf, 0)) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2448 if(simaUVSel_Check(efa, tf, 1)) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2449 if(simaUVSel_Check(efa, tf, 2)) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2450 if(efa->v4 && simaUVSel_Check(efa, tf, 3)) UVsToTransData(td++, td2d++, tf->uv[3], 1);
2456 if (G.sima->flag & SI_LIVE_UNWRAP)
2457 unwrap_lscm_live_begin();
2461 void flushTransUVs(TransInfo *t)
2463 #if 0 // TRANSFORM_FIX_ME
2465 int a, width, height;
2467 EditMesh *em = ((Mesh *)ob->data)->edit_mesh;
2468 float aspx, aspy, invx, invy;
2470 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2471 transform_width_height_tface_uv(&width, &height);
2475 /* flush to 2d vector from internally used 3d vector */
2476 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2477 td->loc2d[0]= td->loc[0]*invx;
2478 td->loc2d[1]= td->loc[1]*invy;
2480 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2481 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2482 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2486 if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL))
2487 be_square_tface_uv(em);
2489 /* this is overkill if G.sima->lock is not set, but still needed */
2490 object_uvs_changed(ob);
2494 int clipUVTransform(TransInfo *t, float *vec, int resize)
2496 #if 0 // TRANSFORM_FIX_ME
2498 int a, clipx=1, clipy=1;
2499 float aspx, aspy, min[2], max[2];
2501 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2502 min[0]= min[1]= 0.0f;
2503 max[0]= aspx; max[1]= aspy;
2505 for(a=0, td= t->data; a<t->total; a++, td++) {
2506 DO_MINMAX2(td->loc, min, max);
2510 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2511 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2512 else if(max[0] > aspx && t->center[0] < aspx)
2513 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2517 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2518 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2519 else if(max[1] > aspy && t->center[1] < aspy)
2520 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2527 else if(max[0] > aspx)
2528 vec[0] -= max[0]-aspx;
2534 else if(max[1] > aspy)
2535 vec[1] -= max[1]-aspy;
2540 return (clipx || clipy);
2545 /* ********************* IPO EDITOR ************************* */
2547 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2548 * due to bad globals that would need to be imported specially for this
2550 static void createTransIpoData(bContext *C, TransInfo *t)
2554 /* in editipo.c due to some globals that are defined in that file... */
2555 make_ipo_transdata(t);
2559 /* this function is called on recalcData to apply the transforms applied
2560 * to the transdata on to the actual keyframe data
2562 void flushTransIpoData(TransInfo *t)
2564 #if 0 // TRANSFORM_FIX_ME
2568 /* flush to 2d vector from internally used 3d vector */
2569 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2570 // FIXME: autosnap needs to be here...
2572 /* we need to unapply the nla-scaling from the time in some situations */
2574 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2576 td->loc2d[0]= td->loc[0];
2578 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2579 if ((t->data[a].flag & TD_TIMEONLY)==0)
2580 td->loc2d[1]= td->loc[1];
2585 /* ********************* ACTION/NLA EDITOR ****************** */
2587 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2588 * any other gp-frames which may reside on that frame (that are not selected).
2589 * It also makes sure gp-frames are still stored in chronological order after
2592 static void posttrans_gpd_clean (bGPdata *gpd)
2596 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2597 ListBase sel_buffer = {NULL, NULL};
2598 bGPDframe *gpf, *gpfn;
2599 bGPDframe *gfs, *gfsn;
2601 /* loop 1: loop through and isolate selected gp-frames to buffer
2602 * (these need to be sorted as they are isolated)
2604 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2608 if (gpf->flag & GP_FRAME_SELECT) {
2609 BLI_remlink(&gpl->frames, gpf);
2611 /* find place to add them in buffer
2612 * - go backwards as most frames will still be in order,
2613 * so doing it this way will be faster
2615 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2616 /* if current (gpf) occurs after this one in buffer, add! */
2617 if (gfs->framenum < gpf->framenum) {
2618 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2624 BLI_addhead(&sel_buffer, gpf);
2628 /* error checking: it is unlikely, but may be possible to have none selected */
2629 if (sel_buffer.first == NULL)
2632 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2633 if (gpl->frames.first == NULL) {
2634 gpl->frames.first= sel_buffer.first;
2635 gpl->frames.last= sel_buffer.last;
2640 /* loop 2: remove duplicates of frames in buffers */
2641 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2644 /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2645 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2648 /* if this buffer frame needs to go before current, add it! */
2649 if (gfs->framenum < gpf->framenum) {
2650 /* transfer buffer frame to frames list (before current) */
2651 BLI_remlink(&sel_buffer, gfs);
2652 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2654 /* if this buffer frame is on same frame, replace current with it and stop */
2655 else 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 /* get rid of current frame */
2662 //gpencil_layer_delframe(gpl, gpf);
2667 /* if anything is still in buffer, append to end */
2668 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2671 BLI_remlink(&sel_buffer, gfs);
2672 BLI_addtail(&gpl->frames, gfs);
2677 /* Called by special_aftertrans_update to make sure selected keyframes replace
2678 * any other keyframes which may reside on that frame (that is not selected).
2680 static void posttrans_ipo_clean (Ipo *ipo)
2685 /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
2686 for (icu= ipo->curve.first; icu; icu= icu->next) {
2687 float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2688 int len, index; /* number of frames in cache, item index */
2690 /* allocate memory for the cache */
2691 // TODO: investigate using GHash for this instead?
2692 if (icu->totvert == 0)
2694 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2698 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
2699 * as there is no guarantee what order the keyframes are exactly, even though
2700 * they have been sorted by time.
2703 /* Loop 1: find selected keyframes */
2704 for (i = 0; i < icu->totvert; i++) {
2705 BezTriple *bezt= &icu->bezt[i];
2707 if (BEZSELECTED(bezt)) {
2708 selcache[index]= bezt->vec[1][0];
2714 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2716 for (i = 0; i < icu->totvert; i++) {
2717 BezTriple *bezt= &icu->bezt[i];
2719 if (BEZSELECTED(bezt) == 0) {
2720 /* check beztriple should be removed according to cache */
2721 for (index= 0; index < len; index++) {
2722 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2723 delete_icu_key(icu, i, 0);
2726 else if (bezt->vec[1][0] > selcache[index])
2732 testhandles_ipocurve(icu);
2736 MEM_freeN(selcache);
2740 /* Called by special_aftertrans_update to make sure selected keyframes replace
2741 * any other keyframes which may reside on that frame (that is not selected).
2742 * remake_action_ipos should have already been called
2744 static void posttrans_action_clean (bAnimContext *ac, bAction *act)
2746 ListBase anim_data = {NULL, NULL};
2751 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
2752 ANIM_animdata_filter(&anim_data, filter, act, ANIMCONT_ACTION);
2754 /* loop through relevant data, removing keyframes from the ipo-blocks that were attached
2755 * - all keyframes are converted in/out of global time