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