ebac66d6b127c08656f83aea658bf512dc7e8100
[blender.git] / source / blender / editors / transform / transform_conversions.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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.
10  *
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.
15  *
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.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifndef WIN32
31 #include <unistd.h>
32 #else
33 #include <io.h>
34 #endif
35 #include <string.h>
36 #include <math.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_action_types.h"
41 #include "DNA_armature_types.h"
42 #include "DNA_camera_types.h"
43 #include "DNA_curve_types.h"
44 #include "DNA_effect_types.h"
45 #include "DNA_image_types.h"
46 #include "DNA_ipo_types.h"
47 #include "DNA_key_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_modifier_types.h"
54 #include "DNA_nla_types.h"
55 #include "DNA_node_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_object_force.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_texture_types.h"
63 #include "DNA_view3d_types.h"
64 #include "DNA_world_types.h"
65 #include "DNA_userdef_types.h"
66 #include "DNA_property_types.h"
67 #include "DNA_vfont_types.h"
68 #include "DNA_constraint_types.h"
69 #include "DNA_listBase.h"
70 #include "DNA_gpencil_types.h"
71
72 #include "BKE_action.h"
73 #include "BKE_armature.h"
74 #include "BKE_blender.h"
75 #include "BKE_cloth.h"
76 #include "BKE_curve.h"
77 #include "BKE_constraint.h"
78 #include "BKE_depsgraph.h"
79 #include "BKE_displist.h"
80 #include "BKE_DerivedMesh.h"
81 #include "BKE_effect.h"
82 #include "BKE_font.h"
83 #include "BKE_global.h"
84 #include "BKE_ipo.h"
85 #include "BKE_lattice.h"
86 #include "BKE_key.h"
87 #include "BKE_main.h"
88 #include "BKE_mball.h"
89 #include "BKE_mesh.h"
90 #include "BKE_modifier.h"
91 #include "BKE_object.h"
92 #include "BKE_particle.h"
93 #include "BKE_pointcache.h"
94 #include "BKE_softbody.h"
95 #include "BKE_utildefines.h"
96 #include "BKE_bmesh.h"
97 #include "BKE_context.h"
98
99 //#include "BIF_editaction.h"
100 //#include "BIF_editview.h"
101 //#include "BIF_editlattice.h"
102 //#include "BIF_editconstraint.h"
103 #include "BIF_editarmature.h"
104 //#include "BIF_editmesh.h"
105 //#include "BIF_editnla.h"
106 //#include "BIF_editsima.h"
107 //#include "BIF_editparticle.h"
108 #include "BIF_gl.h"
109 //#include "BIF_keyframing.h"
110 //#include "BIF_poseobject.h"
111 //#include "BIF_meshtools.h"
112 //#include "BIF_mywindow.h"
113 //#include "BIF_resources.h"
114 #include "BIF_retopo.h"
115 //#include "BIF_screen.h"
116 //#include "BIF_space.h"
117 //#include "BIF_toolbox.h"
118
119 #include "ED_types.h"
120 #include "ED_anim_api.h"
121 #include "ED_keyframing.h"
122 #include "ED_keyframes_edit.h"
123 #include "ED_view3d.h"
124 #include "ED_mesh.h"
125
126 #include "UI_view2d.h"
127
128 //#include "BSE_drawipo.h"
129 //#include "BSE_edit.h"
130 //#include "BSE_editipo.h"
131 //#include "BSE_editipo_types.h"
132 //#include "BSE_editaction_types.h"
133
134 //#include "BDR_drawaction.h"           // list of keyframes in action
135 //#include "BDR_editobject.h"           // reset_slowparents()
136 //#include "BDR_gpencil.h"
137 //#include "BDR_unwrapper.h"
138
139 #include "BLI_arithb.h"
140 #include "BLI_blenlib.h"
141 #include "BLI_editVert.h"
142
143 //#include "editmesh.h"
144 //
145 //#include "blendef.h"
146 //
147 //#include "mydevice.h"
148
149 extern ListBase editNurb;
150 extern ListBase editelems;
151
152 #include "transform.h"
153
154 #include "BLO_sys_types.h" // for intptr_t support
155
156 /************ STUBS TO GET COMPILE ************/
157 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
158
159
160
161 /* local function prototype - for Object/Bone Constraints */
162 static short constraints_list_needinv(TransInfo *t, ListBase *list);
163 /* local function prototype - for finding number of keyframes that are selected for editing */
164 static int count_ipo_keys(Ipo *ipo, char side, float cfra);
165
166 /* ************************** Functions *************************** */
167
168 static void qsort_trans_data(TransInfo *t, TransData *head, TransData *tail) {
169         TransData pivot = *head;
170         TransData *ihead = head;
171         TransData *itail = tail;
172         short connected = t->flag & T_PROP_CONNECTED;
173
174         while (head < tail)
175         {
176                 if (connected) {
177                         while ((tail->dist >= pivot.dist) && (head < tail))
178                                 tail--;
179                 }
180                 else {
181                         while ((tail->rdist >= pivot.rdist) && (head < tail))
182                                 tail--;
183                 }
184
185                 if (head != tail)
186                 {
187                         *head = *tail;
188                         head++;
189                 }
190
191                 if (connected) {
192                         while ((head->dist <= pivot.dist) && (head < tail))
193                                 head++;
194                 }
195                 else {
196                         while ((head->rdist <= pivot.rdist) && (head < tail))
197                                 head++;
198                 }
199
200                 if (head != tail)
201                 {
202                         *tail = *head;
203                         tail--;
204                 }
205         }
206
207         *head = pivot;
208         if (ihead < head) {
209                 qsort_trans_data(t, ihead, head-1);
210         }
211         if (itail > head) {
212                 qsort_trans_data(t, head+1, itail);
213         }
214 }
215
216 void sort_trans_data_dist(TransInfo *t) {
217         TransData *start = t->data;
218         int i = 1;
219
220         while(i < t->total && start->flag & TD_SELECTED) {
221                 start++;
222                 i++;
223         }
224         qsort_trans_data(t, start, t->data + t->total - 1);
225 }
226
227 static void sort_trans_data(TransInfo *t) 
228 {
229         TransData *sel, *unsel;
230         TransData temp;
231         unsel = t->data;
232         sel = t->data;
233         sel += t->total - 1;
234         while (sel > unsel) {
235                 while (unsel->flag & TD_SELECTED) {
236                         unsel++;
237                         if (unsel == sel) {
238                                 return;
239                         }
240                 }
241                 while (!(sel->flag & TD_SELECTED)) {
242                         sel--;
243                         if (unsel == sel) {
244                                 return;
245                         }
246                 }
247                 temp = *unsel;
248                 *unsel = *sel;
249                 *sel = temp;
250                 sel--;
251                 unsel++;
252         }
253 }
254
255 /* distance calculated from not-selected vertex to nearest selected vertex
256    warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
257 static void set_prop_dist(TransInfo *t, short with_dist)
258 {
259         TransData *tob;
260         int a;
261
262         for(a=0, tob= t->data; a<t->total; a++, tob++) {
263                 
264                 tob->rdist= 0.0f; // init, it was mallocced
265                 
266                 if((tob->flag & TD_SELECTED)==0) {
267                         TransData *td;
268                         int i;
269                         float dist, vec[3];
270
271                         tob->rdist = -1.0f; // signal for next loop
272                                 
273                         for (i = 0, td= t->data; i < t->total; i++, td++) {
274                                 if(td->flag & TD_SELECTED) {
275                                         VecSubf(vec, tob->center, td->center);
276                                         Mat3MulVecfl(tob->mtx, vec);
277                                         dist = Normalize(vec);
278                                         if (tob->rdist == -1.0f) {
279                                                 tob->rdist = dist;
280                                         }
281                                         else if (dist < tob->rdist) {
282                                                 tob->rdist = dist;
283                                         }
284                                 }
285                                 else break;     // by definition transdata has selected items in beginning
286                         }
287                         if (with_dist) {
288                                 tob->dist = tob->rdist;
289                         }
290                 }       
291         }
292 }
293
294 /* ************************** CONVERSIONS ************************* */
295
296 /* ********************* texture space ********* */
297
298 static void createTransTexspace(bContext *C, TransInfo *t)
299 {
300         Scene *scene = CTX_data_scene(C);
301         TransData *td;
302         Object *ob;
303         ID *id;
304         int *texflag;
305         
306         ob = OBACT;
307         
308         if (ob == NULL) { // Shouldn't logically happen, but still...
309                 t->total = 0;
310                 return;
311         }
312
313         id = ob->data;
314         if(id == NULL || !ELEM3( GS(id->name), ID_ME, ID_CU, ID_MB )) {
315                 t->total = 0;
316                 return;
317         }
318
319         t->total = 1;
320         td= t->data= MEM_callocN(sizeof(TransData), "TransTexspace");
321         td->ext= t->ext= MEM_callocN(sizeof(TransDataExtension), "TransTexspace");
322         
323         td->flag= TD_SELECTED;
324         VECCOPY(td->center, ob->obmat[3]);
325         td->ob = ob;
326         
327         Mat3CpyMat4(td->mtx, ob->obmat);
328         Mat3CpyMat4(td->axismtx, ob->obmat);
329         Mat3Ortho(td->axismtx);
330         Mat3Inv(td->smtx, td->mtx);
331         
332         if (give_obdata_texspace(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) {
333                 *texflag &= ~AUTOSPACE;
334         }
335         
336         VECCOPY(td->iloc, td->loc);
337         VECCOPY(td->ext->irot, td->ext->rot);
338         VECCOPY(td->ext->isize, td->ext->size);
339 }
340
341 /* ********************* edge (for crease) ***** */
342
343 static void createTransEdge(bContext *C, TransInfo *t) {
344 #if 0   // TRANSFORM_FIX_ME
345         TransData *td = NULL;
346         EditEdge *eed;
347         float mtx[3][3], smtx[3][3];
348         int count=0, countsel=0;
349         int propmode = t->flag & T_PROP_EDIT;
350
351         for(eed= em->edges.first; eed; eed= eed->next) {
352                 if(eed->h==0) {
353                         if (eed->f & SELECT) countsel++;
354                         if (propmode) count++;
355                 }
356         }
357
358         if (countsel == 0)
359                 return;
360
361         if(propmode) {
362                 t->total = count;
363         }
364         else {
365                 t->total = countsel;
366         }
367
368         td= t->data= MEM_callocN(t->total * sizeof(TransData), "TransCrease");
369
370         Mat3CpyMat4(mtx, t->obedit->obmat);
371         Mat3Inv(smtx, mtx);
372
373         for(eed= em->edges.first; eed; eed= eed->next) {
374                 if(eed->h==0 && (eed->f & SELECT || propmode)) {
375                         /* need to set center for center calculations */
376                         VecAddf(td->center, eed->v1->co, eed->v2->co);
377                         VecMulf(td->center, 0.5f);
378
379                         td->loc= NULL;
380                         if (eed->f & SELECT)
381                                 td->flag= TD_SELECTED;
382                         else 
383                                 td->flag= 0;
384
385
386                         Mat3CpyMat3(td->smtx, smtx);
387                         Mat3CpyMat3(td->mtx, mtx);
388
389                         td->ext = NULL;
390                         td->tdi = NULL;
391                         if (t->mode == TFM_BWEIGHT) {
392                                 td->val = &(eed->bweight);
393                                 td->ival = eed->bweight;
394                         }
395                         else {
396                                 td->val = &(eed->crease);
397                                 td->ival = eed->crease;
398                         }
399
400                         td++;
401                 }
402         }
403 #endif
404 }
405
406 /* ********************* pose mode ************* */
407
408 static bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan)
409 {
410         bConstraint *con= pchan->constraints.first;
411         
412         for(;con; con= con->next) {
413                 if(con->type==CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
414                         bKinematicConstraint *data= con->data;
415                         
416                         if(data->tar==NULL) 
417                                 return data;
418                         if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) 
419                                 return data;
420                 }
421         }
422         return NULL;
423 }
424
425 static short apply_targetless_ik(Object *ob)
426 {
427         bPoseChannel *pchan, *parchan, *chanlist[256];
428         bKinematicConstraint *data;
429         int segcount, apply= 0;
430         
431         /* now we got a difficult situation... we have to find the
432            target-less IK pchans, and apply transformation to the all 
433            pchans that were in the chain */
434         
435         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
436                 data= has_targetless_ik(pchan);
437                 if(data && (data->flag & CONSTRAINT_IK_AUTO)) {
438                         
439                         /* fill the array with the bones of the chain (armature.c does same, keep it synced) */
440                         segcount= 0;
441                         
442                         /* exclude tip from chain? */
443                         if(!(data->flag & CONSTRAINT_IK_TIP))
444                                 parchan= pchan->parent;
445                         else
446                                 parchan= pchan;
447                         
448                         /* Find the chain's root & count the segments needed */
449                         for (; parchan; parchan=parchan->parent){
450                                 chanlist[segcount]= parchan;
451                                 segcount++;
452                                 
453                                 if(segcount==data->rootbone || segcount>255) break; // 255 is weak
454                         }
455                         for(;segcount;segcount--) {
456                                 Bone *bone;
457                                 float rmat[4][4], tmat[4][4], imat[4][4];
458                                 
459                                 /* pose_mat(b) = pose_mat(b-1) * offs_bone * channel * constraint * IK  */
460                                 /* we put in channel the entire result of rmat= (channel * constraint * IK) */
461                                 /* pose_mat(b) = pose_mat(b-1) * offs_bone * rmat  */
462                                 /* rmat = pose_mat(b) * inv( pose_mat(b-1) * offs_bone ) */
463                                 
464                                 parchan= chanlist[segcount-1];
465                                 bone= parchan->bone;
466                                 bone->flag |= BONE_TRANSFORM;   /* ensures it gets an auto key inserted */
467                                 
468                                 if(parchan->parent) {
469                                         Bone *parbone= parchan->parent->bone;
470                                         float offs_bone[4][4];
471                                         
472                                         /* offs_bone =  yoffs(b-1) + root(b) + bonemat(b) */
473                                         Mat4CpyMat3(offs_bone, bone->bone_mat);
474                                         
475                                         /* The bone's root offset (is in the parent's coordinate system) */
476                                         VECCOPY(offs_bone[3], bone->head);
477                                         
478                                         /* Get the length translation of parent (length along y axis) */
479                                         offs_bone[3][1]+= parbone->length;
480                                         
481                                         /* pose_mat(b-1) * offs_bone */
482                                         if(parchan->bone->flag & BONE_HINGE) {
483                                                 /* the rotation of the parent restposition */
484                                                 Mat4CpyMat4(rmat, parbone->arm_mat);    /* rmat used as temp */
485                                                 
486                                                 /* the location of actual parent transform */
487                                                 VECCOPY(rmat[3], offs_bone[3]);
488                                                 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f;
489                                                 Mat4MulVecfl(parchan->parent->pose_mat, rmat[3]);
490                                                 
491                                                 Mat4MulMat4(tmat, offs_bone, rmat);
492                                         }
493                                         else if(parchan->bone->flag & BONE_NO_SCALE) {
494                                                 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
495                                                 Mat4Ortho(tmat);
496                                         }
497                                         else
498                                                 Mat4MulMat4(tmat, offs_bone, parchan->parent->pose_mat);
499                                         
500                                         Mat4Invert(imat, tmat);
501                                 }
502                                 else {
503                                         Mat4CpyMat3(tmat, bone->bone_mat);
504
505                                         VECCOPY(tmat[3], bone->head);
506                                         Mat4Invert(imat, tmat);
507                                 }
508                                 /* result matrix */
509                                 Mat4MulMat4(rmat, parchan->pose_mat, imat);
510                                 
511                                 /* apply and decompose, doesn't work for constraints or non-uniform scale well */
512                                 {
513                                         float rmat3[3][3], qmat[3][3], imat[3][3], smat[3][3];
514                                         
515                                         Mat3CpyMat4(rmat3, rmat);
516                                         
517                                         /* quaternion */
518                                         Mat3ToQuat(rmat3, parchan->quat);
519                                         
520                                         /* for size, remove rotation */
521                                         /* causes problems with some constraints (so apply only if needed) */
522                                         if (data->flag & CONSTRAINT_IK_STRETCH) {
523                                                 QuatToMat3(parchan->quat, qmat);
524                                                 Mat3Inv(imat, qmat);
525                                                 Mat3MulMat3(smat, rmat3, imat);
526                                                 Mat3ToSize(smat, parchan->size);
527                                         }
528                                         
529                                         /* causes problems with some constraints (e.g. childof), so disable this */
530                                         /* as it is IK shouldn't affect location directly */
531                                         /* VECCOPY(parchan->loc, rmat[3]); */
532                                 }
533                                 
534                         }
535                         
536                         apply= 1;
537                         data->flag &= ~CONSTRAINT_IK_AUTO;
538                 }
539         }               
540         
541         return apply;
542 }
543
544 static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, TransData *td)
545 {
546         Bone *bone= pchan->bone;
547         float pmat[3][3], omat[3][3];
548         float cmat[3][3], tmat[3][3];
549         float vec[3];
550
551         VECCOPY(vec, pchan->pose_mat[3]);
552         VECCOPY(td->center, vec);
553         
554         td->ob = ob;
555         td->flag= TD_SELECTED|TD_USEQUAT;
556         if (bone->flag & BONE_HINGE_CHILD_TRANSFORM)
557         {
558                 td->flag |= TD_NOCENTER;
559         }
560         
561         if (bone->flag & BONE_TRANSFORM_CHILD)
562         {
563                 td->flag |= TD_NOCENTER;
564                 td->flag |= TD_NO_LOC;
565         }
566         
567         td->protectflag= pchan->protectflag;
568         
569         td->loc = pchan->loc;
570         VECCOPY(td->iloc, pchan->loc);
571         
572         td->ext->rot= NULL;
573         td->ext->quat= pchan->quat;
574         td->ext->size= pchan->size;
575
576         QUATCOPY(td->ext->iquat, pchan->quat);
577         VECCOPY(td->ext->isize, pchan->size);
578
579         /* proper way to get parent transform + own transform + constraints transform */
580         Mat3CpyMat4(omat, ob->obmat);
581         
582         if(pchan->parent) {      
583                 if(pchan->bone->flag & BONE_HINGE)       
584                         Mat3CpyMat4(pmat, pchan->parent->bone->arm_mat);         
585                 else     
586                         Mat3CpyMat4(pmat, pchan->parent->pose_mat);
587                 
588                 if (constraints_list_needinv(t, &pchan->constraints)) {
589                         Mat3CpyMat4(tmat, pchan->constinv);
590                         Mat3Inv(cmat, tmat);
591                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, cmat, 0,0,0,0);    // dang mulserie swaps args
592                 }
593                 else
594                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, pmat, omat, 0,0,0,0,0);    // dang mulserie swaps args
595         }
596         else {
597                 if (constraints_list_needinv(t, &pchan->constraints)) {
598                         Mat3CpyMat4(tmat, pchan->constinv);
599                         Mat3Inv(cmat, tmat);
600                         Mat3MulSerie(td->mtx, pchan->bone->bone_mat, omat, cmat, 0,0,0,0,0);    // dang mulserie swaps args
601                 }
602                 else 
603                         Mat3MulMat3(td->mtx, omat, pchan->bone->bone_mat);  // Mat3MulMat3 has swapped args! 
604         }
605         
606         Mat3Inv(td->smtx, td->mtx);
607         
608         /* for axismat we use bone's own transform */
609         Mat3CpyMat4(pmat, pchan->pose_mat);
610         Mat3MulMat3(td->axismtx, omat, pmat);
611         Mat3Ortho(td->axismtx);
612         
613         if(t->mode==TFM_BONESIZE) {
614                 bArmature *arm= t->poseobj->data;
615                 
616                 if(arm->drawtype==ARM_ENVELOPE) {
617                         td->loc= NULL;
618                         td->val= &bone->dist;
619                         td->ival= bone->dist;
620                 }
621                 else {
622                         // abusive storage of scale in the loc pointer :)
623                         td->loc= &bone->xwidth;
624                         VECCOPY (td->iloc, td->loc);
625                         td->val= NULL;
626                 }
627         }
628         
629         /* in this case we can do target-less IK grabbing */
630         if(t->mode==TFM_TRANSLATION) {
631                 bKinematicConstraint *data= has_targetless_ik(pchan);
632                 if(data) {
633                         if(data->flag & CONSTRAINT_IK_TIP) {
634                                 VECCOPY(data->grabtarget, pchan->pose_tail);
635                         }
636                         else {
637                                 VECCOPY(data->grabtarget, pchan->pose_head);
638                         }
639                         td->loc = data->grabtarget;
640                         VECCOPY(td->iloc, td->loc);
641                         data->flag |= CONSTRAINT_IK_AUTO;
642                         
643                         /* only object matrix correction */
644                         Mat3CpyMat3 (td->mtx, omat);
645                         Mat3Inv (td->smtx, td->mtx);
646                 }
647         }
648         
649         /* store reference to first constraint */
650         td->con= pchan->constraints.first;
651 }
652
653 static void bone_children_clear_transflag(TransInfo *t, ListBase *lb)
654 {
655         Bone *bone= lb->first;
656         
657         for(;bone;bone= bone->next) {
658                 if((bone->flag & BONE_HINGE) && (bone->flag & BONE_CONNECTED))
659                 {
660                         bone->flag |= BONE_HINGE_CHILD_TRANSFORM;
661                 }
662                 else if (bone->flag & BONE_TRANSFORM && (t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)) 
663                 {
664                         bone->flag |= BONE_TRANSFORM_CHILD;
665                 }
666                 else
667                 {
668                         bone->flag &= ~BONE_TRANSFORM;
669                 }
670
671                 bone_children_clear_transflag(t, &bone->childbase);
672         }
673 }
674
675 /* sets transform flags in the bones, returns total */
676 static void set_pose_transflags(TransInfo *t, Object *ob)
677 {
678         bArmature *arm= ob->data;
679         bPoseChannel *pchan;
680         Bone *bone;
681         int hastranslation;
682         
683         t->total= 0;
684         
685         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
686                 bone= pchan->bone;
687                 if(bone->layer & arm->layer) {
688                         if(bone->flag & BONE_SELECTED)
689                                 bone->flag |= BONE_TRANSFORM;
690                         else
691                                 bone->flag &= ~BONE_TRANSFORM;
692
693                         bone->flag &= ~BONE_HINGE_CHILD_TRANSFORM;
694                         bone->flag &= ~BONE_TRANSFORM_CHILD;
695                 }
696         }
697         
698         /* make sure no bone can be transformed when a parent is transformed */
699         /* since pchans are depsgraph sorted, the parents are in beginning of list */
700         if(t->mode!=TFM_BONESIZE) {
701                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
702                         bone= pchan->bone;
703                         if(bone->flag & BONE_TRANSFORM)
704                                 bone_children_clear_transflag(t, &bone->childbase);
705                 }
706         }       
707         /* now count, and check if we have autoIK or have to switch from translate to rotate */
708         hastranslation= 0;
709
710         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
711                 bone= pchan->bone;
712                 if(bone->flag & BONE_TRANSFORM) {
713
714                         t->total++;
715                         
716                         if(t->mode==TFM_TRANSLATION) {
717                                 if( has_targetless_ik(pchan)==NULL ) {
718                                         if(pchan->parent && (pchan->bone->flag & BONE_CONNECTED)) {
719                                                 if(pchan->bone->flag & BONE_HINGE_CHILD_TRANSFORM)
720                                                         hastranslation= 1;
721                                         }
722                                         else if((pchan->protectflag & OB_LOCK_LOC)!=OB_LOCK_LOC)
723                                                 hastranslation= 1;
724                                 }
725                                 else
726                                         hastranslation= 1;
727                         }
728                 }
729         }
730
731         /* if there are no translatable bones, do rotation */
732         if(t->mode==TFM_TRANSLATION && !hastranslation)
733                 t->mode= TFM_ROTATION;
734 }
735
736
737 /* -------- Auto-IK ---------- */
738
739 /* adjust pose-channel's auto-ik chainlen */
740 static void pchan_autoik_adjust (bPoseChannel *pchan, short chainlen)
741 {
742         bConstraint *con;
743         
744         /* don't bother to search if no valid constraints */
745         if ((pchan->constflag & (PCHAN_HAS_IK|PCHAN_HAS_TARGET))==0)
746                 return;
747         
748         /* check if pchan has ik-constraint */
749         for (con= pchan->constraints.first; con; con= con->next) {
750                 if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce!=0.0)) {
751                         bKinematicConstraint *data= con->data;
752                         
753                         /* only accept if a temporary one (for auto-ik) */
754                         if (data->flag & CONSTRAINT_IK_TEMP) {
755                                 /* chainlen is new chainlen, but is limited by maximum chainlen */
756                                 if ((chainlen==0) || (chainlen > data->max_rootbone))
757                                         data->rootbone= data->max_rootbone;
758                                 else
759                                         data->rootbone= chainlen;
760                         }
761                 }
762         }
763 }
764
765 /* change the chain-length of auto-ik */
766 void transform_autoik_update (TransInfo *t, short mode)
767 {
768         short *chainlen= &G.scene->toolsettings->autoik_chainlen;
769         bPoseChannel *pchan;
770         
771         /* mode determines what change to apply to chainlen */
772         if (mode == 1) {
773                 /* mode=1 is from WHEELMOUSEDOWN... increases len */
774                 (*chainlen)++;
775         }
776         else if (mode == -1) {
777                 /* mode==-1 is from WHEELMOUSEUP... decreases len */
778                 if (*chainlen > 0) (*chainlen)--;
779         }
780         
781         /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
782         if (ELEM(NULL, t->poseobj, t->poseobj->pose))
783                 return;
784         
785         /* apply to all pose-channels */
786         for (pchan=t->poseobj->pose->chanbase.first; pchan; pchan=pchan->next) {
787                 pchan_autoik_adjust(pchan, *chainlen);
788         }       
789 }
790
791 /* frees temporal IKs */
792 static void pose_grab_with_ik_clear(Object *ob)
793 {
794         bKinematicConstraint *data;
795         bPoseChannel *pchan;
796         bConstraint *con, *next;
797         
798         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
799                 /* clear all temporary lock flags */
800                 pchan->ikflag &= ~(BONE_IK_NO_XDOF_TEMP|BONE_IK_NO_YDOF_TEMP|BONE_IK_NO_ZDOF_TEMP);
801                 
802                 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
803                 /* remove all temporary IK-constraints added */
804                 for (con= pchan->constraints.first; con; con= next) {
805                         next= con->next;
806                         if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
807                                 data= con->data;
808                                 if (data->flag & CONSTRAINT_IK_TEMP) {
809                                         BLI_remlink(&pchan->constraints, con);
810                                         MEM_freeN(con->data);
811                                         MEM_freeN(con);
812                                         continue;
813                                 }
814                                 pchan->constflag |= PCHAN_HAS_IK;
815                                 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
816                                         pchan->constflag |= PCHAN_HAS_TARGET;
817                         }
818                 }
819         }
820 }
821
822 /* adds the IK to pchan - returns if added */
823 static short pose_grab_with_ik_add(bPoseChannel *pchan)
824 {
825         bKinematicConstraint *data;
826         bConstraint *con;
827         bConstraint *targetless = 0;
828         
829         /* Sanity check */
830         if (pchan == NULL) 
831                 return 0;
832         
833         /* Rule: not if there's already an IK on this channel */
834         for (con= pchan->constraints.first; con; con= con->next) {
835                 if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
836                         bKinematicConstraint *data= con->data;
837                         if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) {
838                                 targetless = con;
839                                 /* but, if this is a targetless IK, we make it auto anyway (for the children loop) */
840                                 if (con->enforce!=0.0) {
841                                         targetless->flag |= CONSTRAINT_IK_AUTO;
842                                         return 0;
843                                 }
844                         }
845                         if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0))
846                                 return 0;
847                 }
848         }
849         
850         // TRANSFORM_FIX_ME
851         //con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
852         BLI_addtail(&pchan->constraints, con);
853         pchan->constflag |= (PCHAN_HAS_IK|PCHAN_HAS_TARGET);    /* for draw, but also for detecting while pose solving */
854         data= con->data;
855         if (targetless) { /* if exists use values from last targetless IK-constraint as base */
856                 *data = *((bKinematicConstraint*)targetless->data);
857         }
858         else
859                 data->flag= CONSTRAINT_IK_TIP;
860         data->flag |= CONSTRAINT_IK_TEMP|CONSTRAINT_IK_AUTO;
861         VECCOPY(data->grabtarget, pchan->pose_tail);
862         data->rootbone= 1;
863         
864         /* we include only a connected chain */
865         while ((pchan) && (pchan->bone->flag & BONE_CONNECTED)) {
866                 /* here, we set ik-settings for bone from pchan->protectflag */
867                 if (pchan->protectflag & OB_LOCK_ROTX) pchan->ikflag |= BONE_IK_NO_XDOF_TEMP;
868                 if (pchan->protectflag & OB_LOCK_ROTY) pchan->ikflag |= BONE_IK_NO_YDOF_TEMP;
869                 if (pchan->protectflag & OB_LOCK_ROTZ) pchan->ikflag |= BONE_IK_NO_ZDOF_TEMP;
870                 
871                 /* now we count this pchan as being included */
872                 data->rootbone++;
873                 pchan= pchan->parent;
874         }
875         
876         /* make a copy of maximum chain-length */
877         data->max_rootbone= data->rootbone;
878         
879         return 1;
880 }
881
882 /* bone is a candidate to get IK, but we don't do it if it has children connected */
883 static short pose_grab_with_ik_children(bPose *pose, Bone *bone)
884 {
885         Bone *bonec;
886         short wentdeeper=0, added=0;
887
888         /* go deeper if children & children are connected */
889         for (bonec= bone->childbase.first; bonec; bonec= bonec->next) {
890                 if (bonec->flag & BONE_CONNECTED) {
891                         wentdeeper= 1;
892                         added+= pose_grab_with_ik_children(pose, bonec);
893                 }
894         }
895         if (wentdeeper==0) {
896                 bPoseChannel *pchan= get_pose_channel(pose, bone->name);
897                 if (pchan)
898                         added+= pose_grab_with_ik_add(pchan);
899         }
900         
901         return added;
902 }
903
904 /* main call which adds temporal IK chains */
905 static short pose_grab_with_ik(Object *ob)
906 {
907         bArmature *arm;
908         bPoseChannel *pchan, *parent;
909         Bone *bonec;
910         short tot_ik= 0;
911         
912         if ((ob==NULL) || (ob->pose==NULL) || (ob->flag & OB_POSEMODE)==0)
913                 return 0;
914                 
915         arm = ob->data;
916         
917         /* Rule: allow multiple Bones (but they must be selected, and only one ik-solver per chain should get added) */
918         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
919                 if (pchan->bone->layer & arm->layer) {
920                         if (pchan->bone->flag & BONE_SELECTED) {
921                                 /* Rule: no IK for solitatry (unconnected) bones */
922                                 for (bonec=pchan->bone->childbase.first; bonec; bonec=bonec->next) {
923                                         if (bonec->flag & BONE_CONNECTED) {
924                                                 break;
925                                         }
926                                 }
927                                 if ((pchan->bone->flag & BONE_CONNECTED)==0 && (bonec == NULL))
928                                         continue;
929                                 
930                                 /* rule: if selected Bone is not a root bone, it gets a temporal IK */
931                                 if (pchan->parent) {
932                                         /* only adds if there's no IK yet (and no parent bone was selected) */
933                                         for (parent= pchan->parent; parent; parent= parent->parent) {
934                                                 if (parent->bone->flag & BONE_SELECTED)
935                                                         break;
936                                         }
937                                         if (parent == NULL)
938                                                 tot_ik += pose_grab_with_ik_add(pchan);
939                                 }
940                                 else {
941                                         /* rule: go over the children and add IK to the tips */
942                                         tot_ik += pose_grab_with_ik_children(ob->pose, pchan->bone);
943                                 }
944                         }
945                 }
946         }
947         
948         return (tot_ik) ? 1 : 0;
949 }       
950
951
952 /* only called with pose mode active object now */
953 static void createTransPose(bContext *C, TransInfo *t, Object *ob)
954 {
955         // TRANSFORM_FIX_ME
956 #if 0
957         bArmature *arm;
958         bPoseChannel *pchan;
959         TransData *td;
960         TransDataExtension *tdx;
961         short ik_on= 0;
962         int i;
963         
964         t->total= 0;
965         
966         /* check validity of state */
967         arm=get_armature (ob);
968         if (arm==NULL || ob->pose==NULL) return;
969         
970         if (arm->flag & ARM_RESTPOS) {
971                 if(ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
972                         notice("Pose edit not possible while Rest Position is enabled");
973                         return;
974                 }
975         }
976         if (!(ob->lay & G.vd->lay)) return;
977
978         /* do we need to add temporal IK chains? */
979         if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
980                 ik_on= pose_grab_with_ik(ob);
981                 if (ik_on) t->flag |= T_AUTOIK;
982         }
983         
984         /* set flags and count total (warning, can change transform to rotate) */
985         set_pose_transflags(t, ob);
986         
987         if(t->total==0) return;
988
989         t->flag |= T_POSE;
990         t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
991         
992         /* make sure the lock is set OK, unlock can be accidentally saved? */
993         ob->pose->flag |= POSE_LOCKED;
994         ob->pose->flag &= ~POSE_DO_UNLOCK;
995
996         /* init trans data */
997     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
998     tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
999         for(i=0; i<t->total; i++, td++, tdx++) {
1000                 td->ext= tdx;
1001                 td->tdi = NULL;
1002                 td->val = NULL;
1003         }       
1004         
1005         /* use pose channels to fill trans data */
1006         td= t->data;
1007         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1008                 if(pchan->bone->flag & BONE_TRANSFORM) {
1009                         add_pose_transdata(t, pchan, ob, td);
1010                         td++;
1011                 }
1012         }
1013         
1014         if(td != (t->data+t->total)) printf("Bone selection count error\n");
1015         
1016         /* initialise initial auto=ik chainlen's? */
1017         if (ik_on) transform_autoik_update(t, 0);
1018 #endif
1019 }
1020
1021 /* ********************* armature ************** */
1022
1023 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1024 {
1025         // TRANSFORM_FIX_ME
1026 #if 0
1027         EditBone *ebo;
1028         bArmature *arm= t->obedit->data;
1029         TransData *td;
1030         float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1031
1032         t->total = 0;
1033         for (ebo=G.edbo.first;ebo;ebo=ebo->next) {
1034                 if(ebo->layer & arm->layer) {
1035                         if (t->mode==TFM_BONESIZE) {
1036                                 if (ebo->flag & BONE_SELECTED)
1037                                         t->total++;
1038                         }
1039                         else if (t->mode==TFM_BONE_ROLL) {
1040                                 if (ebo->flag & BONE_SELECTED)
1041                                         t->total++;
1042                         }
1043                         else {
1044                                 if (ebo->flag & BONE_TIPSEL)
1045                                         t->total++;
1046                                 if (ebo->flag & BONE_ROOTSEL)
1047                                         t->total++;
1048                         }
1049                 }
1050         }
1051
1052     if (!t->total) return;
1053         
1054         Mat3CpyMat4(mtx, t->obedit->obmat);
1055         Mat3Inv(smtx, mtx);
1056
1057     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1058         
1059         for (ebo=G.edbo.first;ebo;ebo=ebo->next){
1060                 ebo->oldlength= ebo->length;    // length==0.0 on extrude, used for scaling radius of bone points
1061                 
1062                 if(ebo->layer & arm->layer) {
1063                         if (t->mode==TFM_BONE_ENVELOPE) {
1064                                 
1065                                 if (ebo->flag & BONE_ROOTSEL){
1066                                         td->val= &ebo->rad_head;
1067                                         td->ival= *td->val;
1068                                         
1069                                         VECCOPY (td->center, ebo->head);
1070                                         td->flag= TD_SELECTED;
1071                                         
1072                                         Mat3CpyMat3(td->smtx, smtx);
1073                                         Mat3CpyMat3(td->mtx, mtx);
1074                                         
1075                                         td->loc = NULL;
1076                                         td->ext = NULL;
1077                                         td->tdi = NULL;
1078                                         
1079                                         td++;
1080                                 }
1081                                 if (ebo->flag & BONE_TIPSEL){
1082                                         td->val= &ebo->rad_tail;
1083                                         td->ival= *td->val;
1084                                         VECCOPY (td->center, ebo->tail);
1085                                         td->flag= TD_SELECTED;
1086                                         
1087                                         Mat3CpyMat3(td->smtx, smtx);
1088                                         Mat3CpyMat3(td->mtx, mtx);
1089                                         
1090                                         td->loc = NULL;
1091                                         td->ext = NULL;
1092                                         td->tdi = NULL;
1093                                         
1094                                         td++;
1095                                 }
1096                                 
1097                         }
1098                         else if (t->mode==TFM_BONESIZE) {
1099                                 if (ebo->flag & BONE_SELECTED) {
1100                                         if(arm->drawtype==ARM_ENVELOPE) {
1101                                                 td->loc= NULL;
1102                                                 td->val= &ebo->dist;
1103                                                 td->ival= ebo->dist;
1104                                         }
1105                                         else {
1106                                                 // abusive storage of scale in the loc pointer :)
1107                                                 td->loc= &ebo->xwidth;
1108                                                 VECCOPY (td->iloc, td->loc);
1109                                                 td->val= NULL;
1110                                         }
1111                                         VECCOPY (td->center, ebo->head);
1112                                         td->flag= TD_SELECTED;
1113                                         
1114                                         /* use local bone matrix */
1115                                         VecSubf(delta, ebo->tail, ebo->head);   
1116                                         vec_roll_to_mat3(delta, ebo->roll, bonemat);
1117                                         Mat3MulMat3(td->mtx, mtx, bonemat);
1118                                         Mat3Inv(td->smtx, td->mtx);
1119                                         
1120                                         Mat3CpyMat3(td->axismtx, td->mtx);
1121                                         Mat3Ortho(td->axismtx);
1122
1123                                         td->ext = NULL;
1124                                         td->tdi = NULL;
1125                                         
1126                                         td++;
1127                                 }
1128                         }
1129                         else if (t->mode==TFM_BONE_ROLL) {
1130                                 if (ebo->flag & BONE_SELECTED) {
1131                                         td->loc= NULL;
1132                                         td->val= &(ebo->roll);
1133                                         td->ival= ebo->roll;
1134                                         
1135                                         VECCOPY (td->center, ebo->head);
1136                                         td->flag= TD_SELECTED;
1137
1138                                         td->ext = NULL;
1139                                         td->tdi = NULL;
1140                                         
1141                                         td++;
1142                                 }
1143                         }
1144                         else {
1145                                 if (ebo->flag & BONE_TIPSEL){
1146                                         VECCOPY (td->iloc, ebo->tail);
1147                                         VECCOPY (td->center, td->iloc);
1148                                         td->loc= ebo->tail;
1149                                         td->flag= TD_SELECTED;
1150                                         if (ebo->flag & BONE_EDITMODE_LOCKED)
1151                                                 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1152
1153                                         Mat3CpyMat3(td->smtx, smtx);
1154                                         Mat3CpyMat3(td->mtx, mtx);
1155
1156                                         VecSubf(delta, ebo->tail, ebo->head);   
1157                                         vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1158
1159                                         if ((ebo->flag & BONE_ROOTSEL) == 0)
1160                                         {
1161                                                 td->extra = ebo;
1162                                         }
1163
1164                                         td->ext = NULL;
1165                                         td->tdi = NULL;
1166                                         td->val = NULL;
1167
1168                                         td++;
1169                                 }
1170                                 if (ebo->flag & BONE_ROOTSEL){
1171                                         VECCOPY (td->iloc, ebo->head);
1172                                         VECCOPY (td->center, td->iloc);
1173                                         td->loc= ebo->head;
1174                                         td->flag= TD_SELECTED;
1175                                         if (ebo->flag & BONE_EDITMODE_LOCKED)
1176                                                 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1177
1178                                         Mat3CpyMat3(td->smtx, smtx);
1179                                         Mat3CpyMat3(td->mtx, mtx);
1180
1181                                         VecSubf(delta, ebo->tail, ebo->head);   
1182                                         vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1183
1184                                         td->extra = ebo; /* to fix roll */
1185
1186                                         td->ext = NULL;
1187                                         td->tdi = NULL;
1188                                         td->val = NULL;
1189
1190                                         td++;
1191                                 }
1192                         }
1193                 }
1194         }
1195 #endif
1196 }
1197
1198 /* ********************* meta elements ********* */
1199
1200 static void createTransMBallVerts(bContext *C, TransInfo *t)
1201 {
1202         // TRANSFORM_FIX_ME
1203 #if 0
1204         MetaElem *ml;
1205         TransData *td;
1206         TransDataExtension *tx;
1207         float mtx[3][3], smtx[3][3];
1208         int count=0, countsel=0;
1209         int propmode = t->flag & T_PROP_EDIT;
1210
1211         /* count totals */
1212         for(ml= editelems.first; ml; ml= ml->next) {
1213                 if(ml->flag & SELECT) countsel++;
1214                 if(propmode) count++;
1215         }
1216
1217         /* note: in prop mode we need at least 1 selected */
1218         if (countsel==0) return;
1219         
1220         if(propmode) t->total = count; 
1221         else t->total = countsel;
1222         
1223         td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1224         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1225
1226         Mat3CpyMat4(mtx, t->obedit->obmat);
1227         Mat3Inv(smtx, mtx);
1228     
1229         for(ml= editelems.first; ml; ml= ml->next) {
1230                 if(propmode || (ml->flag & SELECT)) {
1231                         td->loc= &ml->x;
1232                         VECCOPY(td->iloc, td->loc);
1233                         VECCOPY(td->center, td->loc);
1234
1235                         if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1236                         else td->flag= TD_USEQUAT;
1237
1238                         Mat3CpyMat3(td->smtx, smtx);
1239                         Mat3CpyMat3(td->mtx, mtx);
1240
1241                         td->ext = tx;
1242                         td->tdi = NULL;
1243
1244                         /* Radius of MetaElem (mass of MetaElem influence) */
1245                         if(ml->flag & MB_SCALE_RAD){
1246                                 td->val = &ml->rad;
1247                                 td->ival = ml->rad;
1248                         }
1249                         else{
1250                                 td->val = &ml->s;
1251                                 td->ival = ml->s;
1252                         }
1253
1254                         /* expx/expy/expz determine "shape" of some MetaElem types */
1255                         tx->size = &ml->expx;
1256                         tx->isize[0] = ml->expx;
1257                         tx->isize[1] = ml->expy;
1258                         tx->isize[2] = ml->expz;
1259
1260                         /* quat is used for rotation of MetaElem */
1261                         tx->quat = ml->quat;
1262                         QUATCOPY(tx->iquat, ml->quat);
1263
1264                         tx->rot = NULL;
1265
1266                         td++;
1267                         tx++;
1268                 }
1269         }
1270 #endif
1271 }
1272
1273 /* ********************* curve/surface ********* */
1274
1275 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1276         TransData *td, *td_near = NULL;
1277         for (td = head; td<=tail; td++) {
1278                 if (td->flag & TD_SELECTED) {
1279                         td_near = td;
1280                         td->dist = 0.0f;
1281                 }
1282                 else if(td_near) {
1283                         float dist;
1284                         dist = VecLenf(td_near->center, td->center);
1285                         if (dist < (td-1)->dist) {
1286                                 td->dist = (td-1)->dist;
1287                         }
1288                         else {
1289                                 td->dist = dist;
1290                         }
1291                 }
1292                 else {
1293                         td->dist = MAXFLOAT;
1294                         td->flag |= TD_NOTCONNECTED;
1295                 }
1296         }
1297         td_near = NULL;
1298         for (td = tail; td>=head; td--) {
1299                 if (td->flag & TD_SELECTED) {
1300                         td_near = td;
1301                         td->dist = 0.0f;
1302                 }
1303                 else if(td_near) {
1304                         float dist;
1305                         dist = VecLenf(td_near->center, td->center);
1306                         if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1307                                 td->flag &= ~TD_NOTCONNECTED;
1308                                 if (dist < (td+1)->dist) {
1309                                         td->dist = (td+1)->dist;
1310                                 }
1311                                 else {
1312                                         td->dist = dist;
1313                                 }
1314                         }
1315                 }
1316         }
1317 }
1318
1319 /* Utility function for getting the handle data from bezier's */
1320 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1321         TransDataCurveHandleFlags *hdata;
1322         td->flag |= TD_BEZTRIPLE;
1323         hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1324         hdata->ih1 = bezt->h1;
1325         hdata->h1 = &bezt->h1;
1326         hdata->ih2 = bezt->h2; /* incase the second is not selected */
1327         hdata->h2 = &bezt->h2;
1328         return hdata;
1329 }
1330
1331 static void createTransCurveVerts(bContext *C, TransInfo *t)
1332 {
1333         // TRANSFORM_FIX_ME
1334 #if 0
1335         TransData *td = NULL;
1336         Nurb *nu;
1337         BezTriple *bezt;
1338         BPoint *bp;
1339         float mtx[3][3], smtx[3][3];
1340         int a;
1341         int count=0, countsel=0;
1342         int propmode = t->flag & T_PROP_EDIT;
1343
1344         /* count total of vertices, check identical as in 2nd loop for making transdata! */
1345         for(nu= editNurb.first; nu; nu= nu->next) {
1346                 if((nu->type & 7)==CU_BEZIER) {
1347                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1348                                 if(bezt->hide==0) {
1349                                         if (G.f & G_HIDDENHANDLES) {
1350                                                 if(bezt->f2 & SELECT) countsel+=3;
1351                                                 if(propmode) count+= 3;
1352                                         } else {
1353                                                 if(bezt->f1 & SELECT) countsel++;
1354                                                 if(bezt->f2 & SELECT) countsel++;
1355                                                 if(bezt->f3 & SELECT) countsel++;
1356                                                 if(propmode) count+= 3;
1357                                         }
1358                                 }
1359                         }
1360                 }
1361                 else {
1362                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1363                                 if(bp->hide==0) {
1364                                         if(propmode) count++;
1365                                         if(bp->f1 & SELECT) countsel++;
1366                                 }
1367                         }
1368                 }
1369         }
1370         /* note: in prop mode we need at least 1 selected */
1371         if (countsel==0) return;
1372         
1373         if(propmode) t->total = count; 
1374         else t->total = countsel;
1375         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1376
1377         Mat3CpyMat4(mtx, t->obedit->obmat);
1378         Mat3Inv(smtx, mtx);
1379         
1380     td = t->data;
1381         for(nu= editNurb.first; nu; nu= nu->next) {
1382                 if((nu->type & 7)==CU_BEZIER) {
1383                         TransData *head, *tail;
1384                         head = tail = td;
1385                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1386                                 if(bezt->hide==0) {
1387                                         TransDataCurveHandleFlags *hdata = NULL;
1388                                         
1389                                         if(             propmode ||
1390                                                         ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1391                                                         ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1392                                           ) {
1393                                                 VECCOPY(td->iloc, bezt->vec[0]);
1394                                                 td->loc= bezt->vec[0];
1395                                                 VECCOPY(td->center, bezt->vec[1]);
1396                                                 if (G.f & G_HIDDENHANDLES) {
1397                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1398                                                         else td->flag= 0;
1399                                                 } else {
1400                                                         if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1401                                                         else td->flag= 0;
1402                                                 }
1403                                                 td->ext = NULL;
1404                                                 td->tdi = NULL;
1405                                                 td->val = NULL;
1406                                                 
1407                                                 hdata = initTransDataCurveHandes(td, bezt);
1408
1409                                                 Mat3CpyMat3(td->smtx, smtx);
1410                                                 Mat3CpyMat3(td->mtx, mtx);
1411
1412                                                 td++;
1413                                                 count++;
1414                                                 tail++;
1415                                         }
1416                                         
1417                                         /* This is the Curve Point, the other two are handles */
1418                                         if(propmode || (bezt->f2 & SELECT)) {
1419                                                 VECCOPY(td->iloc, bezt->vec[1]);
1420                                                 td->loc= bezt->vec[1];
1421                                                 VECCOPY(td->center, td->loc);
1422                                                 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1423                                                 else td->flag= 0;
1424                                                 td->ext = NULL;
1425                                                 td->tdi = NULL;
1426                                                 
1427                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1428                                                         td->val = &(bezt->radius);
1429                                                         td->ival = bezt->radius;
1430                                                 } else if (t->mode==TFM_TILT) {
1431                                                         td->val = &(bezt->alfa);
1432                                                         td->ival = bezt->alfa;
1433                                                 } else {
1434                                                         td->val = NULL;
1435                                                 }
1436
1437                                                 Mat3CpyMat3(td->smtx, smtx);
1438                                                 Mat3CpyMat3(td->mtx, mtx);
1439                                                 
1440                                                 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1441                                                 /* If the middle is selected but the sides arnt, this is needed */
1442                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1443                                                         hdata = initTransDataCurveHandes(td, bezt);
1444                                                 }
1445                                                 
1446                                                 td++;
1447                                                 count++;
1448                                                 tail++;
1449                                         }
1450                                         if(             propmode ||
1451                                                         ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1452                                                         ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1453                                           ) {
1454                                                 VECCOPY(td->iloc, bezt->vec[2]);
1455                                                 td->loc= bezt->vec[2];
1456                                                 VECCOPY(td->center, bezt->vec[1]);
1457                                                 if (G.f & G_HIDDENHANDLES) {
1458                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1459                                                         else td->flag= 0;
1460                                                 } else {
1461                                                         if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1462                                                         else td->flag= 0;
1463                                                 }
1464                                                 td->ext = NULL;
1465                                                 td->tdi = NULL;
1466                                                 td->val = NULL;
1467
1468                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1469                                                         hdata = initTransDataCurveHandes(td, bezt);
1470                                                 }
1471                                                 
1472                                                 Mat3CpyMat3(td->smtx, smtx);
1473                                                 Mat3CpyMat3(td->mtx, mtx);
1474
1475                                                 td++;
1476                                                 count++;
1477                                                 tail++;
1478                                         }
1479                                 }
1480                                 else if (propmode && head != tail) {
1481                                         calc_distanceCurveVerts(head, tail-1);
1482                                         head = tail;
1483                                 }
1484                         }
1485                         if (propmode && head != tail)
1486                                 calc_distanceCurveVerts(head, tail-1);
1487                         
1488                         /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1489                          * but for now just dont change handle types */
1490                         if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1491                                 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1492                 }
1493                 else {
1494                         TransData *head, *tail;
1495                         head = tail = td;
1496                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1497                                 if(bp->hide==0) {
1498                                         if(propmode || (bp->f1 & SELECT)) {
1499                                                 VECCOPY(td->iloc, bp->vec);
1500                                                 td->loc= bp->vec;
1501                                                 VECCOPY(td->center, td->loc);
1502                                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1503                                                 else td->flag= 0;
1504                                                 td->ext = NULL;
1505                                                 td->tdi = NULL;
1506                                                 
1507                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1508                                                         td->val = &(bp->radius);
1509                                                         td->ival = bp->radius;
1510                                                 } else {
1511                                                         td->val = &(bp->alfa);
1512                                                         td->ival = bp->alfa;
1513                                                 }
1514
1515                                                 Mat3CpyMat3(td->smtx, smtx);
1516                                                 Mat3CpyMat3(td->mtx, mtx);
1517
1518                                                 td++;
1519                                                 count++;
1520                                                 tail++;
1521                                         }
1522                                 }
1523                                 else if (propmode && head != tail) {
1524                                         calc_distanceCurveVerts(head, tail-1);
1525                                         head = tail;
1526                                 }
1527                         }
1528                         if (propmode && head != tail)
1529                                 calc_distanceCurveVerts(head, tail-1);
1530                 }
1531         }
1532 #endif
1533 }
1534
1535 /* ********************* lattice *************** */
1536
1537 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1538 {
1539         // TRANSFORM_FIX_ME
1540 #if 0
1541         TransData *td = NULL;
1542         BPoint *bp;
1543         float mtx[3][3], smtx[3][3];
1544         int a;
1545         int count=0, countsel=0;
1546         int propmode = t->flag & T_PROP_EDIT;
1547
1548         bp= editLatt->def;
1549         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1550         while(a--) {
1551                 if(bp->hide==0) {
1552                         if(bp->f1 & SELECT) countsel++;
1553                         if(propmode) count++;
1554                 }
1555                 bp++;
1556         }
1557         
1558         /* note: in prop mode we need at least 1 selected */
1559         if (countsel==0) return;
1560         
1561         if(propmode) t->total = count; 
1562         else t->total = countsel;
1563         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1564         
1565         Mat3CpyMat4(mtx, t->obedit->obmat);
1566         Mat3Inv(smtx, mtx);
1567
1568         td = t->data;
1569         bp= editLatt->def;
1570         a= editLatt->pntsu*editLatt->pntsv*editLatt->pntsw;
1571         while(a--) {
1572                 if(propmode || (bp->f1 & SELECT)) {
1573                         if(bp->hide==0) {
1574                                 VECCOPY(td->iloc, bp->vec);
1575                                 td->loc= bp->vec;
1576                                 VECCOPY(td->center, td->loc);
1577                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1578                                 else td->flag= 0;
1579                                 Mat3CpyMat3(td->smtx, smtx);
1580                                 Mat3CpyMat3(td->mtx, mtx);
1581
1582                                 td->ext = NULL;
1583                                 td->tdi = NULL;
1584                                 td->val = NULL;
1585
1586                                 td++;
1587                                 count++;
1588                         }
1589                 }
1590                 bp++;
1591         }
1592 #endif
1593 }
1594
1595 /* ******************* particle edit **************** */
1596 static void createTransParticleVerts(bContext *C, TransInfo *t)
1597 {
1598         // TRANSFORM_FIX_ME
1599 #if 0
1600         TransData *td = NULL;
1601         TransDataExtension *tx;
1602         Base *base = BASACT;
1603         Object *ob = OBACT;
1604         ParticleSystem *psys = PE_get_current(ob);
1605         ParticleSystemModifierData *psmd = NULL;
1606         ParticleEditSettings *pset = PE_settings();
1607         ParticleData *pa = NULL;
1608         ParticleEdit *edit;
1609         ParticleEditKey *key;
1610         float mat[4][4];
1611         int i,k, totpart, transformparticle;
1612         int count = 0, hasselected = 0;
1613         int propmode = t->flag & T_PROP_EDIT;
1614
1615         if(psys==NULL || G.scene->selectmode==SCE_SELECT_PATH) return;
1616
1617         psmd = psys_get_modifier(ob,psys);
1618
1619         edit = psys->edit;
1620         totpart = psys->totpart;
1621         base->flag |= BA_HAS_RECALC_DATA;
1622
1623         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1624                 pa->flag &= ~PARS_TRANSFORM;
1625                 transformparticle= 0;
1626
1627                 if((pa->flag & PARS_HIDE)==0) {
1628                         for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1629                                 if((key->flag&PEK_HIDE)==0) {
1630                                         if(key->flag&PEK_SELECT) {
1631                                                 hasselected= 1;
1632                                                 transformparticle= 1;
1633                                         }
1634                                         else if(propmode)
1635                                                 transformparticle= 1;
1636                                 }
1637                         }
1638                 }
1639
1640                 if(transformparticle) {
1641                         count += pa->totkey;
1642                         pa->flag |= PARS_TRANSFORM;
1643                 }
1644         }
1645         
1646         /* note: in prop mode we need at least 1 selected */
1647         if (hasselected==0) return;
1648         
1649         t->total = count;
1650         td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1651
1652         if(t->mode == TFM_BAKE_TIME)
1653                 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1654         else
1655                 tx = t->ext = NULL;
1656
1657         Mat4One(mat);
1658
1659         Mat4Invert(ob->imat,ob->obmat);
1660
1661         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1662                 TransData *head, *tail;
1663                 head = tail = td;
1664
1665                 if(!(pa->flag & PARS_TRANSFORM)) continue;
1666
1667                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1668
1669                 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1670                         VECCOPY(key->world_co, key->co);
1671                         Mat4MulVecfl(mat, key->world_co);
1672                         td->loc = key->world_co;
1673
1674                         VECCOPY(td->iloc, td->loc);
1675                         VECCOPY(td->center, td->loc);
1676
1677                         if(key->flag & PEK_SELECT)
1678                                 td->flag |= TD_SELECTED;
1679                         else if(!propmode)
1680                                 td->flag |= TD_SKIP;
1681
1682                         Mat3One(td->mtx);
1683                         Mat3One(td->smtx);
1684
1685                         /* don't allow moving roots */
1686                         if(k==0 && pset->flag & PE_LOCK_FIRST)
1687                                 td->protectflag |= OB_LOCK_LOC;
1688
1689                         td->ob = ob;
1690                         td->ext = tx;
1691                         td->tdi = NULL;
1692                         if(t->mode == TFM_BAKE_TIME) {
1693                                 td->val = key->time;
1694                                 td->ival = *(key->time);
1695                                 /* abuse size and quat for min/max values */
1696                                 td->flag |= TD_NO_EXT;
1697                                 if(k==0) tx->size = 0;
1698                                 else tx->size = (key - 1)->time;
1699
1700                                 if(k == pa->totkey - 1) tx->quat = 0;
1701                                 else tx->quat = (key + 1)->time;
1702                         }
1703
1704                         td++;
1705                         if(tx)
1706                                 tx++;
1707                         tail++;
1708                 }
1709                 if (propmode && head != tail)
1710                         calc_distanceCurveVerts(head, tail - 1);
1711         }
1712 #endif
1713 }
1714
1715 void flushTransParticles(TransInfo *t)
1716 {
1717 #if 0 // TRANSFORM_FIX_ME
1718         Scene *scene = t->scene;
1719         Object *ob = OBACT;
1720         ParticleSystem *psys = PE_get_current(ob);
1721         ParticleSystemModifierData *psmd;
1722         ParticleData *pa;
1723         ParticleEditKey *key;
1724         TransData *td;
1725         float mat[4][4], imat[4][4], co[3];
1726         int i, k, propmode = t->flag & T_PROP_EDIT;
1727
1728         psmd = psys_get_modifier(ob, psys);
1729
1730         /* we do transform in world space, so flush world space position
1731          * back to particle local space */
1732         td= t->data;
1733         for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1734                 if(!(pa->flag & PARS_TRANSFORM)) continue;
1735
1736                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1737                 Mat4Invert(imat,mat);
1738
1739                 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1740                         VECCOPY(co, key->world_co);
1741                         Mat4MulVecfl(imat, co);
1742
1743                         /* optimization for proportional edit */
1744                         if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1745                                 VECCOPY(key->co, co);
1746                                 pa->flag |= PARS_EDIT_RECALC;
1747                         }
1748                 }
1749         }
1750
1751         PE_update_object(OBACT, 1);
1752 #endif
1753 }
1754
1755 /* ********************* mesh ****************** */
1756
1757 /* proportional distance based on connectivity  */
1758 #define E_VEC(a)        (vectors + (3 * (a)->tmp.l))
1759 #define E_NEAR(a)       (nears[((a)->tmp.l)])
1760 #define THRESHOLD       0.0001f
1761 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1762 {
1763         EditVert *eve;
1764         EditEdge *eed;
1765         int i= 0, done= 1;
1766
1767         /* f2 flag is used for 'selection' */
1768         /* tmp.l is offset on scratch array   */
1769         for(eve= em->verts.first; eve; eve= eve->next) {
1770                 if(eve->h==0) {
1771                         eve->tmp.l = i++;
1772
1773                         if(eve->f & SELECT) {
1774                                 eve->f2= 2;
1775                                 E_NEAR(eve) = eve;
1776                                 E_VEC(eve)[0] = 0.0f;
1777                                 E_VEC(eve)[1] = 0.0f;
1778                                 E_VEC(eve)[2] = 0.0f;
1779                         }
1780                         else {
1781                                 eve->f2 = 0;
1782                         }
1783                 }
1784         }
1785
1786
1787         /* Floodfill routine */
1788         /*
1789         At worst this is n*n of complexity where n is number of edges 
1790         Best case would be n if the list is ordered perfectly.
1791         Estimate is n log n in average (so not too bad)
1792         */
1793         while(done) {
1794                 done= 0;
1795                 
1796                 for(eed= em->edges.first; eed; eed= eed->next) {
1797                         if(eed->h==0) {
1798                                 EditVert *v1= eed->v1, *v2= eed->v2;
1799                                 float *vec2 = E_VEC(v2);
1800                                 float *vec1 = E_VEC(v1);
1801
1802                                 if (v1->f2 + v2->f2 == 4)
1803                                         continue;
1804
1805                                 if (v1->f2) {
1806                                         if (v2->f2) {
1807                                                 float nvec[3];
1808                                                 float len1 = VecLength(vec1);
1809                                                 float len2 = VecLength(vec2);
1810                                                 float lenn;
1811                                                 /* for v2 if not selected */
1812                                                 if (v2->f2 != 2) {
1813                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1814                                                         lenn = VecLength(nvec);
1815                                                         /* 1 < n < 2 */
1816                                                         if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1817                                                                 VECCOPY(vec2, nvec);
1818                                                                 E_NEAR(v2) = E_NEAR(v1);
1819                                                                 done = 1;
1820                                                         }
1821                                                         /* n < 1 < 2 */
1822                                                         else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1823                                                                 VECCOPY(vec2, vec1);
1824                                                                 E_NEAR(v2) = E_NEAR(v1);
1825                                                                 done = 1;
1826                                                         }
1827                                                 }
1828                                                 /* for v1 if not selected */
1829                                                 if (v1->f2 != 2) {
1830                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1831                                                         lenn = VecLength(nvec);
1832                                                         /* 2 < n < 1 */
1833                                                         if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1834                                                                 VECCOPY(vec1, nvec);
1835                                                                 E_NEAR(v1) = E_NEAR(v2);
1836                                                                 done = 1;
1837                                                         }
1838                                                         /* n < 2 < 1 */
1839                                                         else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1840                                                                 VECCOPY(vec1, vec2);
1841                                                                 E_NEAR(v1) = E_NEAR(v2);
1842                                                                 done = 1;
1843                                                         }
1844                                                 }
1845                                         }
1846                                         else {
1847                                                 v2->f2 = 1;
1848                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1849                                                 /* 2 < 1 */
1850                                                 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1851                                                         VECCOPY(vec2, vec1);
1852                                                 }
1853                                                 E_NEAR(v2) = E_NEAR(v1);
1854                                                 done = 1;
1855                                         }
1856                                 }
1857                                 else if (v2->f2) {
1858                                         v1->f2 = 1;
1859                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1860                                         /* 2 < 1 */
1861                                         if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1862                                                 VECCOPY(vec1, vec2);
1863                                         }
1864                                         E_NEAR(v1) = E_NEAR(v2);
1865                                         done = 1;
1866                                 }
1867                         }
1868                 }
1869         }
1870 }
1871
1872 /* loop-in-a-loop I know, but we need it! (ton) */
1873 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1874 {
1875         EditFace *efa;
1876         
1877         for(efa= em->faces.first; efa; efa= efa->next)
1878                 if(efa->f & SELECT)
1879                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1880                                 break;
1881         if(efa) {
1882                 VECCOPY(cent, efa->cent);
1883         }
1884 }
1885
1886 //way to overwrite what data is edited with transform
1887 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1888 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1889 {
1890         td->flag = 0;
1891         //if(key)
1892         //      td->loc = key->co;
1893         //else
1894         td->loc = eve->co;
1895         
1896         VECCOPY(td->center, td->loc);
1897         if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1898                 get_face_center(td->center, em, eve);
1899         VECCOPY(td->iloc, td->loc);
1900
1901         // Setting normals
1902         VECCOPY(td->axismtx[2], eve->no);
1903         td->axismtx[0][0]               =
1904                 td->axismtx[0][1]       =
1905                 td->axismtx[0][2]       =
1906                 td->axismtx[1][0]       =
1907                 td->axismtx[1][1]       =
1908                 td->axismtx[1][2]       = 0.0f;
1909
1910         td->ext = NULL;
1911         td->tdi = NULL;
1912         td->val = NULL;
1913         td->extra = NULL;
1914         if (t->mode == TFM_BWEIGHT) {
1915                 td->val = &(eve->bweight);
1916                 td->ival = eve->bweight;
1917         }
1918
1919 #ifdef WITH_VERSE
1920         if(eve->vvert) {
1921                 td->verse = (void*)eve->vvert;
1922                 td->flag |= TD_VERSE_VERT;
1923         }
1924         else
1925                 td->flag &= ~TD_VERSE_VERT;
1926 #endif
1927 }
1928
1929 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1930
1931 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1932 {
1933         float *vec = userData;
1934         
1935         vec+= 3*index;
1936         VECCOPY(vec, co);
1937 }
1938
1939 static int modifiers_disable_subsurf_temporary(Object *ob)
1940 {
1941         ModifierData *md;
1942         int disabled = 0;
1943         
1944         for(md=ob->modifiers.first; md; md=md->next)
1945                 if(md->type==eModifierType_Subsurf)
1946                         if(md->mode & eModifierMode_OnCage) {
1947                                 md->mode ^= eModifierMode_DisableTemporary;
1948                                 disabled= 1;
1949                         }
1950         
1951         return disabled;
1952 }
1953
1954 /* disable subsurf temporal, get mapped cos, and enable it */
1955 static float *get_crazy_mapped_editverts(TransInfo *t)
1956 {
1957         Mesh *me= t->obedit->data;
1958         DerivedMesh *dm;
1959         float *vertexcos;
1960
1961         /* disable subsurf temporal, get mapped cos, and enable it */
1962         if(modifiers_disable_subsurf_temporary(t->obedit)) {
1963                 /* need to make new derivemesh */
1964                 makeDerivedMesh(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1965         }
1966
1967         /* now get the cage */
1968         dm= editmesh_get_derived_cage(t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1969
1970         vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map");
1971         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1972         
1973         dm->release(dm);
1974         
1975         /* set back the flag, no new cage needs to be built, transform does it */
1976         modifiers_disable_subsurf_temporary(t->obedit);
1977         
1978         return vertexcos;
1979 }
1980
1981 #define TAN_MAKE_VEC(a, b, c)   a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2])
1982 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1983 {
1984         float vecu[3], vecv[3];
1985         float q1[4], q2[4];
1986         
1987         TAN_MAKE_VEC(vecu, v1, v2);
1988         TAN_MAKE_VEC(vecv, v1, v3);
1989         triatoquat(v1, vecu, vecv, q1);
1990         
1991         TAN_MAKE_VEC(vecu, def1, def2);
1992         TAN_MAKE_VEC(vecv, def1, def3);
1993         triatoquat(def1, vecu, vecv, q2);
1994         
1995         QuatSub(quat, q2, q1);
1996 }
1997 #undef TAN_MAKE_VEC
1998
1999 static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
2000 {
2001         EditVert *eve, *prev;
2002         EditFace *efa;
2003         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2004         intptr_t index= 0;
2005         
2006         /* two abused locations in vertices */
2007         for(eve= em->verts.first; eve; eve= eve->next, index++) {
2008                 eve->tmp.p = NULL;
2009                 eve->prev= (EditVert *)index;
2010         }
2011         
2012         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2013         for(efa= em->faces.first; efa; efa= efa->next) {
2014                 
2015                 /* retrieve mapped coordinates */
2016                 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2017                 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2018                 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2019
2020                 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2021                 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2022                 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2023
2024                 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2025                         set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2026                         efa->v2->tmp.p= (void*)quats;
2027                         quats+= 4;
2028                 }
2029                 
2030                 if(efa->v4) {
2031                         v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2032                         co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2033
2034                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2035                                 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2036                                 efa->v1->tmp.p= (void*)quats;
2037                                 quats+= 4;
2038                         }
2039                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2040                                 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2041                                 efa->v3->tmp.p= (void*)quats;
2042                                 quats+= 4;
2043                         }
2044                         if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2045                                 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2046                                 efa->v4->tmp.p= (void*)quats;
2047                                 quats+= 4;
2048                         }
2049                 }
2050                 else {
2051                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2052                                 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2053                                 efa->v1->tmp.p= (void*)quats;
2054                                 quats+= 4;
2055                         }
2056                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2057                                 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2058                                 efa->v3->tmp.p= (void*)quats;
2059                                 quats+= 4;
2060                         }
2061                 }
2062         }
2063
2064         /* restore abused prev pointer */
2065         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2066                 eve->prev= prev;
2067
2068 }
2069
2070 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2071         BME_Vert *v;
2072         BME_TransData *vtd;
2073         TransData *tob;
2074         int i;
2075
2076         tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2077
2078         for (i=0,v=bm->verts.first;v;v=v->next) {
2079                 if ( (vtd = BME_get_transdata(td,v)) ) {
2080                         tob->loc = vtd->loc;
2081                         tob->val = &vtd->factor;
2082                         VECCOPY(tob->iloc,vtd->co);
2083                         VECCOPY(tob->center,vtd->org);
2084                         VECCOPY(tob->axismtx[0],vtd->vec);
2085                         tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2086                         tob++;
2087                         i++;
2088                 }
2089         }
2090         /* since td is a memarena, it can hold more transdata than actual elements
2091          * (i.e. we can't depend on td->len to determine the number of actual elements) */
2092         t->total = i;
2093 }
2094
2095 static void createTransEditVerts(bContext *C, TransInfo *t)
2096 {
2097         Scene *scene = CTX_data_scene(C);
2098         TransData *tob = NULL;
2099         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2100         EditVert *eve;
2101         EditVert **nears = NULL;
2102         EditVert *eve_act = NULL;
2103         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2104         float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2105         int count=0, countsel=0, a, totleft;
2106         int propmode = t->flag & T_PROP_EDIT;
2107         int mirror = 0;
2108         
2109         if ((t->options & CTX_NO_MIRROR) == 0 && (scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2110         {
2111                 mirror = 1;
2112         }
2113
2114         // transform now requires awareness for select mode, so we tag the f1 flags in verts
2115         if(scene->selectmode & SCE_SELECT_VERTEX) {
2116                 for(eve= em->verts.first; eve; eve= eve->next) {
2117                         if(eve->h==0 && (eve->f & SELECT)) 
2118                                 eve->f1= SELECT;
2119                         else
2120                                 eve->f1= 0;
2121                 }
2122         }
2123         else if(scene->selectmode & SCE_SELECT_EDGE) {
2124                 EditEdge *eed;
2125                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2126                 for(eed= em->edges.first; eed; eed= eed->next) {
2127                         if(eed->h==0 && (eed->f & SELECT))
2128                                 eed->v1->f1= eed->v2->f1= SELECT;
2129                 }
2130         }
2131         else {
2132                 EditFace *efa;
2133                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2134                 for(efa= em->faces.first; efa; efa= efa->next) {
2135                         if(efa->h==0 && (efa->f & SELECT)) {
2136                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2137                                 if(efa->v4) efa->v4->f1= SELECT;
2138                         }
2139                 }
2140         }
2141         
2142         /* now we can count */
2143         for(eve= em->verts.first; eve; eve= eve->next) {
2144                 if(eve->h==0) {
2145                         if(eve->f1) countsel++;
2146                         if(propmode) count++;
2147                 }
2148         }
2149         
2150         /* note: in prop mode we need at least 1 selected */
2151         if (countsel==0) return;
2152         
2153         /* check active */
2154         if (em->selected.last) {
2155                 EditSelection *ese = em->selected.last;
2156                 if ( ese->type == EDITVERT ) {
2157                         eve_act = (EditVert *)ese->data;
2158                 }
2159         }
2160
2161         
2162         if(propmode) {
2163                 t->total = count; 
2164         
2165                 /* allocating scratch arrays */
2166                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2167                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2168         }
2169         else t->total = countsel;
2170         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2171         
2172         Mat3CpyMat4(mtx, t->obedit->obmat);
2173         Mat3Inv(smtx, mtx);
2174
2175         if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2176         
2177         /* detect CrazySpace [tm] */
2178         if(propmode==0) {
2179                 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2180                         if(modifiers_isDeformed(t->obedit)) {
2181                                 /* check if we can use deform matrices for modifier from the
2182                                    start up to stack, they are more accurate than quats */
2183                                 totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
2184
2185                                 /* if we still have more modifiers, also do crazyspace
2186                                    correction with quats, relative to the coordinates after
2187                                    the modifiers that support deform matrices (defcos) */
2188                                 if(totleft > 0) {
2189                                         mappedcos= get_crazy_mapped_editverts(t);
2190                                         quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2191                                         set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2192                                         if(mappedcos)
2193                                                 MEM_freeN(mappedcos);
2194                                 }
2195
2196                                 if(defcos)
2197                                         MEM_freeN(defcos);
2198                         }
2199                 }
2200         }
2201         
2202         /* find out which half we do */
2203         if(mirror) {
2204                 for (eve=em->verts.first; eve; eve=eve->next) {
2205                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2206                                 if(eve->co[0]<0.0f)
2207                                         mirror = -1;
2208                                 break;
2209                         }
2210                 }
2211         }
2212         
2213         for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2214                 if(eve->h==0) {
2215                         if(propmode || eve->f1) {
2216                                 VertsToTransData(t, tob, em, eve);
2217                                 
2218                                 /* selected */
2219                                 if(eve->f1) tob->flag |= TD_SELECTED;
2220                                 
2221                                 /* active */
2222                                 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2223                                 
2224                                 if(propmode) {
2225                                         if (eve->f2) {
2226                                                 float vec[3];
2227                                                 VECCOPY(vec, E_VEC(eve));
2228                                                 Mat3MulVecfl(mtx, vec);
2229                                                 tob->dist= VecLength(vec);
2230                                         }
2231                                         else {
2232                                                 tob->flag |= TD_NOTCONNECTED;
2233                                                 tob->dist = MAXFLOAT;
2234                                         }
2235                                 }
2236                                 
2237                                 /* CrazySpace */
2238                                 if(defmats || (quats && eve->tmp.p)) {
2239                                         float mat[3][3], imat[3][3], qmat[3][3];
2240                                         
2241                                         /* use both or either quat and defmat correction */
2242                                         if(quats && eve->tmp.f) {
2243                                                 QuatToMat3(eve->tmp.p, qmat);
2244
2245                                                 if(defmats)
2246                                                         Mat3MulSerie(mat, mtx, qmat, defmats[a],
2247                                                                 NULL, NULL, NULL, NULL, NULL);
2248                                                 else
2249                                                         Mat3MulMat3(mat, mtx, qmat);
2250                                         }
2251                                         else
2252                                                 Mat3MulMat3(mat, mtx, defmats[a]);
2253
2254                                         Mat3Inv(imat, mat);
2255                                         
2256                                         Mat3CpyMat3(tob->smtx, imat);
2257                                         Mat3CpyMat3(tob->mtx, mat);
2258                                 }
2259                                 else {
2260                                         Mat3CpyMat3(tob->smtx, smtx);
2261                                         Mat3CpyMat3(tob->mtx, mtx);
2262                                 }
2263                                 
2264                                 /* Mirror? */
2265                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2266                                         EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc);   /* initializes octree on first call */
2267                                         if(vmir != eve) tob->extra = vmir;
2268                                 }
2269                                 tob++;
2270                         }
2271                 }       
2272         }
2273         if (propmode) {
2274                 MEM_freeN(vectors);
2275                 MEM_freeN(nears);
2276         }
2277         /* crazy space free */
2278         if(quats)
2279                 MEM_freeN(quats);
2280         if(defmats)
2281                 MEM_freeN(defmats);
2282 }
2283
2284 /* ********************* UV ****************** */
2285
2286 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2287 {
2288         float aspx, aspy;
2289
2290         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2291
2292         /* uv coords are scaled by aspects. this is needed for rotations and
2293            proportional editing to be consistent with the stretchted uv coords
2294            that are displayed. this also means that for display and numinput,
2295            and when the the uv coords are flushed, these are converted each time */
2296         td2d->loc[0] = uv[0]*aspx;
2297         td2d->loc[1] = uv[1]*aspy;
2298         td2d->loc[2] = 0.0f;
2299         td2d->loc2d = uv;
2300
2301         td->flag = 0;
2302         td->loc = td2d->loc;
2303         VECCOPY(td->center, td->loc);
2304         VECCOPY(td->iloc, td->loc);
2305
2306         memset(td->axismtx, 0, sizeof(td->axismtx));
2307         td->axismtx[2][2] = 1.0f;
2308
2309         td->ext= NULL; td->tdi= NULL; td->val= NULL;
2310
2311         if(selected) {
2312                 td->flag |= TD_SELECTED;
2313                 td->dist= 0.0;
2314         }
2315         else {
2316                 td->dist= MAXFLOAT;
2317         }
2318         Mat3One(td->mtx);
2319         Mat3One(td->smtx);
2320 }
2321
2322 static void createTransUVs(bContext *C, TransInfo *t)
2323 {
2324         // TRANSFORM_FIX_ME
2325 #if 0
2326         TransData *td = NULL;
2327         TransData2D *td2d = NULL;
2328         MTFace *tf;
2329         int count=0, countsel=0;
2330         int propmode = t->flag & T_PROP_EDIT;
2331         int efa_s1,efa_s2,efa_s3,efa_s4;
2332
2333         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2334         EditFace *efa;
2335         
2336         if(is_uv_tface_editing_allowed()==0) return;
2337
2338         /* count */
2339         if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2340                 for (efa= em->faces.first; efa; efa= efa->next) {
2341                         /* store face pointer for second loop, prevent second lookup */
2342                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2343                         if (simaFaceDraw_Check(efa, tf)) {
2344                                 efa->tmp.p = tf;
2345                                 
2346                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2347                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2348                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2349                                 if (efa->v4) {
2350                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2351                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2352                                                 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2353                                         }
2354                                 } else {
2355                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2356                                         if (efa_s1) countsel++; 
2357                                         if (efa_s2) countsel++; 
2358                                         if (efa_s3) countsel++;
2359                                 }
2360                         } else {
2361                                 efa->tmp.p = NULL;
2362                         }
2363                 }
2364         } else {
2365                 for (efa= em->faces.first; efa; efa= efa->next) {
2366                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2367                         if (simaFaceDraw_Check(efa, tf)) {
2368                                 efa->tmp.p = tf;
2369                                 
2370                                 if (simaUVSel_Check(efa, tf, 0)) countsel++; 
2371                                 if (simaUVSel_Check(efa, tf, 1)) countsel++; 
2372                                 if (simaUVSel_Check(efa, tf, 2)) countsel++; 
2373                                 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2374                                 if(propmode)
2375                                         count += (efa->v4)? 4: 3;
2376                         } else {
2377                                 efa->tmp.p = NULL;
2378                         }
2379                 }
2380         }
2381         
2382         /* note: in prop mode we need at least 1 selected */
2383         if (countsel==0) return;
2384         
2385         t->total= (propmode)? count: countsel;
2386         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2387         /* for each 2d uv coord a 3d vector is allocated, so that they can be
2388            treated just as if they were 3d verts */
2389         t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2390
2391         if(G.sima->flag & SI_CLIP_UV)
2392                 t->flag |= T_CLIP_UV;
2393
2394         td= t->data;
2395         td2d= t->data2d;
2396         
2397         if (G.sima->flag & SI_BE_SQUARE && !propmode) {
2398                 for (efa= em->faces.first; efa; efa= efa->next) {
2399                         tf=(MTFace *)efa->tmp.p;
2400                         if (tf) {
2401                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2402                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2403                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2404                                 
2405                                 if (efa->v4) {
2406                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2407                                         
2408                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2409                                                 /* all corners of this quad need their edges moved. so we must store TD for each */
2410
2411                                                 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2412                                                 if (!efa_s1)    td->flag |= TD_SKIP;
2413                                                 td++; td2d++;
2414
2415                                                 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2416                                                 if (!efa_s2)    td->flag |= TD_SKIP;
2417                                                 td++; td2d++;
2418
2419                                                 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2420                                                 if (!efa_s3)    td->flag |= TD_SKIP;
2421                                                 td++; td2d++;
2422
2423                                                 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2424                                                 if (!efa_s4)    td->flag |= TD_SKIP;
2425                                                 td++; td2d++;
2426                                         }
2427                                 } else {
2428                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2429                                         if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1); 
2430                                         if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1); 
2431                                         if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2432                                 }
2433                         }
2434                 }
2435         } else {
2436                 for (efa= em->faces.first; efa; efa= efa->next) {
2437                         /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2438                         if (simaFaceDraw_Check(efa, tf)) {*/
2439                         if ((tf=(MTFace *)efa->tmp.p)) {
2440                                 if (propmode) {
2441                                         UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2442                                         UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2443                                         UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2444                                         if(efa->v4)
2445                                                 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2446                                 } else {
2447                                         if(simaUVSel_Check(efa, tf, 0))                         UVsToTransData(td++, td2d++, tf->uv[0], 1);
2448                                         if(simaUVSel_Check(efa, tf, 1))                         UVsToTransData(td++, td2d++, tf->uv[1], 1);
2449                                         if(simaUVSel_Check(efa, tf, 2))                         UVsToTransData(td++, td2d++, tf->uv[2], 1);
2450                                         if(efa->v4 && simaUVSel_Check(efa, tf, 3))      UVsToTransData(td++, td2d++, tf->uv[3], 1);
2451                                 }
2452                         }
2453                 }
2454         }
2455         
2456         if (G.sima->flag & SI_LIVE_UNWRAP)
2457                 unwrap_lscm_live_begin();
2458 #endif
2459 }
2460
2461 void flushTransUVs(TransInfo *t)
2462 {
2463 #if 0 // TRANSFORM_FIX_ME
2464         TransData2D *td;
2465         int a, width, height;
2466         Object *ob= OBACT;
2467         EditMesh *em = ((Mesh *)ob->data)->edit_mesh;
2468         float aspx, aspy, invx, invy;
2469
2470         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2471         transform_width_height_tface_uv(&width, &height);
2472         invx= 1.0f/aspx;
2473         invy= 1.0f/aspy;
2474
2475         /* flush to 2d vector from internally used 3d vector */
2476         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2477                 td->loc2d[0]= td->loc[0]*invx;
2478                 td->loc2d[1]= td->loc[1]*invy;
2479                 
2480                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2481                         td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2482                         td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2483                 }
2484         }
2485         
2486         if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL)) 
2487                 be_square_tface_uv(em);
2488
2489         /* this is overkill if G.sima->lock is not set, but still needed */
2490         object_uvs_changed(ob);
2491 #endif
2492 }
2493
2494 int clipUVTransform(TransInfo *t, float *vec, int resize)
2495 {
2496 #if 0 // TRANSFORM_FIX_ME
2497         TransData *td;
2498         int a, clipx=1, clipy=1;
2499         float aspx, aspy, min[2], max[2];
2500
2501         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2502         min[0]= min[1]= 0.0f;
2503         max[0]= aspx; max[1]= aspy;
2504
2505         for(a=0, td= t->data; a<t->total; a++, td++) {
2506                 DO_MINMAX2(td->loc, min, max);
2507         }
2508
2509         if(resize) {
2510                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2511                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
2512                 else if(max[0] > aspx && t->center[0] < aspx)
2513                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2514                 else
2515                         clipx= 0;
2516
2517                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2518                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
2519                 else if(max[1] > aspy && t->center[1] < aspy)
2520                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2521                 else
2522                         clipy= 0;
2523         }
2524         else {
2525                 if(min[0] < 0.0f)
2526                         vec[0] -= min[0];
2527                 else if(max[0] > aspx)
2528                         vec[0] -= max[0]-aspx;
2529                 else
2530                         clipx= 0;
2531
2532                 if(min[1] < 0.0f)
2533                         vec[1] -= min[1];
2534                 else if(max[1] > aspy)
2535                         vec[1] -= max[1]-aspy;
2536                 else
2537                         clipy= 0;
2538         }       
2539
2540         return (clipx || clipy);
2541 #endif
2542 return 0;
2543 }
2544
2545 /* ********************* IPO EDITOR ************************* */
2546
2547 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2548  * due to bad globals that would need to be imported specially for this
2549  */
2550 static void createTransIpoData(bContext *C, TransInfo *t)
2551 {
2552         // TRANSFORM_FIX_ME
2553 #if 0
2554         /* in editipo.c due to some globals that are defined in that file... */
2555         make_ipo_transdata(t);
2556 #endif
2557 }
2558
2559 /* this function is called on recalcData to apply the transforms applied
2560  * to the transdata on to the actual keyframe data 
2561  */
2562 void flushTransIpoData(TransInfo *t)
2563 {
2564 #if 0 // TRANSFORM_FIX_ME
2565         TransData2D *td;
2566         int a;
2567         
2568         /* flush to 2d vector from internally used 3d vector */
2569         for (a=0, td= t->data2d; a<t->total; a++, td++) {
2570                 // FIXME: autosnap needs to be here...
2571                 
2572                 /* we need to unapply the nla-scaling from the time in some situations */
2573                 if (NLA_IPO_SCALED)
2574                         td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2575                 else
2576                         td->loc2d[0]= td->loc[0];
2577                 
2578                 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2579                 if ((t->data[a].flag & TD_TIMEONLY)==0)
2580                         td->loc2d[1]= td->loc[1];
2581         }
2582 #endif
2583 }
2584
2585 /* ********************* ACTION/NLA EDITOR ****************** */
2586
2587 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2588  * any other gp-frames which may reside on that frame (that are not selected).
2589  * It also makes sure gp-frames are still stored in chronological order after
2590  * transform.
2591  */
2592 static void posttrans_gpd_clean (bGPdata *gpd)
2593 {
2594         bGPDlayer *gpl;
2595         
2596         for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2597                 ListBase sel_buffer = {NULL, NULL};
2598                 bGPDframe *gpf, *gpfn;
2599                 bGPDframe *gfs, *gfsn;
2600                 
2601                 /* loop 1: loop through and isolate selected gp-frames to buffer 
2602                  * (these need to be sorted as they are isolated)
2603                  */
2604                 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2605                         short added= 0;
2606                         gpfn= gpf->next;
2607                         
2608                         if (gpf->flag & GP_FRAME_SELECT) {
2609                                 BLI_remlink(&gpl->frames, gpf);
2610                                 
2611                                 /* find place to add them in buffer
2612                                  * - go backwards as most frames will still be in order,
2613                                  *   so doing it this way will be faster 
2614                                  */
2615                                 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2616                                         /* if current (gpf) occurs after this one in buffer, add! */
2617                                         if (gfs->framenum < gpf->framenum) {
2618                                                 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2619                                                 added= 1;
2620                                                 break;
2621                                         }
2622                                 }
2623                                 if (added == 0)
2624                                         BLI_addhead(&sel_buffer, gpf);
2625                         }
2626                 }
2627                 
2628                 /* error checking: it is unlikely, but may be possible to have none selected */
2629                 if (sel_buffer.first == NULL)
2630                         continue;
2631                 
2632                 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2633                 if (gpl->frames.first == NULL) {
2634                         gpl->frames.first= sel_buffer.first;
2635                         gpl->frames.last= sel_buffer.last;
2636                         
2637                         continue;
2638                 }
2639                 
2640                 /* loop 2: remove duplicates of frames in buffers */
2641                 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2642                         gpfn= gpf->next;
2643                         
2644                         /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2645                         for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2646                                 gfsn= gfs->next;
2647                                 
2648                                 /* if this buffer frame needs to go before current, add it! */
2649                                 if (gfs->framenum < gpf->framenum) {
2650                                         /* transfer buffer frame to frames list (before current) */
2651                                         BLI_remlink(&sel_buffer, gfs);
2652                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2653                                 }
2654                                 /* if this buffer frame is on same frame, replace current with it and stop */
2655                                 else if (gfs->framenum == gpf->framenum) {
2656                                         /* transfer buffer frame to frames list (before current) */
2657                                         BLI_remlink(&sel_buffer, gfs);
2658                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2659                                         
2660                                         /* get rid of current frame */
2661                                         // TRANSFORM_FIX_ME
2662                                         //gpencil_layer_delframe(gpl, gpf);
2663                                 }
2664                         }
2665                 }
2666                 
2667                 /* if anything is still in buffer, append to end */
2668                 for (gfs= sel_buffer.first; gfs; gfs= gfsn) {
2669                         gfsn= gfs->next;
2670                         
2671                         BLI_remlink(&sel_buffer, gfs);
2672                         BLI_addtail(&gpl->frames, gfs);
2673                 }
2674         }
2675 }
2676
2677 /* Called by special_aftertrans_update to make sure selected keyframes replace
2678  * any other keyframes which may reside on that frame (that is not selected).
2679  */
2680 static void posttrans_ipo_clean (Ipo *ipo)
2681 {
2682         IpoCurve *icu;
2683         int i;
2684         
2685         /* delete any keyframes that occur on same frame as selected keyframe, but is not selected */
2686         for (icu= ipo->curve.first; icu; icu= icu->next) {
2687                 float *selcache;        /* cache for frame numbers of selected frames (icu->totvert*sizeof(float)) */
2688                 int len, index;         /* number of frames in cache, item index */
2689                 
2690                 /* allocate memory for the cache */
2691                 // TODO: investigate using GHash for this instead?
2692                 if (icu->totvert == 0) 
2693                         continue;
2694                 selcache= MEM_callocN(sizeof(float)*icu->totvert, "IcuSelFrameNums");
2695                 len= 0;
2696                 index= 0;
2697                 
2698                 /* We do 2 loops, 1 for marking keyframes for deletion, one for deleting 
2699                  * as there is no guarantee what order the keyframes are exactly, even though 
2700                  * they have been sorted by time.
2701                  */
2702                  
2703                 /*      Loop 1: find selected keyframes   */
2704                 for (i = 0; i < icu->totvert; i++) {
2705                         BezTriple *bezt= &icu->bezt[i];
2706                         
2707                         if (BEZSELECTED(bezt)) {
2708                                 selcache[index]= bezt->vec[1][0];
2709                                 index++;
2710                                 len++;
2711                         }
2712                 }
2713                 
2714                 /* Loop 2: delete unselected keyframes on the same frames (if any keyframes were found) */
2715                 if (len) {
2716                         for (i = 0; i < icu->totvert; i++) {
2717                                 BezTriple *bezt= &icu->bezt[i];
2718                                 
2719                                 if (BEZSELECTED(bezt) == 0) {
2720                                         /* check beztriple should be removed according to cache */
2721                                         for (index= 0; index < len; index++) {
2722                                                 if (IS_EQ(bezt->vec[1][0], selcache[index])) {
2723                                                         delete_icu_key(icu, i, 0);
2724                                                         break;
2725                                                 }
2726                                                 else if (bezt->vec[1][0] > selcache[index])
2727                                                         break;
2728                                         }
2729                                 }
2730                         }
2731                         
2732                         testhandles_ipocurve(icu);
2733                 }
2734                 
2735                 /* free cache */
2736                 MEM_freeN(selcache);
2737         }
2738 }
2739
2740 /* Called by special_aftertrans_update to make sure selected keyframes replace
2741  * any other keyframes which may reside on that frame (that is not selected).
2742  * remake_action_ipos should have already been called 
2743  */
2744 static void posttrans_action_clean (bAnimContext *ac, bAction *act)
2745 {
2746         ListBase anim_data = {NULL, NULL};
2747         bAnimListElem *ale;
2748         int filter;
2749         
2750         /* filter data */
2751         filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS);
2752         ANIM_animdata_filter(&anim_data, filter, act, ANIMCONT_ACTION);