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);
164 /* ************************** Functions *************************** */
166 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
167 TransData pivot = *head;
168 TransData *ihead = head;
169 TransData *itail = tail;
170 short connected = t->flag & T_PROP_CONNECTED;
175 while ((tail->dist >= pivot.dist) && (head < tail))
179 while ((tail->rdist >= pivot.rdist) && (head < tail))
190 while ((head->dist <= pivot.dist) && (head < tail))
194 while ((head->rdist <= pivot.rdist) && (head < tail))
207 qsort_trans_data(t, ihead, head-1);
210 qsort_trans_data(t, head+1, itail);
214 void sort_trans_data_dist(TransInfo *t) {
215 TransData *start = t->data;
218 while(i < t->total && start->flag & TD_SELECTED) {
222 qsort_trans_data(t, start, t->data + t->total - 1);
225 static void sort_trans_data(TransInfo *t)
227 TransData *sel, *unsel;
232 while (sel > unsel) {
233 while (unsel->flag & TD_SELECTED) {
239 while (!(sel->flag & TD_SELECTED)) {
253 /* distance calculated from not-selected vertex to nearest selected vertex
254 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
255 static void set_prop_dist(TransInfo *t, short with_dist)
260 for(a=0, tob= t->data; a<t->total; a++, tob++) {
262 tob->rdist= 0.0f; // init, it was mallocced
264 if((tob->flag & TD_SELECTED)==0) {
269 tob->rdist = -1.0f; // signal for next loop
271 for (i = 0, td= t->data; i < t->total; i++, td++) {
272 if(td->flag & TD_SELECTED) {
273 VecSubf(vec, tob->center, td->center);
274 Mat3MulVecfl(tob->mtx, vec);
275 dist = Normalize(vec);
276 if (tob->rdist == -1.0f) {
279 else if (dist < tob->rdist) {
283 else break; // by definition transdata has selected items in beginning
286 tob->dist = tob->rdist;
292 /* ************************** CONVERSIONS ************************* */
294 /* ********************* texture space ********* */
296 static void createTransTexspace(bContext *C, TransInfo *t)
298 Scene *scene = CTX_data_scene(C);
306 if (ob == NULL) { // Shouldn't logically happen, but still...
312 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
318 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
319 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
321 td->flag= TD_SELECTED;
322 VECCOPY(td->center, ob->obmat[3]);
325 Mat3CpyMat4(td->mtx, ob->obmat);
326 Mat3CpyMat4(td->axismtx, ob->obmat);
327 Mat3Ortho(td->axismtx);
328 Mat3Inv(td->smtx, td->mtx);
330 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
331 *texflag &= ~AUTOSPACE;
334 VECCOPY(td->iloc, td->loc);
335 VECCOPY(td->ext->irot, td->ext->rot);
336 VECCOPY(td->ext->isize, td->ext->size);
339 /* ********************* edge (for crease) ***** */
341 static void createTransEdge(bContext *C, TransInfo *t) {
342 #if 0 // TRANSFORM_FIX_ME
343 TransData *td = NULL;
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, t->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= t->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, t->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, t->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, t->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, t->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(EditMesh *em, int total, float *vectors, EditVert **nears)
1765 /* f2 flag is used for 'selection' */
1766 /* tmp.l is offset on scratch array */
1767 for(eve= em->verts.first; eve; eve= eve->next) {
1771 if(eve->f & SELECT) {
1774 E_VEC(eve)[0] = 0.0f;
1775 E_VEC(eve)[1] = 0.0f;
1776 E_VEC(eve)[2] = 0.0f;
1785 /* Floodfill routine */
1787 At worst this is n*n of complexity where n is number of edges
1788 Best case would be n if the list is ordered perfectly.
1789 Estimate is n log n in average (so not too bad)
1794 for(eed= em->edges.first; eed; eed= eed->next) {
1796 EditVert *v1= eed->v1, *v2= eed->v2;
1797 float *vec2 = E_VEC(v2);
1798 float *vec1 = E_VEC(v1);
1800 if (v1->f2 + v2->f2 == 4)
1806 float len1 = VecLength(vec1);
1807 float len2 = VecLength(vec2);
1809 /* for v2 if not selected */
1811 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1812 lenn = VecLength(nvec);
1814 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1815 VECCOPY(vec2, nvec);
1816 E_NEAR(v2) = E_NEAR(v1);
1820 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1821 VECCOPY(vec2, vec1);
1822 E_NEAR(v2) = E_NEAR(v1);
1826 /* for v1 if not selected */
1828 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1829 lenn = VecLength(nvec);
1831 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1832 VECCOPY(vec1, nvec);
1833 E_NEAR(v1) = E_NEAR(v2);
1837 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1838 VECCOPY(vec1, vec2);
1839 E_NEAR(v1) = E_NEAR(v2);
1846 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1848 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1849 VECCOPY(vec2, vec1);
1851 E_NEAR(v2) = E_NEAR(v1);
1857 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1859 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1860 VECCOPY(vec1, vec2);
1862 E_NEAR(v1) = E_NEAR(v2);
1870 /* loop-in-a-loop I know, but we need it! (ton) */
1871 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1875 for(efa= em->faces.first; efa; efa= efa->next)
1877 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1880 VECCOPY(cent, efa->cent);
1884 //way to overwrite what data is edited with transform
1885 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1886 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1890 // td->loc = key->co;
1894 VECCOPY(td->center, td->loc);
1895 if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1896 get_face_center(td->center, em, eve);
1897 VECCOPY(td->iloc, td->loc);
1900 VECCOPY(td->axismtx[2], eve->no);
1906 td->axismtx[1][2] = 0.0f;
1912 if (t->mode == TFM_BWEIGHT) {
1913 td->val = &(eve->bweight);
1914 td->ival = eve->bweight;
1919 td->verse = (void*)eve->vvert;
1920 td->flag |= TD_VERSE_VERT;
1923 td->flag &= ~TD_VERSE_VERT;
1927 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1929 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1931 float *vec = userData;
1937 static int modifiers_disable_subsurf_temporary(Object *ob)
1942 for(md=ob->modifiers.first; md; md=md->next)
1943 if(md->type==eModifierType_Subsurf)
1944 if(md->mode & eModifierMode_OnCage) {
1945 md->mode ^= eModifierMode_DisableTemporary;
1952 /* disable subsurf temporal, get mapped cos, and enable it */
1953 static float *get_crazy_mapped_editverts(TransInfo *t)
1955 Mesh *me= t->obedit->data;
1959 /* disable subsurf temporal, get mapped cos, and enable it */
1960 if(modifiers_disable_subsurf_temporary(t->obedit)) {
1961 /* need to make new derivemesh */
1962 makeDerivedMesh(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1965 /* now get the cage */
1966 dm= editmesh_get_derived_cage(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1968 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1969 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1973 /* set back the flag, no new cage needs to be built, transform does it */
1974 modifiers_disable_subsurf_temporary(t->obedit);
1979 #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])
1980 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1982 float vecu[3], vecv[3];
1985 TAN_MAKE_VEC(vecu, v1, v2);
1986 TAN_MAKE_VEC(vecv, v1, v3);
1987 triatoquat(v1, vecu, vecv, q1);
1989 TAN_MAKE_VEC(vecu, def1, def2);
1990 TAN_MAKE_VEC(vecv, def1, def3);
1991 triatoquat(def1, vecu, vecv, q2);
1993 QuatSub(quat, q2, q1);
1997 static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
1999 EditVert *eve, *prev;
2001 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2004 /* two abused locations in vertices */
2005 for(eve= em->verts.first; eve; eve= eve->next, index++) {
2007 eve->prev= (EditVert *)index;
2010 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2011 for(efa= em->faces.first; efa; efa= efa->next) {
2013 /* retrieve mapped coordinates */
2014 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2015 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2016 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2018 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2019 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2020 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2022 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2023 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2024 efa->v2->tmp.p= (void*)quats;
2029 v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2030 co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2032 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2033 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2034 efa->v1->tmp.p= (void*)quats;
2037 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2038 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2039 efa->v3->tmp.p= (void*)quats;
2042 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2043 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2044 efa->v4->tmp.p= (void*)quats;
2049 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2050 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2051 efa->v1->tmp.p= (void*)quats;
2054 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2055 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2056 efa->v3->tmp.p= (void*)quats;
2062 /* restore abused prev pointer */
2063 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2068 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2074 tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2076 for (i=0,v=bm->verts.first;v;v=v->next) {
2077 if ( (vtd = BME_get_transdata(td,v)) ) {
2078 tob->loc = vtd->loc;
2079 tob->val = &vtd->factor;
2080 VECCOPY(tob->iloc,vtd->co);
2081 VECCOPY(tob->center,vtd->org);
2082 VECCOPY(tob->axismtx[0],vtd->vec);
2083 tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2088 /* since td is a memarena, it can hold more transdata than actual elements
2089 * (i.e. we can't depend on td->len to determine the number of actual elements) */
2093 static void createTransEditVerts(bContext *C, TransInfo *t)
2095 Scene *scene = CTX_data_scene(C);
2096 TransData *tob = NULL;
2097 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2099 EditVert **nears = NULL;
2100 EditVert *eve_act = NULL;
2101 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2102 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2103 int count=0, countsel=0, a, totleft;
2104 int propmode = t->flag & T_PROP_EDIT;
2107 if ((t->options & CTX_NO_MIRROR) == 0 && (scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2112 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2113 if(scene->selectmode & SCE_SELECT_VERTEX) {
2114 for(eve= em->verts.first; eve; eve= eve->next) {
2115 if(eve->h==0 && (eve->f & SELECT))
2121 else if(scene->selectmode & SCE_SELECT_EDGE) {
2123 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2124 for(eed= em->edges.first; eed; eed= eed->next) {
2125 if(eed->h==0 && (eed->f & SELECT))
2126 eed->v1->f1= eed->v2->f1= SELECT;
2131 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2132 for(efa= em->faces.first; efa; efa= efa->next) {
2133 if(efa->h==0 && (efa->f & SELECT)) {
2134 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2135 if(efa->v4) efa->v4->f1= SELECT;
2140 /* now we can count */
2141 for(eve= em->verts.first; eve; eve= eve->next) {
2143 if(eve->f1) countsel++;
2144 if(propmode) count++;
2148 /* note: in prop mode we need at least 1 selected */
2149 if (countsel==0) return;
2152 if (em->selected.last) {
2153 EditSelection *ese = em->selected.last;
2154 if ( ese->type == EDITVERT ) {
2155 eve_act = (EditVert *)ese->data;
2163 /* allocating scratch arrays */
2164 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2165 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2167 else t->total = countsel;
2168 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2170 Mat3CpyMat4(mtx, t->obedit->obmat);
2173 if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2175 /* detect CrazySpace [tm] */
2177 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2178 if(modifiers_isDeformed(t->obedit)) {
2179 /* check if we can use deform matrices for modifier from the
2180 start up to stack, they are more accurate than quats */
2181 totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
2183 /* if we still have more modifiers, also do crazyspace
2184 correction with quats, relative to the coordinates after
2185 the modifiers that support deform matrices (defcos) */
2187 mappedcos= get_crazy_mapped_editverts(t);
2188 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2189 set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2191 MEM_freeN(mappedcos);
2200 /* find out which half we do */
2202 for (eve=em->verts.first; eve; eve=eve->next) {
2203 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2211 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2213 if(propmode || eve->f1) {
2214 VertsToTransData(t, tob, em, eve);
2217 if(eve->f1) tob->flag |= TD_SELECTED;
2220 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2225 VECCOPY(vec, E_VEC(eve));
2226 Mat3MulVecfl(mtx, vec);
2227 tob->dist= VecLength(vec);
2230 tob->flag |= TD_NOTCONNECTED;
2231 tob->dist = MAXFLOAT;
2236 if(defmats || (quats && eve->tmp.p)) {
2237 float mat[3][3], imat[3][3], qmat[3][3];
2239 /* use both or either quat and defmat correction */
2240 if(quats && eve->tmp.f) {
2241 QuatToMat3(eve->tmp.p, qmat);
2244 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2245 NULL, NULL, NULL, NULL, NULL);
2247 Mat3MulMat3(mat, mtx, qmat);
2250 Mat3MulMat3(mat, mtx, defmats[a]);
2254 Mat3CpyMat3(tob->smtx, imat);
2255 Mat3CpyMat3(tob->mtx, mat);
2258 Mat3CpyMat3(tob->smtx, smtx);
2259 Mat3CpyMat3(tob->mtx, mtx);
2263 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2264 EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */
2265 if(vmir != eve) tob->extra = vmir;
2275 /* crazy space free */
2282 /* *** NODE EDITOR *** */
2283 void flushTransNodes(TransInfo *t)
2288 /* flush to 2d vector from internally used 3d vector */
2289 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2290 td->loc2d[0]= td->loc[0];
2291 td->loc2d[1]= td->loc[1];
2295 /* ********************* UV ****************** */
2297 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2301 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2303 /* uv coords are scaled by aspects. this is needed for rotations and
2304 proportional editing to be consistent with the stretchted uv coords
2305 that are displayed. this also means that for display and numinput,
2306 and when the the uv coords are flushed, these are converted each time */
2307 td2d->loc[0] = uv[0]*aspx;
2308 td2d->loc[1] = uv[1]*aspy;
2309 td2d->loc[2] = 0.0f;
2313 td->loc = td2d->loc;
2314 VECCOPY(td->center, td->loc);
2315 VECCOPY(td->iloc, td->loc);
2317 memset(td->axismtx, 0, sizeof(td->axismtx));
2318 td->axismtx[2][2] = 1.0f;
2320 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2323 td->flag |= TD_SELECTED;
2333 static void createTransUVs(bContext *C, TransInfo *t)
2337 TransData *td = NULL;
2338 TransData2D *td2d = NULL;
2340 int count=0, countsel=0;
2341 int propmode = t->flag & T_PROP_EDIT;
2342 int efa_s1,efa_s2,efa_s3,efa_s4;
2344 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2347 if(is_uv_tface_editing_allowed()==0) return;
2350 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2351 for (efa= em->faces.first; efa; efa= efa->next) {
2352 /* store face pointer for second loop, prevent second lookup */
2353 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2354 if (simaFaceDraw_Check(efa, tf)) {
2357 efa_s1 = simaUVSel_Check(efa, tf, 0);
2358 efa_s2 = simaUVSel_Check(efa, tf, 1);
2359 efa_s3 = simaUVSel_Check(efa, tf, 2);
2361 efa_s4 = simaUVSel_Check(efa, tf, 3);
2362 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2363 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2366 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2367 if (efa_s1) countsel++;
2368 if (efa_s2) countsel++;
2369 if (efa_s3) countsel++;
2376 for (efa= em->faces.first; efa; efa= efa->next) {
2377 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2378 if (simaFaceDraw_Check(efa, tf)) {
2381 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2382 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2383 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2384 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2386 count += (efa->v4)? 4: 3;
2393 /* note: in prop mode we need at least 1 selected */
2394 if (countsel==0) return;
2396 t->total= (propmode)? count: countsel;
2397 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2398 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2399 treated just as if they were 3d verts */
2400 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2402 if(G.sima->flag & SI_CLIP_UV)
2403 t->flag |= T_CLIP_UV;
2408 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2409 for (efa= em->faces.first; efa; efa= efa->next) {
2410 tf=(MTFace *)efa->tmp.p;
2412 efa_s1 = simaUVSel_Check(efa, tf, 0);
2413 efa_s2 = simaUVSel_Check(efa, tf, 1);
2414 efa_s3 = simaUVSel_Check(efa, tf, 2);
2417 efa_s4 = simaUVSel_Check(efa, tf, 3);
2419 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2420 /* all corners of this quad need their edges moved. so we must store TD for each */
2422 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2423 if (!efa_s1) td->flag |= TD_SKIP;
2426 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2427 if (!efa_s2) td->flag |= TD_SKIP;
2430 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2431 if (!efa_s3) td->flag |= TD_SKIP;
2434 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2435 if (!efa_s4) td->flag |= TD_SKIP;
2439 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2440 if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2441 if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2442 if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2447 for (efa= em->faces.first; efa; efa= efa->next) {
2448 /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2449 if (simaFaceDraw_Check(efa, tf)) {*/
2450 if ((tf=(MTFace *)efa->tmp.p)) {
2452 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2453 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2454 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2456 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2458 if(simaUVSel_Check(efa, tf, 0)) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2459 if(simaUVSel_Check(efa, tf, 1)) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2460 if(simaUVSel_Check(efa, tf, 2)) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2461 if(efa->v4 && simaUVSel_Check(efa, tf, 3)) UVsToTransData(td++, td2d++, tf->uv[3], 1);
2467 if (G.sima->flag & SI_LIVE_UNWRAP)
2468 unwrap_lscm_live_begin();
2472 void flushTransUVs(TransInfo *t)
2474 #if 0 // TRANSFORM_FIX_ME
2476 int a, width, height;
2478 EditMesh *em = ((Mesh *)ob->data)->edit_mesh;
2479 float aspx, aspy, invx, invy;
2481 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2482 transform_width_height_tface_uv(&width, &height);
2486 /* flush to 2d vector from internally used 3d vector */
2487 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2488 td->loc2d[0]= td->loc[0]*invx;
2489 td->loc2d[1]= td->loc[1]*invy;
2491 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2492 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2493 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2497 if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL))
2498 be_square_tface_uv(em);
2500 /* this is overkill if G.sima->lock is not set, but still needed */
2501 object_uvs_changed(ob);
2505 int clipUVTransform(TransInfo *t, float *vec, int resize)
2507 #if 0 // TRANSFORM_FIX_ME
2509 int a, clipx=1, clipy=1;
2510 float aspx, aspy, min[2], max[2];
2512 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2513 min[0]= min[1]= 0.0f;
2514 max[0]= aspx; max[1]= aspy;
2516 for(a=0, td= t->data; a<t->total; a++, td++) {
2517 DO_MINMAX2(td->loc, min, max);
2521 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2522 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2523 else if(max[0] > aspx && t->center[0] < aspx)
2524 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2528 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2529 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2530 else if(max[1] > aspy && t->center[1] < aspy)
2531 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2538 else if(max[0] > aspx)
2539 vec[0] -= max[0]-aspx;
2545 else if(max[1] > aspy)
2546 vec[1] -= max[1]-aspy;
2551 return (clipx || clipy);
2556 /* ********************* IPO EDITOR ************************* */
2558 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2559 * due to bad globals that would need to be imported specially for this
2561 static void createTransIpoData(bContext *C, TransInfo *t)
2565 /* in editipo.c due to some globals that are defined in that file... */
2566 make_ipo_transdata(t);
2570 /* this function is called on recalcData to apply the transforms applied
2571 * to the transdata on to the actual keyframe data
2573 void flushTransIpoData(TransInfo *t)
2575 #if 0 // TRANSFORM_FIX_ME
2579 /* flush to 2d vector from internally used 3d vector */
2580 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2581 // FIXME: autosnap needs to be here...
2583 /* we need to unapply the nla-scaling from the time in some situations */
2585 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2587 td->loc2d[0]= td->loc[0];
2589 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2590 if ((t->data[a].flag & TD_TIMEONLY)==0)
2591 td->loc2d[1]= td->loc[1];
2596 /* ********************* ACTION/NLA EDITOR ****************** */
2598 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2599 * any other gp-frames which may reside on that frame (that are not selected).
2600 * It also makes sure gp-frames are still stored in chronological order after
2603 static void posttrans_gpd_clean (bGPdata *gpd)
2607 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2608 ListBase sel_buffer = {NULL, NULL};
2609 bGPDframe *gpf, *gpfn;
2610 bGPDframe *gfs, *gfsn;
2612 /* loop 1: loop through and isolate selected gp-frames to buffer
2613 * (these need to be sorted as they are isolated)
2615 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2619 if (gpf->flag & GP_FRAME_SELECT) {
2620 BLI_remlink(&gpl->frames, gpf);
2622 /* find place to add them in buffer
2623 * - go backwards as most frames will still be in order,
2624 * so doing it this way will be faster
2626 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2627 /* if current (gpf) occurs after this one in buffer, add! */
2628 if (gfs->framenum < gpf->framenum) {
2629 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2635 BLI_addhead(&sel_buffer, gpf);
2639 /* error checking: it is unlikely, but may be possible to have none selected */
2640 if (sel_buffer.first == NULL)
2643 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2644 if (gpl->frames.first == NULL) {
2645 gpl->frames.first= sel_buffer.first;
2646 gpl->frames.last= sel_buffer.last;
2651 /* loop 2: remove duplicates of frames in buffers */
2652 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2655 /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2656 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2659 /* if this buffer frame needs to go before current, add it! */
2660 if (gfs->framenum < gpf->framenum) {
2661 /* transfer buffer frame to frames list (before current) */
2662 BLI_remlink(&sel_buffer, gfs);
2663 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2665 /* if this buffer frame is on same frame, replace current with it and stop */
2666 else if (gfs->framenum == gpf->framenum) {
2667 /* transfer buffer frame to frames list (before current) */
2668 BLI_remlink(&sel_buffer, gfs);
2669 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2671 /* get rid of current frame */
2673 //gpencil_layer_delframe(gpl, gpf);
2678 /* if anything is still in buffer, append to end */
2679 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2682 BLI_remlink(&sel_buffer, gfs);
2683 BLI_addtail(&gpl->frames, gfs);
2688 /* Called during special_aftertrans_update to make sure selected keyframes replace
2689 * any other keyframes which may reside on that frame (that is not selected).
2691 static void posttrans_icu_clean (IpoCurve *icu)
2693 float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2694 int len, index, i; /* number of frames in cache, item index */
2696 /* allocate memory for the cache */
2697 // TODO: investigate using GHash for this instead?
2698 if (icu->totvert == 0)
2700 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2704 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
2705 * as there is no guarantee what order the keyframes are exactly, even though
2706 * they have been sorted by time.
2709 /* Loop 1: find selected keyframes */
2710 for (i = 0; i < icu->totvert; i++) {
2711 BezTriple *bezt= &icu->bezt[i];
2713 if (BEZSELECTED(bezt)) {
2714 selcache[index]= bezt->vec[1][0];
2720 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2722 for (i = 0; i < icu->totvert; i++) {
2723 BezTriple *bezt= &icu->bezt[i];
2725 if (BEZSELECTED(bezt) == 0) {
2726 /* check beztriple should be removed according to cache */
2727 for (index= 0; index < len; index++) {
2728 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2729 delete_icu_key(icu, i, 0);
2732 else if (bezt->vec[1][0] > selcache[index])
2738 testhandles_ipocurve(icu);
2742 MEM_freeN(selcache);
2745 /* Called by special_aftertrans_update to make sure selected keyframes replace
2746 * any other keyframes which may reside on that frame (that is not selected).
2747 * remake_action_ipos should have already been called
2749 static void posttrans_ipo_clean (Ipo *ipo)
2756 /* loop through relevant data, removing keyframes from the ipocurves
2757 * - all keyframes are converted in/out of global time
2759 for (icu= ipo->curve.first; icu; icu= icu->next) {
2760 posttrans_icu_clean(icu);
2764 /* Called by special_aftertrans_update to make sure selected keyframes replace
2765 * any other keyframes which may reside on that frame (that is not selected).