4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
42 #include "MEM_guardedalloc.h"
44 #include "DNA_action_types.h"
45 #include "DNA_armature_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_effect_types.h"
49 #include "DNA_image_types.h"
50 #include "DNA_ipo_types.h"
51 #include "DNA_key_types.h"
52 #include "DNA_lamp_types.h"
53 #include "DNA_lattice_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_meshdata_types.h"
56 #include "DNA_meta_types.h"
57 #include "DNA_modifier_types.h"
58 #include "DNA_nla_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_object_force.h"
61 #include "DNA_particle_types.h"
62 #include "DNA_scene_types.h"
63 #include "DNA_screen_types.h"
64 #include "DNA_space_types.h"
65 #include "DNA_texture_types.h"
66 #include "DNA_view3d_types.h"
67 #include "DNA_world_types.h"
68 #include "DNA_userdef_types.h"
69 #include "DNA_property_types.h"
70 #include "DNA_vfont_types.h"
71 #include "DNA_constraint_types.h"
72 #include "DNA_listBase.h"
73 #include "DNA_gpencil_types.h"
75 #include "BKE_action.h"
76 #include "BKE_armature.h"
77 #include "BKE_blender.h"
78 #include "BKE_cloth.h"
79 #include "BKE_curve.h"
80 #include "BKE_constraint.h"
81 #include "BKE_depsgraph.h"
82 #include "BKE_displist.h"
83 #include "BKE_DerivedMesh.h"
84 #include "BKE_effect.h"
86 #include "BKE_global.h"
88 #include "BKE_lattice.h"
91 #include "BKE_mball.h"
93 #include "BKE_modifier.h"
94 #include "BKE_object.h"
95 #include "BKE_particle.h"
96 #include "BKE_pointcache.h"
97 #include "BKE_softbody.h"
98 #include "BKE_utildefines.h"
99 #include "BKE_bmesh.h"
100 #include "BKE_context.h"
102 //#include "BIF_editaction.h"
103 //#include "BIF_editview.h"
104 //#include "BIF_editlattice.h"
105 //#include "BIF_editconstraint.h"
106 #include "BIF_editarmature.h"
107 //#include "BIF_editmesh.h"
108 //#include "BIF_editnla.h"
109 //#include "BIF_editsima.h"
110 //#include "BIF_editparticle.h"
112 //#include "BIF_keyframing.h"
113 //#include "BIF_poseobject.h"
114 //#include "BIF_meshtools.h"
115 //#include "BIF_mywindow.h"
116 //#include "BIF_resources.h"
117 #include "BIF_retopo.h"
118 //#include "BIF_screen.h"
119 //#include "BIF_space.h"
120 //#include "BIF_toolbox.h"
122 #include "ED_types.h"
123 #include "ED_anim_api.h"
124 #include "ED_keyframing.h"
125 #include "ED_keyframes_edit.h"
126 #include "ED_view3d.h"
129 #include "UI_view2d.h"
131 //#include "BSE_drawipo.h"
132 //#include "BSE_edit.h"
133 //#include "BSE_editipo.h"
134 //#include "BSE_editipo_types.h"
135 //#include "BSE_editaction_types.h"
137 //#include "BDR_drawaction.h" // list of keyframes in action
138 //#include "BDR_editobject.h" // reset_slowparents()
139 //#include "BDR_gpencil.h"
140 //#include "BDR_unwrapper.h"
142 #include "BLI_arithb.h"
143 #include "BLI_blenlib.h"
144 #include "BLI_editVert.h"
146 //#include "editmesh.h"
148 //#include "blendef.h"
150 //#include "mydevice.h"
152 extern ListBase editNurb;
153 extern ListBase editelems;
155 #include "transform.h"
157 #include "BLO_sys_types.h" // for intptr_t support
159 /************ STUBS TO GET COMPILE ************/
160 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
164 /* local function prototype - for Object/Bone Constraints */
165 static short constraints_list_needinv(TransInfo *t, ListBase *list);
166 /* local function prototype - for finding number of keyframes that are selected for editing */
167 static int count_ipo_keys(Ipo *ipo, char side, float cfra);
169 /* ************************** Functions *************************** */
171 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
172 TransData pivot = *head;
173 TransData *ihead = head;
174 TransData *itail = tail;
175 short connected = t->flag & T_PROP_CONNECTED;
180 while ((tail->dist >= pivot.dist) && (head < tail))
184 while ((tail->rdist >= pivot.rdist) && (head < tail))
195 while ((head->dist <= pivot.dist) && (head < tail))
199 while ((head->rdist <= pivot.rdist) && (head < tail))
212 qsort_trans_data(t, ihead, head-1);
215 qsort_trans_data(t, head+1, itail);
219 void sort_trans_data_dist(TransInfo *t) {
220 TransData *start = t->data;
223 while(i < t->total && start->flag & TD_SELECTED) {
227 qsort_trans_data(t, start, t->data + t->total - 1);
230 static void sort_trans_data(TransInfo *t)
232 TransData *sel, *unsel;
237 while (sel > unsel) {
238 while (unsel->flag & TD_SELECTED) {
244 while (!(sel->flag & TD_SELECTED)) {
258 /* distance calculated from not-selected vertex to nearest selected vertex
259 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
260 static void set_prop_dist(TransInfo *t, short with_dist)
265 for(a=0, tob= t->data; a<t->total; a++, tob++) {
267 tob->rdist= 0.0f; // init, it was mallocced
269 if((tob->flag & TD_SELECTED)==0) {
274 tob->rdist = -1.0f; // signal for next loop
276 for (i = 0, td= t->data; i < t->total; i++, td++) {
277 if(td->flag & TD_SELECTED) {
278 VecSubf(vec, tob->center, td->center);
279 Mat3MulVecfl(tob->mtx, vec);
280 dist = Normalize(vec);
281 if (tob->rdist == -1.0f) {
284 else if (dist < tob->rdist) {
288 else break; // by definition transdata has selected items in beginning
291 tob->dist = tob->rdist;
297 /* ************************** CONVERSIONS ************************* */
299 /* ********************* texture space ********* */
301 static void createTransTexspace(bContext *C, TransInfo *t)
303 Scene *scene = CTX_data_scene(C);
311 if (ob == NULL) { // Shouldn't logically happen, but still...
317 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
323 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
324 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
326 td->flag= TD_SELECTED;
327 VECCOPY(td->center, ob->obmat[3]);
330 Mat3CpyMat4(td->mtx, ob->obmat);
331 Mat3CpyMat4(td->axismtx, ob->obmat);
332 Mat3Ortho(td->axismtx);
333 Mat3Inv(td->smtx, td->mtx);
335 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
336 *texflag &= ~AUTOSPACE;
339 VECCOPY(td->iloc, td->loc);
340 VECCOPY(td->ext->irot, td->ext->rot);
341 VECCOPY(td->ext->isize, td->ext->size);
344 /* ********************* edge (for crease) ***** */
346 static void createTransEdge(bContext *C, TransInfo *t) {
347 #if 0 // TRANSFORM_FIX_ME
348 TransData *td = NULL;
350 float mtx[3][3], smtx[3][3];
351 int count=0, countsel=0;
352 int propmode = t->flag & T_PROP_EDIT;
354 for(eed= em->edges.first; eed; eed= eed->next) {
356 if (eed->f & SELECT) countsel++;
357 if (propmode) count++;
371 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
373 Mat3CpyMat4(mtx, t->obedit->obmat);
376 for(eed= em->edges.first; eed; eed= eed->next) {
377 if(eed->h==0 && (eed->f & SELECT || propmode)) {
378 /* need to set center for center calculations */
379 VecAddf(td->center, eed->v1->co, eed->v2->co);
380 VecMulf(td->center, 0.5f);
384 td->flag= TD_SELECTED;
389 Mat3CpyMat3(td->smtx, smtx);
390 Mat3CpyMat3(td->mtx, mtx);
394 if (t->mode == TFM_BWEIGHT) {
395 td->val = &(eed->bweight);
396 td->ival = eed->bweight;
399 td->val = &(eed->crease);
400 td->ival = eed->crease;
409 /* ********************* pose mode ************* */
411 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
413 bConstraint *con= pchan->constraints.first;
415 for(;con; con= con->next) {
416 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
417 bKinematicConstraint *data= con->data;
421 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
428 static short apply_targetless_ik(Object *ob)
430 bPoseChannel *pchan, *parchan, *chanlist[256];
431 bKinematicConstraint *data;
432 int segcount, apply= 0;
434 /* now we got a difficult situation... we have to find the
435 target-less IK pchans, and apply transformation to the all
436 pchans that were in the chain */
438 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
439 data= has_targetless_ik(pchan);
440 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
442 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
445 /* exclude tip from chain? */
446 if(!(data->flag & CONSTRAINT_IK_TIP))
447 parchan= pchan->parent;
451 /* Find the chain's root & count the segments needed */
452 for (; parchan; parchan=parchan->parent){
453 chanlist[segcount]= parchan;
456 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
458 for(;segcount;segcount--) {
460 float rmat[4][4], tmat[4][4], imat[4][4];
462 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
463 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
464 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
465 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
467 parchan= chanlist[segcount-1];
469 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
471 if(parchan->parent) {
472 Bone *parbone= parchan->parent->bone;
473 float offs_bone[4][4];
475 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
476 Mat4CpyMat3(offs_bone, bone->bone_mat);
478 /* The bone's root offset (is in the parent's coordinate system) */
479 VECCOPY(offs_bone[3], bone->head);
481 /* Get the length translation of parent (length along y axis) */
482 offs_bone[3][1]+= parbone->length;
484 /* pose_mat(b-1) * offs_bone */
485 if(parchan->bone->flag & BONE_HINGE) {
486 /* the rotation of the parent restposition */
487 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
489 /* the location of actual parent transform */
490 VECCOPY(rmat[3], offs_bone[3]);
491 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
492 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
494 Mat4MulMat4(tmat, offs_bone, rmat);
496 else if(parchan->bone->flag & BONE_NO_SCALE) {
497 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
501 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
503 Mat4Invert(imat, tmat);
506 Mat4CpyMat3(tmat, bone->bone_mat);
508 VECCOPY(tmat[3], bone->head);
509 Mat4Invert(imat, tmat);
512 Mat4MulMat4(rmat, parchan->pose_mat, imat);
514 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
516 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
518 Mat3CpyMat4(rmat3, rmat);
521 Mat3ToQuat(rmat3, parchan->quat);
523 /* for size, remove rotation */
524 /* causes problems with some constraints (so apply only if needed) */
525 if (data->flag & CONSTRAINT_IK_STRETCH) {
526 QuatToMat3(parchan->quat, qmat);
528 Mat3MulMat3(smat, rmat3, imat);
529 Mat3ToSize(smat, parchan->size);
532 /* causes problems with some constraints (e.g. childof), so disable this */
533 /* as it is IK shouldn't affect location directly */
534 /* VECCOPY(parchan->loc, rmat[3]); */
540 data->flag &= ~CONSTRAINT_IK_AUTO;
547 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
549 Bone *bone= pchan->bone;
550 float pmat[3][3], omat[3][3];
551 float cmat[3][3], tmat[3][3];
554 VECCOPY(vec, pchan->pose_mat[3]);
555 VECCOPY(td->center, vec);
558 td->flag= TD_SELECTED|TD_USEQUAT;
559 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
561 td->flag |= TD_NOCENTER;
564 if (bone->flag & BONE_TRANSFORM_CHILD)
566 td->flag |= TD_NOCENTER;
567 td->flag |= TD_NO_LOC;
570 td->protectflag= pchan->protectflag;
572 td->loc = pchan->loc;
573 VECCOPY(td->iloc, pchan->loc);
576 td->ext->quat= pchan->quat;
577 td->ext->size= pchan->size;
579 QUATCOPY(td->ext->iquat, pchan->quat);
580 VECCOPY(td->ext->isize, pchan->size);
582 /* proper way to get parent transform + own transform + constraints transform */
583 Mat3CpyMat4(omat, ob->obmat);
586 if(pchan->bone->flag & BONE_HINGE)
587 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
589 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
591 if (constraints_list_needinv(t, &pchan->constraints)) {
592 Mat3CpyMat4(tmat, pchan->constinv);
594 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
597 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
600 if (constraints_list_needinv(t, &pchan->constraints)) {
601 Mat3CpyMat4(tmat, pchan->constinv);
603 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
606 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
609 Mat3Inv(td->smtx, td->mtx);
611 /* for axismat we use bone's own transform */
612 Mat3CpyMat4(pmat, pchan->pose_mat);
613 Mat3MulMat3(td->axismtx, omat, pmat);
614 Mat3Ortho(td->axismtx);
616 if(t->mode==TFM_BONESIZE) {
617 bArmature *arm= t->poseobj->data;
619 if(arm->drawtype==ARM_ENVELOPE) {
621 td->val= &bone->dist;
622 td->ival= bone->dist;
625 // abusive storage of scale in the loc pointer :)
626 td->loc= &bone->xwidth;
627 VECCOPY (td->iloc, td->loc);
632 /* in this case we can do target-less IK grabbing */
633 if(t->mode==TFM_TRANSLATION) {
634 bKinematicConstraint *data= has_targetless_ik(pchan);
636 if(data->flag & CONSTRAINT_IK_TIP) {
637 VECCOPY(data->grabtarget, pchan->pose_tail);
640 VECCOPY(data->grabtarget, pchan->pose_head);
642 td->loc = data->grabtarget;
643 VECCOPY(td->iloc, td->loc);
644 data->flag |= CONSTRAINT_IK_AUTO;
646 /* only object matrix correction */
647 Mat3CpyMat3 (td->mtx, omat);
648 Mat3Inv (td->smtx, td->mtx);
652 /* store reference to first constraint */
653 td->con= pchan->constraints.first;
656 static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
658 Bone *bone= lb->first;
660 for(;bone;bone= bone->next) {
661 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
663 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
665 else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
667 bone->flag |= BONE_TRANSFORM_CHILD;
671 bone->flag &= ~BONE_TRANSFORM;
674 bone_children_clear_transflag(t, &bone->childbase);
678 /* sets transform flags in the bones, returns total */
679 static void set_pose_transflags(TransInfo *t, Object *ob)
681 bArmature *arm= ob->data;
688 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
690 if(bone->layer & arm->layer) {
691 if(bone->flag & BONE_SELECTED)
692 bone->flag |= BONE_TRANSFORM;
694 bone->flag &= ~BONE_TRANSFORM;
696 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
697 bone->flag &= ~BONE_TRANSFORM_CHILD;
701 /* make sure no bone can be transformed when a parent is transformed */
702 /* since pchans are depsgraph sorted, the parents are in beginning of list */
703 if(t->mode!=TFM_BONESIZE) {
704 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
706 if(bone->flag & BONE_TRANSFORM)
707 bone_children_clear_transflag(t, &bone->childbase);
710 /* now count, and check if we have autoIK or have to switch from translate to rotate */
713 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
715 if(bone->flag & BONE_TRANSFORM) {
719 if(t->mode==TFM_TRANSLATION) {
720 if( has_targetless_ik(pchan)==NULL ) {
721 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
722 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
725 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
734 /* if there are no translatable bones, do rotation */
735 if(t->mode==TFM_TRANSLATION && !hastranslation)
736 t->mode= TFM_ROTATION;
740 /* -------- Auto-IK ---------- */
742 /* adjust pose-channel's auto-ik chainlen */
743 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
747 /* don't bother to search if no valid constraints */
748 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
751 /* check if pchan has ik-constraint */
752 for (con= pchan->constraints.first; con; con= con->next) {
753 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
754 bKinematicConstraint *data= con->data;
756 /* only accept if a temporary one (for auto-ik) */
757 if (data->flag & CONSTRAINT_IK_TEMP) {
758 /* chainlen is new chainlen, but is limited by maximum chainlen */
759 if ((chainlen==0) || (chainlen > data->max_rootbone))
760 data->rootbone= data->max_rootbone;
762 data->rootbone= chainlen;
768 /* change the chain-length of auto-ik */
769 void transform_autoik_update (TransInfo *t, short mode)
771 short *chainlen= &G.scene->toolsettings->autoik_chainlen;
774 /* mode determines what change to apply to chainlen */
776 /* mode=1 is from WHEELMOUSEDOWN... increases len */
779 else if (mode == -1) {
780 /* mode==-1 is from WHEELMOUSEUP... decreases len */
781 if (*chainlen > 0) (*chainlen)--;
784 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
785 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
788 /* apply to all pose-channels */
789 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
790 pchan_autoik_adjust(pchan, *chainlen);
794 /* frees temporal IKs */
795 static void pose_grab_with_ik_clear(Object *ob)
797 bKinematicConstraint *data;
799 bConstraint *con, *next;
801 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
802 /* clear all temporary lock flags */
803 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
805 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
806 /* remove all temporary IK-constraints added */
807 for (con= pchan->constraints.first; con; con= next) {
809 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
811 if (data->flag & CONSTRAINT_IK_TEMP) {
812 BLI_remlink(&pchan->constraints, con);
813 MEM_freeN(con->data);
817 pchan->constflag |= PCHAN_HAS_IK;
818 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
819 pchan->constflag |= PCHAN_HAS_TARGET;
825 /* adds the IK to pchan - returns if added */
826 static short pose_grab_with_ik_add(bPoseChannel *pchan)
828 bKinematicConstraint *data;
830 bConstraint *targetless = 0;
836 /* Rule: not if there's already an IK on this channel */
837 for (con= pchan->constraints.first; con; con= con->next) {
838 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
839 bKinematicConstraint *data= con->data;
840 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
842 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
843 if (con->enforce!=0.0) {
844 targetless->flag |= CONSTRAINT_IK_AUTO;
848 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0))
854 //con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
855 BLI_addtail(&pchan->constraints, con);
856 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
858 if (targetless) { /* if exists use values from last targetless IK-constraint as base */
859 *data = *((bKinematicConstraint*)targetless->data);
862 data->flag= CONSTRAINT_IK_TIP;
863 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
864 VECCOPY(data->grabtarget, pchan->pose_tail);
867 /* we include only a connected chain */
868 while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
869 /* here, we set ik-settings for bone from pchan->protectflag */
870 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
871 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
872 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
874 /* now we count this pchan as being included */
876 pchan= pchan->parent;
879 /* make a copy of maximum chain-length */
880 data->max_rootbone= data->rootbone;
885 /* bone is a candidate to get IK, but we don't do it if it has children connected */
886 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
889 short wentdeeper=0, added=0;
891 /* go deeper if children & children are connected */
892 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
893 if (bonec->flag & BONE_CONNECTED) {
895 added+= pose_grab_with_ik_children(pose, bonec);
899 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
901 added+= pose_grab_with_ik_add(pchan);
907 /* main call which adds temporal IK chains */
908 static short pose_grab_with_ik(Object *ob)
911 bPoseChannel *pchan, *parent;
915 if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
920 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
921 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
922 if (pchan->bone->layer & arm->layer) {
923 if (pchan->bone->flag & BONE_SELECTED) {
924 /* Rule: no IK for solitatry (unconnected) bones */
925 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
926 if (bonec->flag & BONE_CONNECTED) {
930 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
933 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
935 /* only adds if there's no IK yet (and no parent bone was selected) */
936 for (parent= pchan->parent; parent; parent= parent->parent) {
937 if (parent->bone->flag & BONE_SELECTED)
941 tot_ik += pose_grab_with_ik_add(pchan);
944 /* rule: go over the children and add IK to the tips */
945 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
951 return (tot_ik) ? 1 : 0;
955 /* only called with pose mode active object now */
956 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
963 TransDataExtension *tdx;
969 /* check validity of state */
970 arm=get_armature (ob);
971 if (arm==NULL || ob->pose==NULL) return;
973 if (arm->flag & ARM_RESTPOS) {
974 if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
975 notice("Pose edit not possible while Rest Position is enabled");
979 if (!(ob->lay & G.vd->lay)) return;
981 /* do we need to add temporal IK chains? */
982 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
983 ik_on= pose_grab_with_ik(ob);
984 if (ik_on) t->flag |= T_AUTOIK;
987 /* set flags and count total (warning, can change transform to rotate) */
988 set_pose_transflags(t, ob);
990 if(t->total==0) return;
993 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
995 /* make sure the lock is set OK, unlock can be accidentally saved? */
996 ob->pose->flag |= POSE_LOCKED;
997 ob->pose->flag &= ~POSE_DO_UNLOCK;
999 /* init trans data */
1000 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
1001 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
1002 for(i=0; i<t->total; i++, td++, tdx++) {
1008 /* use pose channels to fill trans data */
1010 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1011 if(pchan->bone->flag & BONE_TRANSFORM) {
1012 add_pose_transdata(t, pchan, ob, td);
1017 if(td != (t->data+t->total)) printf("Bone selection count error\n");
1019 /* initialise initial auto=ik chainlen's? */
1020 if (ik_on) transform_autoik_update(t, 0);
1024 /* ********************* armature ************** */
1026 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1031 bArmature *arm= t->obedit->data;
1033 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1036 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
1037 if(ebo->layer & arm->layer) {
1038 if (t->mode==TFM_BONESIZE) {
1039 if (ebo->flag & BONE_SELECTED)
1042 else if (t->mode==TFM_BONE_ROLL) {
1043 if (ebo->flag & BONE_SELECTED)
1047 if (ebo->flag & BONE_TIPSEL)
1049 if (ebo->flag & BONE_ROOTSEL)
1055 if (!t->total) return;
1057 Mat3CpyMat4(mtx, t->obedit->obmat);
1060 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1062 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1063 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1065 if(ebo->layer & arm->layer) {
1066 if (t->mode==TFM_BONE_ENVELOPE) {
1068 if (ebo->flag & BONE_ROOTSEL){
1069 td->val= &ebo->rad_head;
1072 VECCOPY (td->center, ebo->head);
1073 td->flag= TD_SELECTED;
1075 Mat3CpyMat3(td->smtx, smtx);
1076 Mat3CpyMat3(td->mtx, mtx);
1084 if (ebo->flag & BONE_TIPSEL){
1085 td->val= &ebo->rad_tail;
1087 VECCOPY (td->center, ebo->tail);
1088 td->flag= TD_SELECTED;
1090 Mat3CpyMat3(td->smtx, smtx);
1091 Mat3CpyMat3(td->mtx, mtx);
1101 else if (t->mode==TFM_BONESIZE) {
1102 if (ebo->flag & BONE_SELECTED) {
1103 if(arm->drawtype==ARM_ENVELOPE) {
1105 td->val= &ebo->dist;
1106 td->ival= ebo->dist;
1109 // abusive storage of scale in the loc pointer :)
1110 td->loc= &ebo->xwidth;
1111 VECCOPY (td->iloc, td->loc);
1114 VECCOPY (td->center, ebo->head);
1115 td->flag= TD_SELECTED;
1117 /* use local bone matrix */
1118 VecSubf(delta, ebo->tail, ebo->head);
1119 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1120 Mat3MulMat3(td->mtx, mtx, bonemat);
1121 Mat3Inv(td->smtx, td->mtx);
1123 Mat3CpyMat3(td->axismtx, td->mtx);
1124 Mat3Ortho(td->axismtx);
1132 else if (t->mode==TFM_BONE_ROLL) {
1133 if (ebo->flag & BONE_SELECTED) {
1135 td->val= &(ebo->roll);
1136 td->ival= ebo->roll;
1138 VECCOPY (td->center, ebo->head);
1139 td->flag= TD_SELECTED;
1148 if (ebo->flag & BONE_TIPSEL){
1149 VECCOPY (td->iloc, ebo->tail);
1150 VECCOPY (td->center, td->iloc);
1152 td->flag= TD_SELECTED;
1153 if (ebo->flag & BONE_EDITMODE_LOCKED)
1154 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1156 Mat3CpyMat3(td->smtx, smtx);
1157 Mat3CpyMat3(td->mtx, mtx);
1159 VecSubf(delta, ebo->tail, ebo->head);
1160 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1162 if ((ebo->flag & BONE_ROOTSEL) == 0)
1173 if (ebo->flag & BONE_ROOTSEL){
1174 VECCOPY (td->iloc, ebo->head);
1175 VECCOPY (td->center, td->iloc);
1177 td->flag= TD_SELECTED;
1178 if (ebo->flag & BONE_EDITMODE_LOCKED)
1179 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1181 Mat3CpyMat3(td->smtx, smtx);
1182 Mat3CpyMat3(td->mtx, mtx);
1184 VecSubf(delta, ebo->tail, ebo->head);
1185 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1187 td->extra = ebo; /* to fix roll */
1201 /* ********************* meta elements ********* */
1203 static void createTransMBallVerts(bContext *C, TransInfo *t)
1209 TransDataExtension *tx;
1210 float mtx[3][3], smtx[3][3];
1211 int count=0, countsel=0;
1212 int propmode = t->flag & T_PROP_EDIT;
1215 for(ml= editelems.first; ml; ml= ml->next) {
1216 if(ml->flag & SELECT) countsel++;
1217 if(propmode) count++;
1220 /* note: in prop mode we need at least 1 selected */
1221 if (countsel==0) return;
1223 if(propmode) t->total = count;
1224 else t->total = countsel;
1226 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1227 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1229 Mat3CpyMat4(mtx, t->obedit->obmat);
1232 for(ml= editelems.first; ml; ml= ml->next) {
1233 if(propmode || (ml->flag & SELECT)) {
1235 VECCOPY(td->iloc, td->loc);
1236 VECCOPY(td->center, td->loc);
1238 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1239 else td->flag= TD_USEQUAT;
1241 Mat3CpyMat3(td->smtx, smtx);
1242 Mat3CpyMat3(td->mtx, mtx);
1247 /* Radius of MetaElem (mass of MetaElem influence) */
1248 if(ml->flag & MB_SCALE_RAD){
1257 /* expx/expy/expz determine "shape" of some MetaElem types */
1258 tx->size = &ml->expx;
1259 tx->isize[0] = ml->expx;
1260 tx->isize[1] = ml->expy;
1261 tx->isize[2] = ml->expz;
1263 /* quat is used for rotation of MetaElem */
1264 tx->quat = ml->quat;
1265 QUATCOPY(tx->iquat, ml->quat);
1276 /* ********************* curve/surface ********* */
1278 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1279 TransData *td, *td_near = NULL;
1280 for (td = head; td<=tail; td++) {
1281 if (td->flag & TD_SELECTED) {
1287 dist = VecLenf(td_near->center, td->center);
1288 if (dist < (td-1)->dist) {
1289 td->dist = (td-1)->dist;
1296 td->dist = MAXFLOAT;
1297 td->flag |= TD_NOTCONNECTED;
1301 for (td = tail; td>=head; td--) {
1302 if (td->flag & TD_SELECTED) {
1308 dist = VecLenf(td_near->center, td->center);
1309 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1310 td->flag &= ~TD_NOTCONNECTED;
1311 if (dist < (td+1)->dist) {
1312 td->dist = (td+1)->dist;
1322 /* Utility function for getting the handle data from bezier's */
1323 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1324 TransDataCurveHandleFlags *hdata;
1325 td->flag |= TD_BEZTRIPLE;
1326 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1327 hdata->ih1 = bezt->h1;
1328 hdata->h1 = &bezt->h1;
1329 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1330 hdata->h2 = &bezt->h2;
1334 static void createTransCurveVerts(bContext *C, TransInfo *t)
1338 TransData *td = NULL;
1342 float mtx[3][3], smtx[3][3];
1344 int count=0, countsel=0;
1345 int propmode = t->flag & T_PROP_EDIT;
1347 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1348 for(nu= editNurb.first; nu; nu= nu->next) {
1349 if((nu->type & 7)==CU_BEZIER) {
1350 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1352 if (G.f & G_HIDDENHANDLES) {
1353 if(bezt->f2 & SELECT) countsel+=3;
1354 if(propmode) count+= 3;
1356 if(bezt->f1 & SELECT) countsel++;
1357 if(bezt->f2 & SELECT) countsel++;
1358 if(bezt->f3 & SELECT) countsel++;
1359 if(propmode) count+= 3;
1365 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1367 if(propmode) count++;
1368 if(bp->f1 & SELECT) countsel++;
1373 /* note: in prop mode we need at least 1 selected */
1374 if (countsel==0) return;
1376 if(propmode) t->total = count;
1377 else t->total = countsel;
1378 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1380 Mat3CpyMat4(mtx, t->obedit->obmat);
1384 for(nu= editNurb.first; nu; nu= nu->next) {
1385 if((nu->type & 7)==CU_BEZIER) {
1386 TransData *head, *tail;
1388 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1390 TransDataCurveHandleFlags *hdata = NULL;
1393 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1394 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1396 VECCOPY(td->iloc, bezt->vec[0]);
1397 td->loc= bezt->vec[0];
1398 VECCOPY(td->center, bezt->vec[1]);
1399 if (G.f & G_HIDDENHANDLES) {
1400 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1403 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1410 hdata = initTransDataCurveHandes(td, bezt);
1412 Mat3CpyMat3(td->smtx, smtx);
1413 Mat3CpyMat3(td->mtx, mtx);
1420 /* This is the Curve Point, the other two are handles */
1421 if(propmode || (bezt->f2 & SELECT)) {
1422 VECCOPY(td->iloc, bezt->vec[1]);
1423 td->loc= bezt->vec[1];
1424 VECCOPY(td->center, td->loc);
1425 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1430 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1431 td->val = &(bezt->radius);
1432 td->ival = bezt->radius;
1433 } else if (t->mode==TFM_TILT) {
1434 td->val = &(bezt->alfa);
1435 td->ival = bezt->alfa;
1440 Mat3CpyMat3(td->smtx, smtx);
1441 Mat3CpyMat3(td->mtx, mtx);
1443 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1444 /* If the middle is selected but the sides arnt, this is needed */
1445 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1446 hdata = initTransDataCurveHandes(td, bezt);
1454 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1455 ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1457 VECCOPY(td->iloc, bezt->vec[2]);
1458 td->loc= bezt->vec[2];
1459 VECCOPY(td->center, bezt->vec[1]);
1460 if (G.f & G_HIDDENHANDLES) {
1461 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1464 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1471 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1472 hdata = initTransDataCurveHandes(td, bezt);
1475 Mat3CpyMat3(td->smtx, smtx);
1476 Mat3CpyMat3(td->mtx, mtx);
1483 else if (propmode && head != tail) {
1484 calc_distanceCurveVerts(head, tail-1);
1488 if (propmode && head != tail)
1489 calc_distanceCurveVerts(head, tail-1);
1491 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1492 * but for now just dont change handle types */
1493 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1494 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1497 TransData *head, *tail;
1499 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1501 if(propmode || (bp->f1 & SELECT)) {
1502 VECCOPY(td->iloc, bp->vec);
1504 VECCOPY(td->center, td->loc);
1505 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1510 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1511 td->val = &(bp->radius);
1512 td->ival = bp->radius;
1514 td->val = &(bp->alfa);
1515 td->ival = bp->alfa;
1518 Mat3CpyMat3(td->smtx, smtx);
1519 Mat3CpyMat3(td->mtx, mtx);
1526 else if (propmode && head != tail) {
1527 calc_distanceCurveVerts(head, tail-1);
1531 if (propmode && head != tail)
1532 calc_distanceCurveVerts(head, tail-1);
1538 /* ********************* lattice *************** */
1540 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1544 TransData *td = NULL;
1546 float mtx[3][3], smtx[3][3];
1548 int count=0, countsel=0;
1549 int propmode = t->flag & T_PROP_EDIT;
1552 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1555 if(bp->f1 & SELECT) countsel++;
1556 if(propmode) count++;
1561 /* note: in prop mode we need at least 1 selected */
1562 if (countsel==0) return;
1564 if(propmode) t->total = count;
1565 else t->total = countsel;
1566 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1568 Mat3CpyMat4(mtx, t->obedit->obmat);
1573 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1575 if(propmode || (bp->f1 & SELECT)) {
1577 VECCOPY(td->iloc, bp->vec);
1579 VECCOPY(td->center, td->loc);
1580 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1582 Mat3CpyMat3(td->smtx, smtx);
1583 Mat3CpyMat3(td->mtx, mtx);
1598 /* ******************* particle edit **************** */
1599 static void createTransParticleVerts(bContext *C, TransInfo *t)
1603 TransData *td = NULL;
1604 TransDataExtension *tx;
1605 Base *base = BASACT;
1607 ParticleSystem *psys = PE_get_current(ob);
1608 ParticleSystemModifierData *psmd = NULL;
1609 ParticleEditSettings *pset = PE_settings();
1610 ParticleData *pa = NULL;
1612 ParticleEditKey *key;
1614 int i,k, totpart, transformparticle;
1615 int count = 0, hasselected = 0;
1616 int propmode = t->flag & T_PROP_EDIT;
1618 if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1620 psmd = psys_get_modifier(ob,psys);
1623 totpart = psys->totpart;
1624 base->flag |= BA_HAS_RECALC_DATA;
1626 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1627 pa->flag &= ~PARS_TRANSFORM;
1628 transformparticle= 0;
1630 if((pa->flag & PARS_HIDE)==0) {
1631 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1632 if((key->flag&PEK_HIDE)==0) {
1633 if(key->flag&PEK_SELECT) {
1635 transformparticle= 1;
1638 transformparticle= 1;
1643 if(transformparticle) {
1644 count += pa->totkey;
1645 pa->flag |= PARS_TRANSFORM;
1649 /* note: in prop mode we need at least 1 selected */
1650 if (hasselected==0) return;
1653 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1655 if(t->mode == TFM_BAKE_TIME)
1656 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1662 Mat4Invert(ob->imat,ob->obmat);
1664 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1665 TransData *head, *tail;
1668 if(!(pa->flag & PARS_TRANSFORM)) continue;
1670 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1672 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1673 VECCOPY(key->world_co, key->co);
1674 Mat4MulVecfl(mat, key->world_co);
1675 td->loc = key->world_co;
1677 VECCOPY(td->iloc, td->loc);
1678 VECCOPY(td->center, td->loc);
1680 if(key->flag & PEK_SELECT)
1681 td->flag |= TD_SELECTED;
1683 td->flag |= TD_SKIP;
1688 /* don't allow moving roots */
1689 if(k==0 && pset->flag & PE_LOCK_FIRST)
1690 td->protectflag |= OB_LOCK_LOC;
1695 if(t->mode == TFM_BAKE_TIME) {
1696 td->val = key->time;
1697 td->ival = *(key->time);
1698 /* abuse size and quat for min/max values */
1699 td->flag |= TD_NO_EXT;
1700 if(k==0) tx->size = 0;
1701 else tx->size = (key - 1)->time;
1703 if(k == pa->totkey - 1) tx->quat = 0;
1704 else tx->quat = (key + 1)->time;
1712 if (propmode && head != tail)
1713 calc_distanceCurveVerts(head, tail - 1);
1718 void flushTransParticles(TransInfo *t)
1720 #if 0 // TRANSFORM_FIX_ME
1721 Scene *scene = t->scene;
1723 ParticleSystem *psys = PE_get_current(ob);
1724 ParticleSystemModifierData *psmd;
1726 ParticleEditKey *key;
1728 float mat[4][4], imat[4][4], co[3];
1729 int i, k, propmode = t->flag & T_PROP_EDIT;
1731 psmd = psys_get_modifier(ob, psys);
1733 /* we do transform in world space, so flush world space position
1734 * back to particle local space */
1736 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1737 if(!(pa->flag & PARS_TRANSFORM)) continue;
1739 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1740 Mat4Invert(imat,mat);
1742 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1743 VECCOPY(co, key->world_co);
1744 Mat4MulVecfl(imat, co);
1746 /* optimization for proportional edit */
1747 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1748 VECCOPY(key->co, co);
1749 pa->flag |= PARS_EDIT_RECALC;
1754 PE_update_object(OBACT, 1);
1758 /* ********************* mesh ****************** */
1760 /* proportional distance based on connectivity */
1761 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1762 #define E_NEAR(a) (nears[((a)->tmp.l)])
1763 #define THRESHOLD 0.0001f
1764 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1770 /* f2 flag is used for 'selection' */
1771 /* tmp.l is offset on scratch array */
1772 for(eve= em->verts.first; eve; eve= eve->next) {
1776 if(eve->f & SELECT) {
1779 E_VEC(eve)[0] = 0.0f;
1780 E_VEC(eve)[1] = 0.0f;
1781 E_VEC(eve)[2] = 0.0f;
1790 /* Floodfill routine */
1792 At worst this is n*n of complexity where n is number of edges
1793 Best case would be n if the list is ordered perfectly.
1794 Estimate is n log n in average (so not too bad)
1799 for(eed= em->edges.first; eed; eed= eed->next) {
1801 EditVert *v1= eed->v1, *v2= eed->v2;
1802 float *vec2 = E_VEC(v2);
1803 float *vec1 = E_VEC(v1);
1805 if (v1->f2 + v2->f2 == 4)
1811 float len1 = VecLength(vec1);
1812 float len2 = VecLength(vec2);
1814 /* for v2 if not selected */
1816 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1817 lenn = VecLength(nvec);
1819 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1820 VECCOPY(vec2, nvec);
1821 E_NEAR(v2) = E_NEAR(v1);
1825 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1826 VECCOPY(vec2, vec1);
1827 E_NEAR(v2) = E_NEAR(v1);
1831 /* for v1 if not selected */
1833 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1834 lenn = VecLength(nvec);
1836 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1837 VECCOPY(vec1, nvec);
1838 E_NEAR(v1) = E_NEAR(v2);
1842 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1843 VECCOPY(vec1, vec2);
1844 E_NEAR(v1) = E_NEAR(v2);
1851 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1853 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1854 VECCOPY(vec2, vec1);
1856 E_NEAR(v2) = E_NEAR(v1);
1862 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1864 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1865 VECCOPY(vec1, vec2);
1867 E_NEAR(v1) = E_NEAR(v2);
1875 /* loop-in-a-loop I know, but we need it! (ton) */
1876 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1880 for(efa= em->faces.first; efa; efa= efa->next)
1882 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1885 VECCOPY(cent, efa->cent);
1889 //way to overwrite what data is edited with transform
1890 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1891 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1895 // td->loc = key->co;
1899 VECCOPY(td->center, td->loc);
1900 if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1901 get_face_center(td->center, em, eve);
1902 VECCOPY(td->iloc, td->loc);
1905 VECCOPY(td->axismtx[2], eve->no);
1911 td->axismtx[1][2] = 0.0f;
1917 if (t->mode == TFM_BWEIGHT) {
1918 td->val = &(eve->bweight);
1919 td->ival = eve->bweight;
1924 td->verse = (void*)eve->vvert;
1925 td->flag |= TD_VERSE_VERT;
1928 td->flag &= ~TD_VERSE_VERT;
1932 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1934 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1936 float *vec = userData;
1942 static int modifiers_disable_subsurf_temporary(Object *ob)
1947 for(md=ob->modifiers.first; md; md=md->next)
1948 if(md->type==eModifierType_Subsurf)
1949 if(md->mode & eModifierMode_OnCage) {
1950 md->mode ^= eModifierMode_DisableTemporary;
1957 /* disable subsurf temporal, get mapped cos, and enable it */
1958 static float *get_crazy_mapped_editverts(TransInfo *t)
1960 Mesh *me= t->obedit->data;
1964 /* disable subsurf temporal, get mapped cos, and enable it */
1965 if(modifiers_disable_subsurf_temporary(t->obedit)) {
1966 /* need to make new derivemesh */
1967 makeDerivedMesh(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1970 /* now get the cage */
1971 dm= editmesh_get_derived_cage(me->edit_mesh, CD_MASK_BAREMESH);
1973 vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1974 dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1978 /* set back the flag, no new cage needs to be built, transform does it */
1979 modifiers_disable_subsurf_temporary(t->obedit);
1984 #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])
1985 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1987 float vecu[3], vecv[3];
1990 TAN_MAKE_VEC(vecu, v1, v2);
1991 TAN_MAKE_VEC(vecv, v1, v3);
1992 triatoquat(v1, vecu, vecv, q1);
1994 TAN_MAKE_VEC(vecu, def1, def2);
1995 TAN_MAKE_VEC(vecv, def1, def3);
1996 triatoquat(def1, vecu, vecv, q2);
1998 QuatSub(quat, q2, q1);
2002 static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
2004 EditVert *eve, *prev;
2006 float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2009 /* two abused locations in vertices */
2010 for(eve= em->verts.first; eve; eve= eve->next, index++) {
2012 eve->prev= (EditVert *)index;
2015 /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2016 for(efa= em->faces.first; efa; efa= efa->next) {
2018 /* retrieve mapped coordinates */
2019 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2020 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2021 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2023 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2024 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2025 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2027 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2028 set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2029 efa->v2->tmp.p= (void*)quats;
2034 v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2035 co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2037 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2038 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2039 efa->v1->tmp.p= (void*)quats;
2042 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2043 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2044 efa->v3->tmp.p= (void*)quats;
2047 if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2048 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2049 efa->v4->tmp.p= (void*)quats;
2054 if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2055 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2056 efa->v1->tmp.p= (void*)quats;
2059 if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2060 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2061 efa->v3->tmp.p= (void*)quats;
2067 /* restore abused prev pointer */
2068 for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2073 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2079 tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2081 for (i=0,v=bm->verts.first;v;v=v->next) {
2082 if ( (vtd = BME_get_transdata(td,v)) ) {
2083 tob->loc = vtd->loc;
2084 tob->val = &vtd->factor;
2085 VECCOPY(tob->iloc,vtd->co);
2086 VECCOPY(tob->center,vtd->org);
2087 VECCOPY(tob->axismtx[0],vtd->vec);
2088 tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2093 /* since td is a memarena, it can hold more transdata than actual elements
2094 * (i.e. we can't depend on td->len to determine the number of actual elements) */
2098 static void createTransEditVerts(bContext *C, TransInfo *t)
2100 Scene *scene = CTX_data_scene(C);
2101 TransData *tob = NULL;
2102 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2104 EditVert **nears = NULL;
2105 EditVert *eve_act = NULL;
2106 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2107 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2108 int count=0, countsel=0, a, totleft;
2109 int propmode = t->flag & T_PROP_EDIT;
2112 if ((t->options & CTX_NO_MIRROR) == 0 && (scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2117 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2118 if(scene->selectmode & SCE_SELECT_VERTEX) {
2119 for(eve= em->verts.first; eve; eve= eve->next) {
2120 if(eve->h==0 && (eve->f & SELECT))
2126 else if(scene->selectmode & SCE_SELECT_EDGE) {
2128 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2129 for(eed= em->edges.first; eed; eed= eed->next) {
2130 if(eed->h==0 && (eed->f & SELECT))
2131 eed->v1->f1= eed->v2->f1= SELECT;
2136 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2137 for(efa= em->faces.first; efa; efa= efa->next) {
2138 if(efa->h==0 && (efa->f & SELECT)) {
2139 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2140 if(efa->v4) efa->v4->f1= SELECT;
2145 /* now we can count */
2146 for(eve= em->verts.first; eve; eve= eve->next) {
2148 if(eve->f1) countsel++;
2149 if(propmode) count++;
2153 /* note: in prop mode we need at least 1 selected */
2154 if (countsel==0) return;
2157 if (em->selected.last) {
2158 EditSelection *ese = em->selected.last;
2159 if ( ese->type == EDITVERT ) {
2160 eve_act = (EditVert *)ese->data;
2168 /* allocating scratch arrays */
2169 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2170 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2172 else t->total = countsel;
2173 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2175 Mat3CpyMat4(mtx, t->obedit->obmat);
2178 if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2180 /* detect CrazySpace [tm] */
2182 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2183 if(modifiers_isDeformed(t->obedit)) {
2184 /* check if we can use deform matrices for modifier from the
2185 start up to stack, they are more accurate than quats */
2186 totleft= editmesh_get_first_deform_matrices(em, &defmats, &defcos);
2188 /* if we still have more modifiers, also do crazyspace
2189 correction with quats, relative to the coordinates after
2190 the modifiers that support deform matrices (defcos) */
2192 mappedcos= get_crazy_mapped_editverts(t);
2193 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2194 set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2196 MEM_freeN(mappedcos);
2205 /* find out which half we do */
2207 for (eve=em->verts.first; eve; eve=eve->next) {
2208 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2216 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2218 if(propmode || eve->f1) {
2219 VertsToTransData(t, tob, em, eve);
2222 if(eve->f1) tob->flag |= TD_SELECTED;
2225 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2230 VECCOPY(vec, E_VEC(eve));
2231 Mat3MulVecfl(mtx, vec);
2232 tob->dist= VecLength(vec);
2235 tob->flag |= TD_NOTCONNECTED;
2236 tob->dist = MAXFLOAT;
2241 if(defmats || (quats && eve->tmp.p)) {
2242 float mat[3][3], imat[3][3], qmat[3][3];
2244 /* use both or either quat and defmat correction */
2245 if(quats && eve->tmp.f) {
2246 QuatToMat3(eve->tmp.p, qmat);
2249 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2250 NULL, NULL, NULL, NULL, NULL);
2252 Mat3MulMat3(mat, mtx, qmat);
2255 Mat3MulMat3(mat, mtx, defmats[a]);
2259 Mat3CpyMat3(tob->smtx, imat);
2260 Mat3CpyMat3(tob->mtx, mat);
2263 Mat3CpyMat3(tob->smtx, smtx);
2264 Mat3CpyMat3(tob->mtx, mtx);
2268 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2269 EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc); /* initializes octree on first call */
2270 if(vmir != eve) tob->extra = vmir;
2280 /* crazy space free */
2287 /* ********************* UV ****************** */
2289 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2293 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2295 /* uv coords are scaled by aspects. this is needed for rotations and
2296 proportional editing to be consistent with the stretchted uv coords
2297 that are displayed. this also means that for display and numinput,
2298 and when the the uv coords are flushed, these are converted each time */
2299 td2d->loc[0] = uv[0]*aspx;
2300 td2d->loc[1] = uv[1]*aspy;
2301 td2d->loc[2] = 0.0f;
2305 td->loc = td2d->loc;
2306 VECCOPY(td->center, td->loc);
2307 VECCOPY(td->iloc, td->loc);
2309 memset(td->axismtx, 0, sizeof(td->axismtx));
2310 td->axismtx[2][2] = 1.0f;
2312 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2315 td->flag |= TD_SELECTED;
2325 static void createTransUVs(bContext *C, TransInfo *t)
2329 TransData *td = NULL;
2330 TransData2D *td2d = NULL;
2332 int count=0, countsel=0;
2333 int propmode = t->flag & T_PROP_EDIT;
2334 int efa_s1,efa_s2,efa_s3,efa_s4;
2336 EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2339 if(is_uv_tface_editing_allowed()==0) return;
2342 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2343 for (efa= em->faces.first; efa; efa= efa->next) {
2344 /* store face pointer for second loop, prevent second lookup */
2345 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2346 if (simaFaceDraw_Check(efa, tf)) {
2349 efa_s1 = simaUVSel_Check(efa, tf, 0);
2350 efa_s2 = simaUVSel_Check(efa, tf, 1);
2351 efa_s3 = simaUVSel_Check(efa, tf, 2);
2353 efa_s4 = simaUVSel_Check(efa, tf, 3);
2354 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2355 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2358 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2359 if (efa_s1) countsel++;
2360 if (efa_s2) countsel++;
2361 if (efa_s3) countsel++;
2368 for (efa= em->faces.first; efa; efa= efa->next) {
2369 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2370 if (simaFaceDraw_Check(efa, tf)) {
2373 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2374 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2375 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2376 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2378 count += (efa->v4)? 4: 3;
2385 /* note: in prop mode we need at least 1 selected */
2386 if (countsel==0) return;
2388 t->total= (propmode)? count: countsel;
2389 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2390 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2391 treated just as if they were 3d verts */
2392 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2394 if(G.sima->flag & SI_CLIP_UV)
2395 t->flag |= T_CLIP_UV;
2400 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2401 for (efa= em->faces.first; efa; efa= efa->next) {
2402 tf=(MTFace *)efa->tmp.p;
2404 efa_s1 = simaUVSel_Check(efa, tf, 0);
2405 efa_s2 = simaUVSel_Check(efa, tf, 1);
2406 efa_s3 = simaUVSel_Check(efa, tf, 2);
2409 efa_s4 = simaUVSel_Check(efa, tf, 3);
2411 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2412 /* all corners of this quad need their edges moved. so we must store TD for each */
2414 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2415 if (!efa_s1) td->flag |= TD_SKIP;
2418 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2419 if (!efa_s2) td->flag |= TD_SKIP;
2422 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2423 if (!efa_s3) td->flag |= TD_SKIP;
2426 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2427 if (!efa_s4) td->flag |= TD_SKIP;
2431 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2432 if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2433 if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2434 if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2439 for (efa= em->faces.first; efa; efa= efa->next) {
2440 /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2441 if (simaFaceDraw_Check(efa, tf)) {*/
2442 if ((tf=(MTFace *)efa->tmp.p)) {
2444 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2445 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2446 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2448 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2450 if(simaUVSel_Check(efa, tf, 0)) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2451 if(simaUVSel_Check(efa, tf, 1)) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2452 if(simaUVSel_Check(efa, tf, 2)) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2453 if(efa->v4 && simaUVSel_Check(efa, tf, 3)) UVsToTransData(td++, td2d++, tf->uv[3], 1);
2459 if (G.sima->flag & SI_LIVE_UNWRAP)
2460 unwrap_lscm_live_begin();
2464 void flushTransUVs(TransInfo *t)
2466 #if 0 // TRANSFORM_FIX_ME
2468 int a, width, height;
2470 EditMesh *em = ((Mesh *)ob->data)->edit_mesh;
2471 float aspx, aspy, invx, invy;
2473 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2474 transform_width_height_tface_uv(&width, &height);
2478 /* flush to 2d vector from internally used 3d vector */
2479 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2480 td->loc2d[0]= td->loc[0]*invx;
2481 td->loc2d[1]= td->loc[1]*invy;
2483 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2484 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2485 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2489 if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL))
2490 be_square_tface_uv(em);
2492 /* this is overkill if G.sima->lock is not set, but still needed */
2493 object_uvs_changed(ob);
2497 int clipUVTransform(TransInfo *t, float *vec, int resize)
2499 #if 0 // TRANSFORM_FIX_ME
2501 int a, clipx=1, clipy=1;
2502 float aspx, aspy, min[2], max[2];
2504 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2505 min[0]= min[1]= 0.0f;
2506 max[0]= aspx; max[1]= aspy;
2508 for(a=0, td= t->data; a<t->total; a++, td++) {
2509 DO_MINMAX2(td->loc, min, max);
2513 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2514 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2515 else if(max[0] > aspx && t->center[0] < aspx)
2516 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2520 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2521 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2522 else if(max[1] > aspy && t->center[1] < aspy)
2523 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2530 else if(max[0] > aspx)
2531 vec[0] -= max[0]-aspx;
2537 else if(max[1] > aspy)
2538 vec[1] -= max[1]-aspy;
2543 return (clipx || clipy);
2548 /* ********************* IPO EDITOR ************************* */
2550 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2551 * due to bad globals that would need to be imported specially for this
2553 static void createTransIpoData(bContext *C, TransInfo *t)
2557 /* in editipo.c due to some globals that are defined in that file... */
2558 make_ipo_transdata(t);
2562 /* this function is called on recalcData to apply the transforms applied
2563 * to the transdata on to the actual keyframe data
2565 void flushTransIpoData(TransInfo *t)
2567 #if 0 // TRANSFORM_FIX_ME
2571 /* flush to 2d vector from internally used 3d vector */
2572 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2573 // FIXME: autosnap needs to be here...
2575 /* we need to unapply the nla-scaling from the time in some situations */
2577 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2579 td->loc2d[0]= td->loc[0];
2581 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2582 if ((t->data[a].flag & TD_TIMEONLY)==0)
2583 td->loc2d[1]= td->loc[1];
2588 /* ********************* ACTION/NLA EDITOR ****************** */
2590 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2591 * any other gp-frames which may reside on that frame (that are not selected).
2592 * It also makes sure gp-frames are still stored in chronological order after
2595 static void posttrans_gpd_clean (bGPdata *gpd)
2599 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2600 ListBase sel_buffer = {NULL, NULL};
2601 bGPDframe *gpf, *gpfn;
2602 bGPDframe *gfs, *gfsn;
2604 /* loop 1: loop through and isolate selected gp-frames to buffer
2605 * (these need to be sorted as they are isolated)
2607 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2611 if (gpf->flag & GP_FRAME_SELECT) {
2612 BLI_remlink(&gpl->frames, gpf);
2614 /* find place to add them in buffer
2615 * - go backwards as most frames will still be in order,
2616 * so doing it this way will be faster
2618 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2619 /* if current (gpf) occurs after this one in buffer, add! */
2620 if (gfs->framenum < gpf->framenum) {
2621 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2627 BLI_addhead(&sel_buffer, gpf);
2631 /* error checking: it is unlikely, but may be possible to have none selected */
2632 if (sel_buffer.first == NULL)
2635 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2636 if (gpl->frames.first == NULL) {
2637 gpl->frames.first= sel_buffer.first;
2638 gpl->frames.last= sel_buffer.last;
2643 /* loop 2: remove duplicates of frames in buffers */
2644 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2647 /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2648 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2651 /* if this buffer frame needs to go before current, add it! */
2652 if (gfs->framenum < gpf->framenum) {
2653 /* transfer buffer frame to frames list (before current) */
2654 BLI_remlink(&sel_buffer, gfs);
2655 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2657 /* if this buffer frame is on same frame, replace current with it and stop */
2658 else if (gfs->framenum == gpf->framenum) {
2659 /* transfer buffer frame to frames list (before current) */
2660 BLI_remlink(&sel_buffer, gfs);
2661 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2663 /* get rid of current frame */
2665 //gpencil_layer_delframe(gpl, gpf);
2670 /* if anything is still in buffer, append to end */
2671 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2674 BLI_remlink(&sel_buffer, gfs);
2675 BLI_addtail(&gpl->frames, gfs);
2680 /* Called by special_aftertrans_update to make sure selected keyframes replace
2681 * any other keyframes which may reside on that frame (that is not selected).
2683 static void posttrans_ipo_clean (Ipo *ipo)
2688 /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
2689 for (icu= ipo->curve.first; icu; icu= icu->next) {
2690 float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2691 int len, index; /* number of frames in cache, item index */
2693 /* allocate memory for the cache */
2694 // TODO: investigate using GHash for this instead?
2695 if (icu->totvert == 0)
2697 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2701 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
2702 * as there is no guarantee what order the keyframes are exactly, even though
2703 * they have been sorted by time.
2706 /* Loop 1: find selected keyframes */
2707 for (i = 0; i < icu->totvert; i++) {
2708 BezTriple *bezt= &icu->bezt[i];
2710 if (BEZSELECTED(bezt)) {
2711 selcache[index]= bezt->vec[1][0];
2717 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2719 for (i = 0; i < icu->totvert; i++) {
2720 BezTriple *bezt= &icu->bezt[i];
2722 if (BEZSELECTED(bezt) == 0) {
2723 /* check beztriple should be removed according to cache */
2724 for (index= 0; index < len; index++) {
2725 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2726 delete_icu_key(icu, i, 0);
2729 else if (bezt->vec[1][0] > selcache[index])
2735 testhandles_ipocurve(icu);
2739 MEM_freeN(selcache);
2743 /* Called by special_aftertrans_update to make sure selected keyframes replace
2744 * any other keyframes which may reside on that frame (that is not selected).
2745 * remake_action_ipos should have already been called
2747 static void posttrans_action_clean (bAnimContext *ac, bAction *act)
2749 ListBase anim_data = {NULL, NULL};
2754 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
2755 ANIM_animdata_filter(&anim_data, filter, act, ANIMCONT_ACTION);
2757 /* loop through relevant data, removing keyframes from the ipo-blocks that were attached