4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
42 #include "MEM_guardedalloc.h"
44 #include "DNA_action_types.h"
45 #include "DNA_armature_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_effect_types.h"
49 #include "DNA_image_types.h"
50 #include "DNA_ipo_types.h"
51 #include "DNA_key_types.h"
52 #include "DNA_lamp_types.h"
53 #include "DNA_lattice_types.h"
54 #include "DNA_mesh_types.h"
55 #include "DNA_meshdata_types.h"
56 #include "DNA_meta_types.h"
57 #include "DNA_modifier_types.h"
58 #include "DNA_nla_types.h"
59 #include "DNA_object_types.h"
60 #include "DNA_object_force.h"
61 #include "DNA_particle_types.h"
62 #include "DNA_scene_types.h"
63 #include "DNA_screen_types.h"
64 #include "DNA_space_types.h"
65 #include "DNA_texture_types.h"
66 #include "DNA_view3d_types.h"
67 #include "DNA_world_types.h"
68 #include "DNA_userdef_types.h"
69 #include "DNA_property_types.h"
70 #include "DNA_vfont_types.h"
71 #include "DNA_constraint_types.h"
72 #include "DNA_listBase.h"
73 #include "DNA_gpencil_types.h"
75 #include "BKE_action.h"
76 #include "BKE_armature.h"
77 #include "BKE_blender.h"
78 #include "BKE_cloth.h"
79 #include "BKE_curve.h"
80 #include "BKE_constraint.h"
81 #include "BKE_depsgraph.h"
82 #include "BKE_displist.h"
83 #include "BKE_DerivedMesh.h"
84 #include "BKE_effect.h"
86 #include "BKE_global.h"
88 #include "BKE_lattice.h"
91 #include "BKE_mball.h"
93 #include "BKE_modifier.h"
94 #include "BKE_object.h"
95 #include "BKE_particle.h"
96 #include "BKE_pointcache.h"
97 #include "BKE_softbody.h"
98 #include "BKE_utildefines.h"
99 #include "BKE_bmesh.h"
100 #include "BKE_context.h"
102 //#include "BIF_editaction.h"
103 //#include "BIF_editview.h"
104 //#include "BIF_editlattice.h"
105 //#include "BIF_editconstraint.h"
106 #include "BIF_editarmature.h"
107 //#include "BIF_editmesh.h"
108 //#include "BIF_editnla.h"
109 //#include "BIF_editsima.h"
110 //#include "BIF_editparticle.h"
112 //#include "BIF_keyframing.h"
113 //#include "BIF_poseobject.h"
114 //#include "BIF_meshtools.h"
115 //#include "BIF_mywindow.h"
116 //#include "BIF_resources.h"
117 #include "BIF_retopo.h"
118 //#include "BIF_screen.h"
119 //#include "BIF_space.h"
120 //#include "BIF_toolbox.h"
122 #include "ED_types.h"
123 #include "ED_anim_api.h"
124 #include "ED_keyframing.h"
125 #include "ED_keyframes_edit.h"
126 #include "ED_view3d.h"
128 #include "UI_view2d.h"
130 //#include "BSE_drawipo.h"
131 //#include "BSE_edit.h"
132 //#include "BSE_editipo.h"
133 //#include "BSE_editipo_types.h"
134 //#include "BSE_editaction_types.h"
136 //#include "BDR_drawaction.h" // list of keyframes in action
137 //#include "BDR_editobject.h" // reset_slowparents()
138 //#include "BDR_gpencil.h"
139 //#include "BDR_unwrapper.h"
141 #include "BLI_arithb.h"
142 #include "BLI_blenlib.h"
143 #include "BLI_editVert.h"
145 //#include "editmesh.h"
147 //#include "blendef.h"
149 //#include "mydevice.h"
151 extern ListBase editNurb;
152 extern ListBase editelems;
154 #include "transform.h"
156 #include "BLO_sys_types.h" // for intptr_t support
158 /************ STUBS TO GET COMPILE ************/
159 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
163 /* local function prototype - for Object/Bone Constraints */
164 static short constraints_list_needinv(TransInfo *t, ListBase *list);
165 /* local function prototype - for finding number of keyframes that are selected for editing */
166 static int count_ipo_keys(Ipo *ipo, char side, float cfra);
168 /* ************************** Functions *************************** */
170 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
171 TransData pivot = *head;
172 TransData *ihead = head;
173 TransData *itail = tail;
174 short connected = t->flag & T_PROP_CONNECTED;
179 while ((tail->dist >= pivot.dist) && (head < tail))
183 while ((tail->rdist >= pivot.rdist) && (head < tail))
194 while ((head->dist <= pivot.dist) && (head < tail))
198 while ((head->rdist <= pivot.rdist) && (head < tail))
211 qsort_trans_data(t, ihead, head-1);
214 qsort_trans_data(t, head+1, itail);
218 void sort_trans_data_dist(TransInfo *t) {
219 TransData *start = t->data;
222 while(i < t->total && start->flag & TD_SELECTED) {
226 qsort_trans_data(t, start, t->data + t->total - 1);
229 static void sort_trans_data(TransInfo *t)
231 TransData *sel, *unsel;
236 while (sel > unsel) {
237 while (unsel->flag & TD_SELECTED) {
243 while (!(sel->flag & TD_SELECTED)) {
257 /* distance calculated from not-selected vertex to nearest selected vertex
258 warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
259 static void set_prop_dist(TransInfo *t, short with_dist)
264 for(a=0, tob= t->data; a<t->total; a++, tob++) {
266 tob->rdist= 0.0f; // init, it was mallocced
268 if((tob->flag & TD_SELECTED)==0) {
273 tob->rdist = -1.0f; // signal for next loop
275 for (i = 0, td= t->data; i < t->total; i++, td++) {
276 if(td->flag & TD_SELECTED) {
277 VecSubf(vec, tob->center, td->center);
278 Mat3MulVecfl(tob->mtx, vec);
279 dist = Normalize(vec);
280 if (tob->rdist == -1.0f) {
283 else if (dist < tob->rdist) {
287 else break; // by definition transdata has selected items in beginning
290 tob->dist = tob->rdist;
296 /* ************************** CONVERSIONS ************************* */
298 /* ********************* texture space ********* */
300 static void createTransTexspace(bContext *C, TransInfo *t)
302 Scene *scene = CTX_data_scene(C);
310 if (ob == NULL) { // Shouldn't logically happen, but still...
316 if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
322 td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
323 td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
325 td->flag= TD_SELECTED;
326 VECCOPY(td->center, ob->obmat[3]);
329 Mat3CpyMat4(td->mtx, ob->obmat);
330 Mat3CpyMat4(td->axismtx, ob->obmat);
331 Mat3Ortho(td->axismtx);
332 Mat3Inv(td->smtx, td->mtx);
334 if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
335 *texflag &= ~AUTOSPACE;
338 VECCOPY(td->iloc, td->loc);
339 VECCOPY(td->ext->irot, td->ext->rot);
340 VECCOPY(td->ext->isize, td->ext->size);
343 /* ********************* edge (for crease) ***** */
345 static void createTransEdge(bContext *C, TransInfo *t) {
346 #if 0 // TRANSFORM_FIX_ME
347 TransData *td = NULL;
349 float mtx[3][3], smtx[3][3];
350 int count=0, countsel=0;
351 int propmode = t->flag & T_PROP_EDIT;
353 for(eed= em->edges.first; eed; eed= eed->next) {
355 if (eed->f & SELECT) countsel++;
356 if (propmode) count++;
370 td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
372 Mat3CpyMat4(mtx, G.obedit->obmat);
375 for(eed= em->edges.first; eed; eed= eed->next) {
376 if(eed->h==0 && (eed->f & SELECT || propmode)) {
377 /* need to set center for center calculations */
378 VecAddf(td->center, eed->v1->co, eed->v2->co);
379 VecMulf(td->center, 0.5f);
383 td->flag= TD_SELECTED;
388 Mat3CpyMat3(td->smtx, smtx);
389 Mat3CpyMat3(td->mtx, mtx);
393 if (t->mode == TFM_BWEIGHT) {
394 td->val = &(eed->bweight);
395 td->ival = eed->bweight;
398 td->val = &(eed->crease);
399 td->ival = eed->crease;
408 /* ********************* pose mode ************* */
410 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
412 bConstraint *con= pchan->constraints.first;
414 for(;con; con= con->next) {
415 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
416 bKinematicConstraint *data= con->data;
420 if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0)
427 static short apply_targetless_ik(Object *ob)
429 bPoseChannel *pchan, *parchan, *chanlist[256];
430 bKinematicConstraint *data;
431 int segcount, apply= 0;
433 /* now we got a difficult situation... we have to find the
434 target-less IK pchans, and apply transformation to the all
435 pchans that were in the chain */
437 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
438 data= has_targetless_ik(pchan);
439 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
441 /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
444 /* exclude tip from chain? */
445 if(!(data->flag & CONSTRAINT_IK_TIP))
446 parchan= pchan->parent;
450 /* Find the chain's root & count the segments needed */
451 for (; parchan; parchan=parchan->parent){
452 chanlist[segcount]= parchan;
455 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
457 for(;segcount;segcount--) {
459 float rmat[4][4], tmat[4][4], imat[4][4];
461 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK */
462 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
463 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat */
464 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
466 parchan= chanlist[segcount-1];
468 bone->flag |= BONE_TRANSFORM; /* ensures it gets an auto key inserted */
470 if(parchan->parent) {
471 Bone *parbone= parchan->parent->bone;
472 float offs_bone[4][4];
474 /* offs_bone = yoffs(b-1) + root(b) + bonemat(b) */
475 Mat4CpyMat3(offs_bone, bone->bone_mat);
477 /* The bone's root offset (is in the parent's coordinate system) */
478 VECCOPY(offs_bone[3], bone->head);
480 /* Get the length translation of parent (length along y axis) */
481 offs_bone[3][1]+= parbone->length;
483 /* pose_mat(b-1) * offs_bone */
484 if(parchan->bone->flag & BONE_HINGE) {
485 /* the rotation of the parent restposition */
486 Mat4CpyMat4(rmat, parbone->arm_mat); /* rmat used as temp */
488 /* the location of actual parent transform */
489 VECCOPY(rmat[3], offs_bone[3]);
490 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
491 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
493 Mat4MulMat4(tmat, offs_bone, rmat);
495 else if(parchan->bone->flag & BONE_NO_SCALE) {
496 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
500 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
502 Mat4Invert(imat, tmat);
505 Mat4CpyMat3(tmat, bone->bone_mat);
507 VECCOPY(tmat[3], bone->head);
508 Mat4Invert(imat, tmat);
511 Mat4MulMat4(rmat, parchan->pose_mat, imat);
513 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
515 float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
517 Mat3CpyMat4(rmat3, rmat);
520 Mat3ToQuat(rmat3, parchan->quat);
522 /* for size, remove rotation */
523 /* causes problems with some constraints (so apply only if needed) */
524 if (data->flag & CONSTRAINT_IK_STRETCH) {
525 QuatToMat3(parchan->quat, qmat);
527 Mat3MulMat3(smat, rmat3, imat);
528 Mat3ToSize(smat, parchan->size);
531 /* causes problems with some constraints (e.g. childof), so disable this */
532 /* as it is IK shouldn't affect location directly */
533 /* VECCOPY(parchan->loc, rmat[3]); */
539 data->flag &= ~CONSTRAINT_IK_AUTO;
546 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
548 Bone *bone= pchan->bone;
549 float pmat[3][3], omat[3][3];
550 float cmat[3][3], tmat[3][3];
553 VECCOPY(vec, pchan->pose_mat[3]);
554 VECCOPY(td->center, vec);
557 td->flag= TD_SELECTED|TD_USEQUAT;
558 if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
560 td->flag |= TD_NOCENTER;
563 if (bone->flag & BONE_TRANSFORM_CHILD)
565 td->flag |= TD_NOCENTER;
566 td->flag |= TD_NO_LOC;
569 td->protectflag= pchan->protectflag;
571 td->loc = pchan->loc;
572 VECCOPY(td->iloc, pchan->loc);
575 td->ext->quat= pchan->quat;
576 td->ext->size= pchan->size;
578 QUATCOPY(td->ext->iquat, pchan->quat);
579 VECCOPY(td->ext->isize, pchan->size);
581 /* proper way to get parent transform + own transform + constraints transform */
582 Mat3CpyMat4(omat, ob->obmat);
585 if(pchan->bone->flag & BONE_HINGE)
586 Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);
588 Mat3CpyMat4(pmat, pchan->parent->pose_mat);
590 if (constraints_list_needinv(t, &pchan->constraints)) {
591 Mat3CpyMat4(tmat, pchan->constinv);
593 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0); // dang mulserie swaps args
596 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0); // dang mulserie swaps args
599 if (constraints_list_needinv(t, &pchan->constraints)) {
600 Mat3CpyMat4(tmat, pchan->constinv);
602 Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0); // dang mulserie swaps args
605 Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat); // Mat3MulMat3 has swapped args!
608 Mat3Inv(td->smtx, td->mtx);
610 /* for axismat we use bone's own transform */
611 Mat3CpyMat4(pmat, pchan->pose_mat);
612 Mat3MulMat3(td->axismtx, omat, pmat);
613 Mat3Ortho(td->axismtx);
615 if(t->mode==TFM_BONESIZE) {
616 bArmature *arm= t->poseobj->data;
618 if(arm->drawtype==ARM_ENVELOPE) {
620 td->val= &bone->dist;
621 td->ival= bone->dist;
624 // abusive storage of scale in the loc pointer :)
625 td->loc= &bone->xwidth;
626 VECCOPY (td->iloc, td->loc);
631 /* in this case we can do target-less IK grabbing */
632 if(t->mode==TFM_TRANSLATION) {
633 bKinematicConstraint *data= has_targetless_ik(pchan);
635 if(data->flag & CONSTRAINT_IK_TIP) {
636 VECCOPY(data->grabtarget, pchan->pose_tail);
639 VECCOPY(data->grabtarget, pchan->pose_head);
641 td->loc = data->grabtarget;
642 VECCOPY(td->iloc, td->loc);
643 data->flag |= CONSTRAINT_IK_AUTO;
645 /* only object matrix correction */
646 Mat3CpyMat3 (td->mtx, omat);
647 Mat3Inv (td->smtx, td->mtx);
651 /* store reference to first constraint */
652 td->con= pchan->constraints.first;
655 static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
657 Bone *bone= lb->first;
659 for(;bone;bone= bone->next) {
660 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
662 bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
664 else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
666 bone->flag |= BONE_TRANSFORM_CHILD;
670 bone->flag &= ~BONE_TRANSFORM;
673 bone_children_clear_transflag(t, &bone->childbase);
677 /* sets transform flags in the bones, returns total */
678 static void set_pose_transflags(TransInfo *t, Object *ob)
680 bArmature *arm= ob->data;
687 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
689 if(bone->layer & arm->layer) {
690 if(bone->flag & BONE_SELECTED)
691 bone->flag |= BONE_TRANSFORM;
693 bone->flag &= ~BONE_TRANSFORM;
695 bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
696 bone->flag &= ~BONE_TRANSFORM_CHILD;
700 /* make sure no bone can be transformed when a parent is transformed */
701 /* since pchans are depsgraph sorted, the parents are in beginning of list */
702 if(t->mode!=TFM_BONESIZE) {
703 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
705 if(bone->flag & BONE_TRANSFORM)
706 bone_children_clear_transflag(t, &bone->childbase);
709 /* now count, and check if we have autoIK or have to switch from translate to rotate */
712 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
714 if(bone->flag & BONE_TRANSFORM) {
718 if(t->mode==TFM_TRANSLATION) {
719 if( has_targetless_ik(pchan)==NULL ) {
720 if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
721 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
724 else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
733 /* if there are no translatable bones, do rotation */
734 if(t->mode==TFM_TRANSLATION && !hastranslation)
735 t->mode= TFM_ROTATION;
739 /* -------- Auto-IK ---------- */
741 /* adjust pose-channel's auto-ik chainlen */
742 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
746 /* don't bother to search if no valid constraints */
747 if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
750 /* check if pchan has ik-constraint */
751 for (con= pchan->constraints.first; con; con= con->next) {
752 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
753 bKinematicConstraint *data= con->data;
755 /* only accept if a temporary one (for auto-ik) */
756 if (data->flag & CONSTRAINT_IK_TEMP) {
757 /* chainlen is new chainlen, but is limited by maximum chainlen */
758 if ((chainlen==0) || (chainlen > data->max_rootbone))
759 data->rootbone= data->max_rootbone;
761 data->rootbone= chainlen;
767 /* change the chain-length of auto-ik */
768 void transform_autoik_update (TransInfo *t, short mode)
770 short *chainlen= &G.scene->toolsettings->autoik_chainlen;
773 /* mode determines what change to apply to chainlen */
775 /* mode=1 is from WHEELMOUSEDOWN... increases len */
778 else if (mode == -1) {
779 /* mode==-1 is from WHEELMOUSEUP... decreases len */
780 if (*chainlen > 0) (*chainlen)--;
783 /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
784 if (ELEM(NULL, t->poseobj, t->poseobj->pose))
787 /* apply to all pose-channels */
788 for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
789 pchan_autoik_adjust(pchan, *chainlen);
793 /* frees temporal IKs */
794 static void pose_grab_with_ik_clear(Object *ob)
796 bKinematicConstraint *data;
798 bConstraint *con, *next;
800 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
801 /* clear all temporary lock flags */
802 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
804 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
805 /* remove all temporary IK-constraints added */
806 for (con= pchan->constraints.first; con; con= next) {
808 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
810 if (data->flag & CONSTRAINT_IK_TEMP) {
811 BLI_remlink(&pchan->constraints, con);
812 MEM_freeN(con->data);
816 pchan->constflag |= PCHAN_HAS_IK;
817 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
818 pchan->constflag |= PCHAN_HAS_TARGET;
824 /* adds the IK to pchan - returns if added */
825 static short pose_grab_with_ik_add(bPoseChannel *pchan)
827 bKinematicConstraint *data;
829 bConstraint *targetless = 0;
835 /* Rule: not if there's already an IK on this channel */
836 for (con= pchan->constraints.first; con; con= con->next) {
837 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
838 bKinematicConstraint *data= con->data;
839 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
841 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
842 if (con->enforce!=0.0) {
843 targetless->flag |= CONSTRAINT_IK_AUTO;
847 if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0))
853 //con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
854 BLI_addtail(&pchan->constraints, con);
855 pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */
857 if (targetless) { /* if exists use values from last targetless IK-constraint as base */
858 *data = *((bKinematicConstraint*)targetless->data);
861 data->flag= CONSTRAINT_IK_TIP;
862 data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
863 VECCOPY(data->grabtarget, pchan->pose_tail);
866 /* we include only a connected chain */
867 while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
868 /* here, we set ik-settings for bone from pchan->protectflag */
869 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
870 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
871 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
873 /* now we count this pchan as being included */
875 pchan= pchan->parent;
878 /* make a copy of maximum chain-length */
879 data->max_rootbone= data->rootbone;
884 /* bone is a candidate to get IK, but we don't do it if it has children connected */
885 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
888 short wentdeeper=0, added=0;
890 /* go deeper if children & children are connected */
891 for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
892 if (bonec->flag & BONE_CONNECTED) {
894 added+= pose_grab_with_ik_children(pose, bonec);
898 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
900 added+= pose_grab_with_ik_add(pchan);
906 /* main call which adds temporal IK chains */
907 static short pose_grab_with_ik(Object *ob)
910 bPoseChannel *pchan, *parent;
914 if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
919 /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
920 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
921 if (pchan->bone->layer & arm->layer) {
922 if (pchan->bone->flag & BONE_SELECTED) {
923 /* Rule: no IK for solitatry (unconnected) bones */
924 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
925 if (bonec->flag & BONE_CONNECTED) {
929 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
932 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
934 /* only adds if there's no IK yet (and no parent bone was selected) */
935 for (parent= pchan->parent; parent; parent= parent->parent) {
936 if (parent->bone->flag & BONE_SELECTED)
940 tot_ik += pose_grab_with_ik_add(pchan);
943 /* rule: go over the children and add IK to the tips */
944 tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
950 return (tot_ik) ? 1 : 0;
954 /* only called with pose mode active object now */
955 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
962 TransDataExtension *tdx;
968 /* check validity of state */
969 arm=get_armature (ob);
970 if (arm==NULL || ob->pose==NULL) return;
972 if (arm->flag & ARM_RESTPOS) {
973 if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
974 notice("Pose edit not possible while Rest Position is enabled");
978 if (!(ob->lay & G.vd->lay)) return;
980 /* do we need to add temporal IK chains? */
981 if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
982 ik_on= pose_grab_with_ik(ob);
983 if (ik_on) t->flag |= T_AUTOIK;
986 /* set flags and count total (warning, can change transform to rotate) */
987 set_pose_transflags(t, ob);
989 if(t->total==0) return;
992 t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
994 /* make sure the lock is set OK, unlock can be accidentally saved? */
995 ob->pose->flag |= POSE_LOCKED;
996 ob->pose->flag &= ~POSE_DO_UNLOCK;
998 /* init trans data */
999 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
1000 tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
1001 for(i=0; i<t->total; i++, td++, tdx++) {
1007 /* use pose channels to fill trans data */
1009 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1010 if(pchan->bone->flag & BONE_TRANSFORM) {
1011 add_pose_transdata(t, pchan, ob, td);
1016 if(td != (t->data+t->total)) printf("Bone selection count error\n");
1018 /* initialise initial auto=ik chainlen's? */
1019 if (ik_on) transform_autoik_update(t, 0);
1023 /* ********************* armature ************** */
1025 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1030 bArmature *arm= G.obedit->data;
1032 float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1035 for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
1036 if(ebo->layer & arm->layer) {
1037 if (t->mode==TFM_BONESIZE) {
1038 if (ebo->flag & BONE_SELECTED)
1041 else if (t->mode==TFM_BONE_ROLL) {
1042 if (ebo->flag & BONE_SELECTED)
1046 if (ebo->flag & BONE_TIPSEL)
1048 if (ebo->flag & BONE_ROOTSEL)
1054 if (!t->total) return;
1056 Mat3CpyMat4(mtx, G.obedit->obmat);
1059 td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1061 for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1062 ebo->oldlength= ebo->length; // length==0.0 on extrude, used for scaling radius of bone points
1064 if(ebo->layer & arm->layer) {
1065 if (t->mode==TFM_BONE_ENVELOPE) {
1067 if (ebo->flag & BONE_ROOTSEL){
1068 td->val= &ebo->rad_head;
1071 VECCOPY (td->center, ebo->head);
1072 td->flag= TD_SELECTED;
1074 Mat3CpyMat3(td->smtx, smtx);
1075 Mat3CpyMat3(td->mtx, mtx);
1083 if (ebo->flag & BONE_TIPSEL){
1084 td->val= &ebo->rad_tail;
1086 VECCOPY (td->center, ebo->tail);
1087 td->flag= TD_SELECTED;
1089 Mat3CpyMat3(td->smtx, smtx);
1090 Mat3CpyMat3(td->mtx, mtx);
1100 else if (t->mode==TFM_BONESIZE) {
1101 if (ebo->flag & BONE_SELECTED) {
1102 if(arm->drawtype==ARM_ENVELOPE) {
1104 td->val= &ebo->dist;
1105 td->ival= ebo->dist;
1108 // abusive storage of scale in the loc pointer :)
1109 td->loc= &ebo->xwidth;
1110 VECCOPY (td->iloc, td->loc);
1113 VECCOPY (td->center, ebo->head);
1114 td->flag= TD_SELECTED;
1116 /* use local bone matrix */
1117 VecSubf(delta, ebo->tail, ebo->head);
1118 vec_roll_to_mat3(delta, ebo->roll, bonemat);
1119 Mat3MulMat3(td->mtx, mtx, bonemat);
1120 Mat3Inv(td->smtx, td->mtx);
1122 Mat3CpyMat3(td->axismtx, td->mtx);
1123 Mat3Ortho(td->axismtx);
1131 else if (t->mode==TFM_BONE_ROLL) {
1132 if (ebo->flag & BONE_SELECTED) {
1134 td->val= &(ebo->roll);
1135 td->ival= ebo->roll;
1137 VECCOPY (td->center, ebo->head);
1138 td->flag= TD_SELECTED;
1147 if (ebo->flag & BONE_TIPSEL){
1148 VECCOPY (td->iloc, ebo->tail);
1149 VECCOPY (td->center, td->iloc);
1151 td->flag= TD_SELECTED;
1152 if (ebo->flag & BONE_EDITMODE_LOCKED)
1153 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1155 Mat3CpyMat3(td->smtx, smtx);
1156 Mat3CpyMat3(td->mtx, mtx);
1158 VecSubf(delta, ebo->tail, ebo->head);
1159 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1161 if ((ebo->flag & BONE_ROOTSEL) == 0)
1172 if (ebo->flag & BONE_ROOTSEL){
1173 VECCOPY (td->iloc, ebo->head);
1174 VECCOPY (td->center, td->iloc);
1176 td->flag= TD_SELECTED;
1177 if (ebo->flag & BONE_EDITMODE_LOCKED)
1178 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1180 Mat3CpyMat3(td->smtx, smtx);
1181 Mat3CpyMat3(td->mtx, mtx);
1183 VecSubf(delta, ebo->tail, ebo->head);
1184 vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1186 td->extra = ebo; /* to fix roll */
1200 /* ********************* meta elements ********* */
1202 static void createTransMBallVerts(bContext *C, TransInfo *t)
1208 TransDataExtension *tx;
1209 float mtx[3][3], smtx[3][3];
1210 int count=0, countsel=0;
1211 int propmode = t->flag & T_PROP_EDIT;
1214 for(ml= editelems.first; ml; ml= ml->next) {
1215 if(ml->flag & SELECT) countsel++;
1216 if(propmode) count++;
1219 /* note: in prop mode we need at least 1 selected */
1220 if (countsel==0) return;
1222 if(propmode) t->total = count;
1223 else t->total = countsel;
1225 td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1226 tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1228 Mat3CpyMat4(mtx, G.obedit->obmat);
1231 for(ml= editelems.first; ml; ml= ml->next) {
1232 if(propmode || (ml->flag & SELECT)) {
1234 VECCOPY(td->iloc, td->loc);
1235 VECCOPY(td->center, td->loc);
1237 if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1238 else td->flag= TD_USEQUAT;
1240 Mat3CpyMat3(td->smtx, smtx);
1241 Mat3CpyMat3(td->mtx, mtx);
1246 /* Radius of MetaElem (mass of MetaElem influence) */
1247 if(ml->flag & MB_SCALE_RAD){
1256 /* expx/expy/expz determine "shape" of some MetaElem types */
1257 tx->size = &ml->expx;
1258 tx->isize[0] = ml->expx;
1259 tx->isize[1] = ml->expy;
1260 tx->isize[2] = ml->expz;
1262 /* quat is used for rotation of MetaElem */
1263 tx->quat = ml->quat;
1264 QUATCOPY(tx->iquat, ml->quat);
1275 /* ********************* curve/surface ********* */
1277 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1278 TransData *td, *td_near = NULL;
1279 for (td = head; td<=tail; td++) {
1280 if (td->flag & TD_SELECTED) {
1286 dist = VecLenf(td_near->center, td->center);
1287 if (dist < (td-1)->dist) {
1288 td->dist = (td-1)->dist;
1295 td->dist = MAXFLOAT;
1296 td->flag |= TD_NOTCONNECTED;
1300 for (td = tail; td>=head; td--) {
1301 if (td->flag & TD_SELECTED) {
1307 dist = VecLenf(td_near->center, td->center);
1308 if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1309 td->flag &= ~TD_NOTCONNECTED;
1310 if (dist < (td+1)->dist) {
1311 td->dist = (td+1)->dist;
1321 /* Utility function for getting the handle data from bezier's */
1322 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1323 TransDataCurveHandleFlags *hdata;
1324 td->flag |= TD_BEZTRIPLE;
1325 hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1326 hdata->ih1 = bezt->h1;
1327 hdata->h1 = &bezt->h1;
1328 hdata->ih2 = bezt->h2; /* incase the second is not selected */
1329 hdata->h2 = &bezt->h2;
1333 static void createTransCurveVerts(bContext *C, TransInfo *t)
1337 TransData *td = NULL;
1341 float mtx[3][3], smtx[3][3];
1343 int count=0, countsel=0;
1344 int propmode = t->flag & T_PROP_EDIT;
1346 /* count total of vertices, check identical as in 2nd loop for making transdata! */
1347 for(nu= editNurb.first; nu; nu= nu->next) {
1348 if((nu->type & 7)==CU_BEZIER) {
1349 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1351 if (G.f & G_HIDDENHANDLES) {
1352 if(bezt->f2 & SELECT) countsel+=3;
1353 if(propmode) count+= 3;
1355 if(bezt->f1 & SELECT) countsel++;
1356 if(bezt->f2 & SELECT) countsel++;
1357 if(bezt->f3 & SELECT) countsel++;
1358 if(propmode) count+= 3;
1364 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1366 if(propmode) count++;
1367 if(bp->f1 & SELECT) countsel++;
1372 /* note: in prop mode we need at least 1 selected */
1373 if (countsel==0) return;
1375 if(propmode) t->total = count;
1376 else t->total = countsel;
1377 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1379 Mat3CpyMat4(mtx, G.obedit->obmat);
1383 for(nu= editNurb.first; nu; nu= nu->next) {
1384 if((nu->type & 7)==CU_BEZIER) {
1385 TransData *head, *tail;
1387 for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1389 TransDataCurveHandleFlags *hdata = NULL;
1392 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1393 ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1395 VECCOPY(td->iloc, bezt->vec[0]);
1396 td->loc= bezt->vec[0];
1397 VECCOPY(td->center, bezt->vec[1]);
1398 if (G.f & G_HIDDENHANDLES) {
1399 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1402 if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1409 hdata = initTransDataCurveHandes(td, bezt);
1411 Mat3CpyMat3(td->smtx, smtx);
1412 Mat3CpyMat3(td->mtx, mtx);
1419 /* This is the Curve Point, the other two are handles */
1420 if(propmode || (bezt->f2 & SELECT)) {
1421 VECCOPY(td->iloc, bezt->vec[1]);
1422 td->loc= bezt->vec[1];
1423 VECCOPY(td->center, td->loc);
1424 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1429 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1430 td->val = &(bezt->radius);
1431 td->ival = bezt->radius;
1432 } else if (t->mode==TFM_TILT) {
1433 td->val = &(bezt->alfa);
1434 td->ival = bezt->alfa;
1439 Mat3CpyMat3(td->smtx, smtx);
1440 Mat3CpyMat3(td->mtx, mtx);
1442 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1443 /* If the middle is selected but the sides arnt, this is needed */
1444 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1445 hdata = initTransDataCurveHandes(td, bezt);
1453 ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1454 ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1456 VECCOPY(td->iloc, bezt->vec[2]);
1457 td->loc= bezt->vec[2];
1458 VECCOPY(td->center, bezt->vec[1]);
1459 if (G.f & G_HIDDENHANDLES) {
1460 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1463 if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1470 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1471 hdata = initTransDataCurveHandes(td, bezt);
1474 Mat3CpyMat3(td->smtx, smtx);
1475 Mat3CpyMat3(td->mtx, mtx);
1482 else if (propmode && head != tail) {
1483 calc_distanceCurveVerts(head, tail-1);
1487 if (propmode && head != tail)
1488 calc_distanceCurveVerts(head, tail-1);
1490 /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1491 * but for now just dont change handle types */
1492 if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1493 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1496 TransData *head, *tail;
1498 for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1500 if(propmode || (bp->f1 & SELECT)) {
1501 VECCOPY(td->iloc, bp->vec);
1503 VECCOPY(td->center, td->loc);
1504 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1509 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1510 td->val = &(bp->radius);
1511 td->ival = bp->radius;
1513 td->val = &(bp->alfa);
1514 td->ival = bp->alfa;
1517 Mat3CpyMat3(td->smtx, smtx);
1518 Mat3CpyMat3(td->mtx, mtx);
1525 else if (propmode && head != tail) {
1526 calc_distanceCurveVerts(head, tail-1);
1530 if (propmode && head != tail)
1531 calc_distanceCurveVerts(head, tail-1);
1537 /* ********************* lattice *************** */
1539 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1543 TransData *td = NULL;
1545 float mtx[3][3], smtx[3][3];
1547 int count=0, countsel=0;
1548 int propmode = t->flag & T_PROP_EDIT;
1551 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1554 if(bp->f1 & SELECT) countsel++;
1555 if(propmode) count++;
1560 /* note: in prop mode we need at least 1 selected */
1561 if (countsel==0) return;
1563 if(propmode) t->total = count;
1564 else t->total = countsel;
1565 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1567 Mat3CpyMat4(mtx, G.obedit->obmat);
1572 a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1574 if(propmode || (bp->f1 & SELECT)) {
1576 VECCOPY(td->iloc, bp->vec);
1578 VECCOPY(td->center, td->loc);
1579 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1581 Mat3CpyMat3(td->smtx, smtx);
1582 Mat3CpyMat3(td->mtx, mtx);
1597 /* ******************* particle edit **************** */
1598 static void createTransParticleVerts(bContext *C, TransInfo *t)
1602 TransData *td = NULL;
1603 TransDataExtension *tx;
1604 Base *base = BASACT;
1606 ParticleSystem *psys = PE_get_current(ob);
1607 ParticleSystemModifierData *psmd = NULL;
1608 ParticleEditSettings *pset = PE_settings();
1609 ParticleData *pa = NULL;
1611 ParticleEditKey *key;
1613 int i,k, totpart, transformparticle;
1614 int count = 0, hasselected = 0;
1615 int propmode = t->flag & T_PROP_EDIT;
1617 if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1619 psmd = psys_get_modifier(ob,psys);
1622 totpart = psys->totpart;
1623 base->flag |= BA_HAS_RECALC_DATA;
1625 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1626 pa->flag &= ~PARS_TRANSFORM;
1627 transformparticle= 0;
1629 if((pa->flag & PARS_HIDE)==0) {
1630 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1631 if((key->flag&PEK_HIDE)==0) {
1632 if(key->flag&PEK_SELECT) {
1634 transformparticle= 1;
1637 transformparticle= 1;
1642 if(transformparticle) {
1643 count += pa->totkey;
1644 pa->flag |= PARS_TRANSFORM;
1648 /* note: in prop mode we need at least 1 selected */
1649 if (hasselected==0) return;
1652 td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1654 if(t->mode == TFM_BAKE_TIME)
1655 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1661 Mat4Invert(ob->imat,ob->obmat);
1663 for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1664 TransData *head, *tail;
1667 if(!(pa->flag & PARS_TRANSFORM)) continue;
1669 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1671 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1672 VECCOPY(key->world_co, key->co);
1673 Mat4MulVecfl(mat, key->world_co);
1674 td->loc = key->world_co;
1676 VECCOPY(td->iloc, td->loc);
1677 VECCOPY(td->center, td->loc);
1679 if(key->flag & PEK_SELECT)
1680 td->flag |= TD_SELECTED;
1682 td->flag |= TD_SKIP;
1687 /* don't allow moving roots */
1688 if(k==0 && pset->flag & PE_LOCK_FIRST)
1689 td->protectflag |= OB_LOCK_LOC;
1694 if(t->mode == TFM_BAKE_TIME) {
1695 td->val = key->time;
1696 td->ival = *(key->time);
1697 /* abuse size and quat for min/max values */
1698 td->flag |= TD_NO_EXT;
1699 if(k==0) tx->size = 0;
1700 else tx->size = (key - 1)->time;
1702 if(k == pa->totkey - 1) tx->quat = 0;
1703 else tx->quat = (key + 1)->time;
1711 if (propmode && head != tail)
1712 calc_distanceCurveVerts(head, tail - 1);
1717 void flushTransParticles(TransInfo *t)
1719 #if 0 // TRANSFORM_FIX_ME
1720 Scene *scene = t->scene;
1722 ParticleSystem *psys = PE_get_current(ob);
1723 ParticleSystemModifierData *psmd;
1725 ParticleEditKey *key;
1727 float mat[4][4], imat[4][4], co[3];
1728 int i, k, propmode = t->flag & T_PROP_EDIT;
1730 psmd = psys_get_modifier(ob, psys);
1732 /* we do transform in world space, so flush world space position
1733 * back to particle local space */
1735 for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1736 if(!(pa->flag & PARS_TRANSFORM)) continue;
1738 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1739 Mat4Invert(imat,mat);
1741 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1742 VECCOPY(co, key->world_co);
1743 Mat4MulVecfl(imat, co);
1745 /* optimization for proportional edit */
1746 if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1747 VECCOPY(key->co, co);
1748 pa->flag |= PARS_EDIT_RECALC;
1753 PE_update_object(OBACT, 1);
1757 /* ********************* mesh ****************** */
1759 /* proportional distance based on connectivity */
1760 #define E_VEC(a) (vectors + (3 * (a)->tmp.l))
1761 #define E_NEAR(a) (nears[((a)->tmp.l)])
1762 #define THRESHOLD 0.0001f
1763 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1769 /* f2 flag is used for 'selection' */
1770 /* tmp.l is offset on scratch array */
1771 for(eve= em->verts.first; eve; eve= eve->next) {
1775 if(eve->f & SELECT) {
1778 E_VEC(eve)[0] = 0.0f;
1779 E_VEC(eve)[1] = 0.0f;
1780 E_VEC(eve)[2] = 0.0f;
1789 /* Floodfill routine */
1791 At worst this is n*n of complexity where n is number of edges
1792 Best case would be n if the list is ordered perfectly.
1793 Estimate is n log n in average (so not too bad)
1798 for(eed= em->edges.first; eed; eed= eed->next) {
1800 EditVert *v1= eed->v1, *v2= eed->v2;
1801 float *vec2 = E_VEC(v2);
1802 float *vec1 = E_VEC(v1);
1804 if (v1->f2 + v2->f2 == 4)
1810 float len1 = VecLength(vec1);
1811 float len2 = VecLength(vec2);
1813 /* for v2 if not selected */
1815 VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1816 lenn = VecLength(nvec);
1818 if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1819 VECCOPY(vec2, nvec);
1820 E_NEAR(v2) = E_NEAR(v1);
1824 else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1825 VECCOPY(vec2, vec1);
1826 E_NEAR(v2) = E_NEAR(v1);
1830 /* for v1 if not selected */
1832 VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1833 lenn = VecLength(nvec);
1835 if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1836 VECCOPY(vec1, nvec);
1837 E_NEAR(v1) = E_NEAR(v2);
1841 else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1842 VECCOPY(vec1, vec2);
1843 E_NEAR(v1) = E_NEAR(v2);
1850 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1852 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1853 VECCOPY(vec2, vec1);
1855 E_NEAR(v2) = E_NEAR(v1);
1861 VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1863 if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1864 VECCOPY(vec1, vec2);
1866 E_NEAR(v1) = E_NEAR(v2);
1874 /* loop-in-a-loop I know, but we need it! (ton) */
1875 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1879 for(efa= em->faces.first; efa; efa= efa->next)
1881 if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1884 VECCOPY(cent, efa->cent);
1888 //way to overwrite what data is edited with transform
1889 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1890 static void VertsToTransData(TransData *td, EditMesh *em, EditVert *eve)
1894 // td->loc = key->co;
1898 VECCOPY(td->center, td->loc);
1900 // if(G.vd->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 (BIF_GetTransInfo()->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(void)
1960 Mesh *me= G.obedit->data;
1964 /* disable subsurf temporal, get mapped cos, and enable it */
1965 if(modifiers_disable_subsurf_temporary(G.obedit)) {
1966 /* need to make new derivemesh */
1967 makeDerivedMesh(G.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(G.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)
2102 TransData *tob = NULL;
2103 EditMesh *em = t->em;
2105 EditVert **nears = NULL;
2106 EditVert *eve_act = NULL;
2107 float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2108 float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2109 int count=0, countsel=0, a, totleft;
2110 int propmode = t->flag & T_PROP_EDIT;
2113 if ((t->options & CTX_NO_MIRROR) == 0 && (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2118 // transform now requires awareness for select mode, so we tag the f1 flags in verts
2119 if(G.scene->selectmode & SCE_SELECT_VERTEX) {
2120 for(eve= em->verts.first; eve; eve= eve->next) {
2121 if(eve->h==0 && (eve->f & SELECT))
2127 else if(G.scene->selectmode & SCE_SELECT_EDGE) {
2129 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2130 for(eed= em->edges.first; eed; eed= eed->next) {
2131 if(eed->h==0 && (eed->f & SELECT))
2132 eed->v1->f1= eed->v2->f1= SELECT;
2137 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2138 for(efa= em->faces.first; efa; efa= efa->next) {
2139 if(efa->h==0 && (efa->f & SELECT)) {
2140 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2141 if(efa->v4) efa->v4->f1= SELECT;
2146 /* now we can count */
2147 for(eve= em->verts.first; eve; eve= eve->next) {
2149 if(eve->f1) countsel++;
2150 if(propmode) count++;
2154 /* note: in prop mode we need at least 1 selected */
2155 if (countsel==0) return;
2158 if (em->selected.last) {
2159 EditSelection *ese = em->selected.last;
2160 if ( ese->type == EDITVERT ) {
2161 eve_act = (EditVert *)ese->data;
2169 /* allocating scratch arrays */
2170 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2171 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2173 else t->total = countsel;
2174 tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2176 Mat3CpyMat4(mtx, G.obedit->obmat);
2179 if(propmode) editmesh_set_connectivity_distance(t->em, t->total, vectors, nears);
2181 /* detect CrazySpace [tm] */
2183 if(modifiers_getCageIndex(G.obedit, NULL)>=0) {
2184 if(modifiers_isDeformed(G.obedit)) {
2185 /* check if we can use deform matrices for modifier from the
2186 start up to stack, they are more accurate than quats */
2187 totleft= editmesh_get_first_deform_matrices(&defmats, &defcos);
2189 /* if we still have more modifiers, also do crazyspace
2190 correction with quats, relative to the coordinates after
2191 the modifiers that support deform matrices (defcos) */
2193 mappedcos= get_crazy_mapped_editverts();
2194 quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2195 set_crazyspace_quats(t->em, (float*)defcos, mappedcos, quats);
2197 MEM_freeN(mappedcos);
2206 /* find out which half we do */
2208 for (eve=em->verts.first; eve; eve=eve->next) {
2209 if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2217 for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2219 if(propmode || eve->f1) {
2220 VertsToTransData(t, tob, t->em, eve);
2223 if(eve->f1) tob->flag |= TD_SELECTED;
2226 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2231 VECCOPY(vec, E_VEC(eve));
2232 Mat3MulVecfl(mtx, vec);
2233 tob->dist= VecLength(vec);
2236 tob->flag |= TD_NOTCONNECTED;
2237 tob->dist = MAXFLOAT;
2242 if(defmats || (quats && eve->tmp.p)) {
2243 float mat[3][3], imat[3][3], qmat[3][3];
2245 /* use both or either quat and defmat correction */
2246 if(quats && eve->tmp.f) {
2247 QuatToMat3(eve->tmp.p, qmat);
2250 Mat3MulSerie(mat, mtx, qmat, defmats[a],
2251 NULL, NULL, NULL, NULL, NULL);
2253 Mat3MulMat3(mat, mtx, qmat);
2256 Mat3MulMat3(mat, mtx, defmats[a]);
2260 Mat3CpyMat3(tob->smtx, imat);
2261 Mat3CpyMat3(tob->mtx, mat);
2264 Mat3CpyMat3(tob->smtx, smtx);
2265 Mat3CpyMat3(tob->mtx, mtx);
2269 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2270 EditVert *vmir= editmesh_get_x_mirror_vert(G.obedit, tob->iloc); /* initializes octree on first call */
2271 if(vmir != eve) tob->extra = vmir;
2281 /* crazy space free */
2289 /* ********************* UV ****************** */
2291 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2295 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2297 /* uv coords are scaled by aspects. this is needed for rotations and
2298 proportional editing to be consistent with the stretchted uv coords
2299 that are displayed. this also means that for display and numinput,
2300 and when the the uv coords are flushed, these are converted each time */
2301 td2d->loc[0] = uv[0]*aspx;
2302 td2d->loc[1] = uv[1]*aspy;
2303 td2d->loc[2] = 0.0f;
2307 td->loc = td2d->loc;
2308 VECCOPY(td->center, td->loc);
2309 VECCOPY(td->iloc, td->loc);
2311 memset(td->axismtx, 0, sizeof(td->axismtx));
2312 td->axismtx[2][2] = 1.0f;
2314 td->ext= NULL; td->tdi= NULL; td->val= NULL;
2317 td->flag |= TD_SELECTED;
2327 static void createTransUVs(bContext *C, TransInfo *t)
2331 TransData *td = NULL;
2332 TransData2D *td2d = NULL;
2334 int count=0, countsel=0;
2335 int propmode = t->flag & T_PROP_EDIT;
2336 int efa_s1,efa_s2,efa_s3,efa_s4;
2338 EditMesh *em = t->em;
2341 if(is_uv_tface_editing_allowed()==0) return;
2344 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2345 for (efa= em->faces.first; efa; efa= efa->next) {
2346 /* store face pointer for second loop, prevent second lookup */
2347 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2348 if (simaFaceDraw_Check(efa, tf)) {
2351 efa_s1 = simaUVSel_Check(efa, tf, 0);
2352 efa_s2 = simaUVSel_Check(efa, tf, 1);
2353 efa_s3 = simaUVSel_Check(efa, tf, 2);
2355 efa_s4 = simaUVSel_Check(efa, tf, 3);
2356 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2357 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2360 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2361 if (efa_s1) countsel++;
2362 if (efa_s2) countsel++;
2363 if (efa_s3) countsel++;
2370 for (efa= em->faces.first; efa; efa= efa->next) {
2371 tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2372 if (simaFaceDraw_Check(efa, tf)) {
2375 if (simaUVSel_Check(efa, tf, 0)) countsel++;
2376 if (simaUVSel_Check(efa, tf, 1)) countsel++;
2377 if (simaUVSel_Check(efa, tf, 2)) countsel++;
2378 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2380 count += (efa->v4)? 4: 3;
2387 /* note: in prop mode we need at least 1 selected */
2388 if (countsel==0) return;
2390 t->total= (propmode)? count: countsel;
2391 t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2392 /* for each 2d uv coord a 3d vector is allocated, so that they can be
2393 treated just as if they were 3d verts */
2394 t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2396 if(G.sima->flag & SI_CLIP_UV)
2397 t->flag |= T_CLIP_UV;
2402 if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2403 for (efa= em->faces.first; efa; efa= efa->next) {
2404 tf=(MTFace *)efa->tmp.p;
2406 efa_s1 = simaUVSel_Check(efa, tf, 0);
2407 efa_s2 = simaUVSel_Check(efa, tf, 1);
2408 efa_s3 = simaUVSel_Check(efa, tf, 2);
2411 efa_s4 = simaUVSel_Check(efa, tf, 3);
2413 if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2414 /* all corners of this quad need their edges moved. so we must store TD for each */
2416 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2417 if (!efa_s1) td->flag |= TD_SKIP;
2420 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2421 if (!efa_s2) td->flag |= TD_SKIP;
2424 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2425 if (!efa_s3) td->flag |= TD_SKIP;
2428 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2429 if (!efa_s4) td->flag |= TD_SKIP;
2433 /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2434 if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2435 if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2436 if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2441 for (efa= em->faces.first; efa; efa= efa->next) {
2442 /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2443 if (simaFaceDraw_Check(efa, tf)) {*/
2444 if ((tf=(MTFace *)efa->tmp.p)) {
2446 UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2447 UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2448 UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2450 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2452 if(simaUVSel_Check(efa, tf, 0)) UVsToTransData(td++, td2d++, tf->uv[0], 1);
2453 if(simaUVSel_Check(efa, tf, 1)) UVsToTransData(td++, td2d++, tf->uv[1], 1);
2454 if(simaUVSel_Check(efa, tf, 2)) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2455 if(efa->v4 && simaUVSel_Check(efa, tf, 3)) UVsToTransData(td++, td2d++, tf->uv[3], 1);
2461 if (G.sima->flag & SI_LIVE_UNWRAP)
2462 unwrap_lscm_live_begin();
2466 void flushTransUVs(TransInfo *t)
2468 #if 0 // TRANSFORM_FIX_ME
2470 int a, width, height;
2472 EditMesh *em = t->em;
2473 float aspx, aspy, invx, invy;
2475 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2476 transform_width_height_tface_uv(&width, &height);
2480 /* flush to 2d vector from internally used 3d vector */
2481 for(a=0, td= t->data2d; a<t->total; a++, td++) {
2482 td->loc2d[0]= td->loc[0]*invx;
2483 td->loc2d[1]= td->loc[1]*invy;
2485 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2486 td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2487 td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2491 if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL))
2492 be_square_tface_uv(em);
2494 /* this is overkill if G.sima->lock is not set, but still needed */
2495 object_uvs_changed(ob);
2499 int clipUVTransform(TransInfo *t, float *vec, int resize)
2501 #if 0 // TRANSFORM_FIX_ME
2503 int a, clipx=1, clipy=1;
2504 float aspx, aspy, min[2], max[2];
2506 transform_aspect_ratio_tface_uv(&aspx, &aspy);
2507 min[0]= min[1]= 0.0f;
2508 max[0]= aspx; max[1]= aspy;
2510 for(a=0, td= t->data; a<t->total; a++, td++) {
2511 DO_MINMAX2(td->loc, min, max);
2515 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2516 vec[0] *= t->center[0]/(t->center[0] - min[0]);
2517 else if(max[0] > aspx && t->center[0] < aspx)
2518 vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2522 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2523 vec[1] *= t->center[1]/(t->center[1] - min[1]);
2524 else if(max[1] > aspy && t->center[1] < aspy)
2525 vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2532 else if(max[0] > aspx)
2533 vec[0] -= max[0]-aspx;
2539 else if(max[1] > aspy)
2540 vec[1] -= max[1]-aspy;
2545 return (clipx || clipy);
2550 /* ********************* IPO EDITOR ************************* */
2552 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2553 * due to bad globals that would need to be imported specially for this
2555 static void createTransIpoData(bContext *C, TransInfo *t)
2559 /* in editipo.c due to some globals that are defined in that file... */
2560 make_ipo_transdata(t);
2564 /* this function is called on recalcData to apply the transforms applied
2565 * to the transdata on to the actual keyframe data
2567 void flushTransIpoData(TransInfo *t)
2569 #if 0 // TRANSFORM_FIX_ME
2573 /* flush to 2d vector from internally used 3d vector */
2574 for (a=0, td= t->data2d; a<t->total; a++, td++) {
2575 // FIXME: autosnap needs to be here...
2577 /* we need to unapply the nla-scaling from the time in some situations */
2579 td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2581 td->loc2d[0]= td->loc[0];
2583 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2584 if ((t->data[a].flag & TD_TIMEONLY)==0)
2585 td->loc2d[1]= td->loc[1];
2590 /* ********************* ACTION/NLA EDITOR ****************** */
2592 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2593 * any other gp-frames which may reside on that frame (that are not selected).
2594 * It also makes sure gp-frames are still stored in chronological order after
2597 static void posttrans_gpd_clean (bGPdata *gpd)
2601 for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2602 ListBase sel_buffer = {NULL, NULL};
2603 bGPDframe *gpf, *gpfn;
2604 bGPDframe *gfs, *gfsn;
2606 /* loop 1: loop through and isolate selected gp-frames to buffer
2607 * (these need to be sorted as they are isolated)
2609 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2613 if (gpf->flag & GP_FRAME_SELECT) {
2614 BLI_remlink(&gpl->frames, gpf);
2616 /* find place to add them in buffer
2617 * - go backwards as most frames will still be in order,
2618 * so doing it this way will be faster
2620 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2621 /* if current (gpf) occurs after this one in buffer, add! */
2622 if (gfs->framenum < gpf->framenum) {
2623 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2629 BLI_addhead(&sel_buffer, gpf);
2633 /* error checking: it is unlikely, but may be possible to have none selected */
2634 if (sel_buffer.first == NULL)
2637 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2638 if (gpl->frames.first == NULL) {
2639 gpl->frames.first= sel_buffer.first;
2640 gpl->frames.last= sel_buffer.last;
2645 /* loop 2: remove duplicates of frames in buffers */
2646 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2649 /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2650 for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2653 /* if this buffer frame needs to go before current, add it! */
2654 if (gfs->framenum < gpf->framenum) {
2655 /* transfer buffer frame to frames list (before current) */
2656 BLI_remlink(&sel_buffer, gfs);
2657 BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2659 /* if this buffer frame is on same frame, replace current with it and stop */
2660 else 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 /* get rid of current frame */
2667 //gpencil_layer_delframe(gpl, gpf);
2672 /* if anything is still in buffer, append to end */
2673 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2676 BLI_remlink(&sel_buffer, gfs);
2677 BLI_addtail(&gpl->frames, gfs);
2682 /* Called by special_aftertrans_update to make sure selected keyframes replace
2683 * any other keyframes which may reside on that frame (that is not selected).
2685 static void posttrans_ipo_clean (Ipo *ipo)
2690 /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
2691 for (icu= ipo->curve.first; icu; icu= icu->next) {
2692 float *selcache; /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2693 int len, index; /* number of frames in cache, item index */
2695 /* allocate memory for the cache */
2696 // TODO: investigate using GHash for this instead?
2697 if (icu->totvert == 0)
2699 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2703 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting
2704 * as there is no guarantee what order the keyframes are exactly, even though
2705 * they have been sorted by time.
2708 /* Loop 1: find selected keyframes */
2709 for (i = 0; i < icu->totvert; i++) {
2710 BezTriple *bezt= &icu->bezt[i];
2712 if (BEZSELECTED(bezt)) {
2713 selcache[index]= bezt->vec[1][0];
2719 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2721 for (i = 0; i < icu->totvert; i++) {
2722 BezTriple *bezt= &icu->bezt[i];
2724 if (BEZSELECTED(bezt) == 0) {
2725 /* check beztriple should be removed according to cache */
2726 for (index= 0; index < len; index++) {
2727 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2728 delete_icu_key(icu, i, 0);
2731 else if (bezt->vec[1][0] > selcache[index])
2737 testhandles_ipocurve(icu);
2741 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_action_clean (bAnimContext *ac, bAction *act)
2751 ListBase anim_data = {NULL, NULL};
2756 filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
2757 ANIM_animdata_filter(&anim_data, filter, act, ANIMCONT_ACTION);