* added operators SEQUENCER_OT_lock, unlock, reload, refresh_all, view_all, view_sele...
[blender.git] / source / blender / editors / transform / transform_conversions.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifndef WIN32
31 #include <unistd.h>
32 #else
33 #include <io.h>
34 #endif
35 #include <string.h>
36 #include <math.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "DNA_anim_types.h"
41 #include "DNA_action_types.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_camera_types.h"
44 #include "DNA_curve_types.h"
45 #include "DNA_effect_types.h"
46 #include "DNA_image_types.h"
47 #include "DNA_key_types.h"
48 #include "DNA_lamp_types.h"
49 #include "DNA_lattice_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "DNA_meta_types.h"
53 #include "DNA_modifier_types.h"
54 #include "DNA_nla_types.h"
55 #include "DNA_node_types.h"
56 #include "DNA_object_types.h"
57 #include "DNA_object_force.h"
58 #include "DNA_particle_types.h"
59 #include "DNA_scene_types.h"
60 #include "DNA_screen_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_sequence_types.h"
63 #include "DNA_texture_types.h"
64 #include "DNA_view3d_types.h"
65 #include "DNA_world_types.h"
66 #include "DNA_userdef_types.h"
67 #include "DNA_property_types.h"
68 #include "DNA_vfont_types.h"
69 #include "DNA_constraint_types.h"
70 #include "DNA_listBase.h"
71 #include "DNA_gpencil_types.h"
72
73 #include "BKE_action.h"
74 #include "BKE_armature.h"
75 #include "BKE_blender.h"
76 #include "BKE_cloth.h"
77 #include "BKE_context.h"
78 #include "BKE_curve.h"
79 #include "BKE_constraint.h"
80 #include "BKE_depsgraph.h"
81 #include "BKE_displist.h"
82 #include "BKE_DerivedMesh.h"
83 #include "BKE_effect.h"
84 #include "BKE_font.h"
85 #include "BKE_fcurve.h"
86 #include "BKE_global.h"
87 #include "BKE_lattice.h"
88 #include "BKE_key.h"
89 #include "BKE_main.h"
90 #include "BKE_mball.h"
91 #include "BKE_mesh.h"
92 #include "BKE_modifier.h"
93 #include "BKE_object.h"
94 #include "BKE_particle.h"
95 #include "BKE_sequence.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 #include "BKE_report.h"
102
103 //#include "BIF_editaction.h"
104 //#include "BIF_editview.h"
105 //#include "BIF_editlattice.h"
106 //#include "BIF_editconstraint.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_anim_api.h"
123 #include "ED_armature.h"
124 #include "ED_editparticle.h"
125 #include "ED_keyframing.h"
126 #include "ED_keyframes_edit.h"
127 #include "ED_mesh.h"
128 #include "ED_types.h"
129 #include "ED_view3d.h"
130
131 #include "UI_view2d.h"
132
133 //#include "BSE_drawipo.h"
134 //#include "BSE_edit.h"
135 //#include "BSE_editipo.h"
136 //#include "BSE_editipo_types.h"
137 //#include "BSE_editaction_types.h"
138
139 //#include "BDR_drawaction.h"           // list of keyframes in action
140 //#include "BDR_editobject.h"           // reset_slowparents()
141 //#include "BDR_gpencil.h"
142 //#include "BDR_unwrapper.h"
143
144 #include "BLI_arithb.h"
145 #include "BLI_blenlib.h"
146 #include "BLI_editVert.h"
147
148 //#include "editmesh.h"
149 //
150 //#include "blendef.h"
151 //
152 //#include "mydevice.h"
153
154 extern ListBase editelems;
155
156 #include "transform.h"
157
158 #include "BLO_sys_types.h" // for intptr_t support
159
160 /************ STUBS TO GET COMPILE ************/
161 void transform_aspect_ratio_tface_uv(float *a1, float *a2) {}
162
163
164
165 /* local function prototype - for Object/Bone Constraints */
166 static short constraints_list_needinv(TransInfo *t, ListBase *list);
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, t->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= &t->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         bArmature *arm;
958         bPoseChannel *pchan;
959         TransData *td;
960         TransDataExtension *tdx;
961         short ik_on= 0;
962         int i;
963         
964         t->total= 0;
965         
966         /* check validity of state */
967         arm= get_armature(ob);
968         if ((arm==NULL) || (ob->pose==NULL)) return;
969         
970         if (arm->flag & ARM_RESTPOS) {
971                 if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE)==0) {
972                         //notice("Pose edit not possible while Rest Position is enabled");
973                         BKE_report(CTX_reports(C), RPT_ERROR, "Can't select linked when sync selection is enabled.");
974                         return;
975                 }
976         }
977
978         /* do we need to add temporal IK chains? */
979         if ((arm->flag & ARM_AUTO_IK) && t->mode==TFM_TRANSLATION) {
980                 ik_on= pose_grab_with_ik(ob);
981                 if (ik_on) t->flag |= T_AUTOIK;
982         }
983         
984         /* set flags and count total (warning, can change transform to rotate) */
985         set_pose_transflags(t, ob);
986         
987         if(t->total==0) return;
988
989         t->flag |= T_POSE;
990         t->poseobj= ob; /* we also allow non-active objects to be transformed, in weightpaint */
991         
992         /* init trans data */
993     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransPoseBone");
994     tdx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "TransPoseBoneExt");
995         for(i=0; i<t->total; i++, td++, tdx++) {
996                 td->ext= tdx;
997                 td->tdi = NULL;
998                 td->val = NULL;
999         }       
1000         
1001         /* use pose channels to fill trans data */
1002         td= t->data;
1003         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1004                 if (pchan->bone->flag & BONE_TRANSFORM) {
1005                         add_pose_transdata(t, pchan, ob, td);
1006                         td++;
1007                 }
1008         }
1009         
1010         if(td != (t->data+t->total)) {
1011                 // printf("Bone selection count error\n");
1012                 BKE_report(CTX_reports(C), RPT_DEBUG, "Bone selection count error.");
1013         }
1014         
1015         /* initialise initial auto=ik chainlen's? */
1016         if (ik_on) transform_autoik_update(t, 0);
1017 }
1018
1019 /* ********************* armature ************** */
1020
1021 static void createTransArmatureVerts(bContext *C, TransInfo *t)
1022 {
1023         EditBone *ebo;
1024         bArmature *arm= t->obedit->data;
1025         ListBase *edbo = arm->edbo;
1026         TransData *td;
1027         float mtx[3][3], smtx[3][3], delta[3], bonemat[3][3];
1028
1029         t->total = 0;
1030         for (ebo = edbo->first; ebo; ebo = ebo->next)
1031         {
1032                 if(ebo->layer & arm->layer)
1033                 {
1034                         if (t->mode==TFM_BONESIZE)
1035                         {
1036                                 if (ebo->flag & BONE_SELECTED)
1037                                         t->total++;
1038                         }
1039                         else if (t->mode==TFM_BONE_ROLL)
1040                         {
1041                                 if (ebo->flag & BONE_SELECTED)
1042                                         t->total++;
1043                         }
1044                         else
1045                         {
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, t->obedit->obmat);
1057         Mat3Inv(smtx, mtx);
1058
1059     td = t->data = MEM_callocN(t->total*sizeof(TransData), "TransEditBone");
1060         
1061         for (ebo = edbo->first; ebo; ebo = ebo->next)
1062         {
1063                 ebo->oldlength = ebo->length;   // length==0.0 on extrude, used for scaling radius of bone points
1064                 
1065                 if(ebo->layer & arm->layer) {
1066                         if (t->mode==TFM_BONE_ENVELOPE)
1067                         {
1068                                 if (ebo->flag & BONE_ROOTSEL)
1069                                 {
1070                                         td->val= &ebo->rad_head;
1071                                         td->ival= *td->val;
1072                                         
1073                                         VECCOPY (td->center, ebo->head);
1074                                         td->flag= TD_SELECTED;
1075                                         
1076                                         Mat3CpyMat3(td->smtx, smtx);
1077                                         Mat3CpyMat3(td->mtx, mtx);
1078                                         
1079                                         td->loc = NULL;
1080                                         td->ext = NULL;
1081                                         td->tdi = NULL;
1082                                         
1083                                         td++;
1084                                 }
1085                                 if (ebo->flag & BONE_TIPSEL)
1086                                 {
1087                                         td->val= &ebo->rad_tail;
1088                                         td->ival= *td->val;
1089                                         VECCOPY (td->center, ebo->tail);
1090                                         td->flag= TD_SELECTED;
1091                                         
1092                                         Mat3CpyMat3(td->smtx, smtx);
1093                                         Mat3CpyMat3(td->mtx, mtx);
1094                                         
1095                                         td->loc = NULL;
1096                                         td->ext = NULL;
1097                                         td->tdi = NULL;
1098                                         
1099                                         td++;
1100                                 }
1101                                 
1102                         }
1103                         else if (t->mode==TFM_BONESIZE)
1104                         {
1105                                 if (ebo->flag & BONE_SELECTED) {
1106                                         if(arm->drawtype==ARM_ENVELOPE)
1107                                         {
1108                                                 td->loc= NULL;
1109                                                 td->val= &ebo->dist;
1110                                                 td->ival= ebo->dist;
1111                                         }
1112                                         else
1113                                         {
1114                                                 // abusive storage of scale in the loc pointer :)
1115                                                 td->loc= &ebo->xwidth;
1116                                                 VECCOPY (td->iloc, td->loc);
1117                                                 td->val= NULL;
1118                                         }
1119                                         VECCOPY (td->center, ebo->head);
1120                                         td->flag= TD_SELECTED;
1121                                         
1122                                         /* use local bone matrix */
1123                                         VecSubf(delta, ebo->tail, ebo->head);   
1124                                         vec_roll_to_mat3(delta, ebo->roll, bonemat);
1125                                         Mat3MulMat3(td->mtx, mtx, bonemat);
1126                                         Mat3Inv(td->smtx, td->mtx);
1127                                         
1128                                         Mat3CpyMat3(td->axismtx, td->mtx);
1129                                         Mat3Ortho(td->axismtx);
1130
1131                                         td->ext = NULL;
1132                                         td->tdi = NULL;
1133                                         
1134                                         td++;
1135                                 }
1136                         }
1137                         else if (t->mode==TFM_BONE_ROLL)
1138                         {
1139                                 if (ebo->flag & BONE_SELECTED)
1140                                 {
1141                                         td->loc= NULL;
1142                                         td->val= &(ebo->roll);
1143                                         td->ival= ebo->roll;
1144                                         
1145                                         VECCOPY (td->center, ebo->head);
1146                                         td->flag= TD_SELECTED;
1147
1148                                         td->ext = NULL;
1149                                         td->tdi = NULL;
1150                                         
1151                                         td++;
1152                                 }
1153                         }
1154                         else
1155                         {
1156                                 if (ebo->flag & BONE_TIPSEL)
1157                                 {
1158                                         VECCOPY (td->iloc, ebo->tail);
1159                                         VECCOPY (td->center, td->iloc);
1160                                         td->loc= ebo->tail;
1161                                         td->flag= TD_SELECTED;
1162                                         if (ebo->flag & BONE_EDITMODE_LOCKED)
1163                                                 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1164
1165                                         Mat3CpyMat3(td->smtx, smtx);
1166                                         Mat3CpyMat3(td->mtx, mtx);
1167
1168                                         VecSubf(delta, ebo->tail, ebo->head);   
1169                                         vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1170
1171                                         if ((ebo->flag & BONE_ROOTSEL) == 0)
1172                                         {
1173                                                 td->extra = ebo;
1174                                         }
1175
1176                                         td->ext = NULL;
1177                                         td->tdi = NULL;
1178                                         td->val = NULL;
1179
1180                                         td++;
1181                                 }
1182                                 if (ebo->flag & BONE_ROOTSEL)
1183                                 {
1184                                         VECCOPY (td->iloc, ebo->head);
1185                                         VECCOPY (td->center, td->iloc);
1186                                         td->loc= ebo->head;
1187                                         td->flag= TD_SELECTED;
1188                                         if (ebo->flag & BONE_EDITMODE_LOCKED)
1189                                                 td->protectflag = OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE;
1190
1191                                         Mat3CpyMat3(td->smtx, smtx);
1192                                         Mat3CpyMat3(td->mtx, mtx);
1193
1194                                         VecSubf(delta, ebo->tail, ebo->head);   
1195                                         vec_roll_to_mat3(delta, ebo->roll, td->axismtx);
1196
1197                                         td->extra = ebo; /* to fix roll */
1198
1199                                         td->ext = NULL;
1200                                         td->tdi = NULL;
1201                                         td->val = NULL;
1202
1203                                         td++;
1204                                 }
1205                         }
1206                 }
1207         }
1208 }
1209
1210 /* ********************* meta elements ********* */
1211
1212 static void createTransMBallVerts(bContext *C, TransInfo *t)
1213 {
1214         // TRANSFORM_FIX_ME
1215 #if 0
1216         MetaElem *ml;
1217         TransData *td;
1218         TransDataExtension *tx;
1219         float mtx[3][3], smtx[3][3];
1220         int count=0, countsel=0;
1221         int propmode = t->flag & T_PROP_EDIT;
1222
1223         /* count totals */
1224         for(ml= editelems.first; ml; ml= ml->next) {
1225                 if(ml->flag & SELECT) countsel++;
1226                 if(propmode) count++;
1227         }
1228
1229         /* note: in prop mode we need at least 1 selected */
1230         if (countsel==0) return;
1231         
1232         if(propmode) t->total = count; 
1233         else t->total = countsel;
1234         
1235         td = t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(MBall EditMode)");
1236         tx = t->ext = MEM_callocN(t->total*sizeof(TransDataExtension), "MetaElement_TransExtension");
1237
1238         Mat3CpyMat4(mtx, t->obedit->obmat);
1239         Mat3Inv(smtx, mtx);
1240     
1241         for(ml= editelems.first; ml; ml= ml->next) {
1242                 if(propmode || (ml->flag & SELECT)) {
1243                         td->loc= &ml->x;
1244                         VECCOPY(td->iloc, td->loc);
1245                         VECCOPY(td->center, td->loc);
1246
1247                         if(ml->flag & SELECT) td->flag= TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE;
1248                         else td->flag= TD_USEQUAT;
1249
1250                         Mat3CpyMat3(td->smtx, smtx);
1251                         Mat3CpyMat3(td->mtx, mtx);
1252
1253                         td->ext = tx;
1254                         td->tdi = NULL;
1255
1256                         /* Radius of MetaElem (mass of MetaElem influence) */
1257                         if(ml->flag & MB_SCALE_RAD){
1258                                 td->val = &ml->rad;
1259                                 td->ival = ml->rad;
1260                         }
1261                         else{
1262                                 td->val = &ml->s;
1263                                 td->ival = ml->s;
1264                         }
1265
1266                         /* expx/expy/expz determine "shape" of some MetaElem types */
1267                         tx->size = &ml->expx;
1268                         tx->isize[0] = ml->expx;
1269                         tx->isize[1] = ml->expy;
1270                         tx->isize[2] = ml->expz;
1271
1272                         /* quat is used for rotation of MetaElem */
1273                         tx->quat = ml->quat;
1274                         QUATCOPY(tx->iquat, ml->quat);
1275
1276                         tx->rot = NULL;
1277
1278                         td++;
1279                         tx++;
1280                 }
1281         }
1282 #endif
1283 }
1284
1285 /* ********************* curve/surface ********* */
1286
1287 static void calc_distanceCurveVerts(TransData *head, TransData *tail) {
1288         TransData *td, *td_near = NULL;
1289         for (td = head; td<=tail; td++) {
1290                 if (td->flag & TD_SELECTED) {
1291                         td_near = td;
1292                         td->dist = 0.0f;
1293                 }
1294                 else if(td_near) {
1295                         float dist;
1296                         dist = VecLenf(td_near->center, td->center);
1297                         if (dist < (td-1)->dist) {
1298                                 td->dist = (td-1)->dist;
1299                         }
1300                         else {
1301                                 td->dist = dist;
1302                         }
1303                 }
1304                 else {
1305                         td->dist = MAXFLOAT;
1306                         td->flag |= TD_NOTCONNECTED;
1307                 }
1308         }
1309         td_near = NULL;
1310         for (td = tail; td>=head; td--) {
1311                 if (td->flag & TD_SELECTED) {
1312                         td_near = td;
1313                         td->dist = 0.0f;
1314                 }
1315                 else if(td_near) {
1316                         float dist;
1317                         dist = VecLenf(td_near->center, td->center);
1318                         if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td+1)->dist < td->dist) {
1319                                 td->flag &= ~TD_NOTCONNECTED;
1320                                 if (dist < (td+1)->dist) {
1321                                         td->dist = (td+1)->dist;
1322                                 }
1323                                 else {
1324                                         td->dist = dist;
1325                                 }
1326                         }
1327                 }
1328         }
1329 }
1330
1331 /* Utility function for getting the handle data from bezier's */
1332 TransDataCurveHandleFlags *initTransDataCurveHandes(TransData *td, struct BezTriple *bezt) {
1333         TransDataCurveHandleFlags *hdata;
1334         td->flag |= TD_BEZTRIPLE;
1335         hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
1336         hdata->ih1 = bezt->h1;
1337         hdata->h1 = &bezt->h1;
1338         hdata->ih2 = bezt->h2; /* incase the second is not selected */
1339         hdata->h2 = &bezt->h2;
1340         return hdata;
1341 }
1342
1343 static void createTransCurveVerts(bContext *C, TransInfo *t)
1344 {
1345         // TRANSFORM_FIX_ME
1346 #if 0
1347         Object *obedit= CTX_data_edit_object(C);
1348         Curve *cu= obedit->data;
1349         TransData *td = NULL;
1350         Nurb *nu;
1351         BezTriple *bezt;
1352         BPoint *bp;
1353         float mtx[3][3], smtx[3][3];
1354         int a;
1355         int count=0, countsel=0;
1356         int propmode = t->flag & T_PROP_EDIT;
1357
1358         /* to be sure */
1359         if(cu->editnurb==NULL) return;
1360         
1361         /* count total of vertices, check identical as in 2nd loop for making transdata! */
1362         for(nu= cu->editnurb->first; nu; nu= nu->next) {
1363                 if((nu->type & 7)==CU_BEZIER) {
1364                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1365                                 if(bezt->hide==0) {
1366                                         if (G.f & G_HIDDENHANDLES) {
1367                                                 if(bezt->f2 & SELECT) countsel+=3;
1368                                                 if(propmode) count+= 3;
1369                                         } else {
1370                                                 if(bezt->f1 & SELECT) countsel++;
1371                                                 if(bezt->f2 & SELECT) countsel++;
1372                                                 if(bezt->f3 & SELECT) countsel++;
1373                                                 if(propmode) count+= 3;
1374                                         }
1375                                 }
1376                         }
1377                 }
1378                 else {
1379                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1380                                 if(bp->hide==0) {
1381                                         if(propmode) count++;
1382                                         if(bp->f1 & SELECT) countsel++;
1383                                 }
1384                         }
1385                 }
1386         }
1387         /* note: in prop mode we need at least 1 selected */
1388         if (countsel==0) return;
1389         
1390         if(propmode) t->total = count; 
1391         else t->total = countsel;
1392         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Curve EditMode)");
1393
1394         Mat3CpyMat4(mtx, t->obedit->obmat);
1395         Mat3Inv(smtx, mtx);
1396         
1397     td = t->data;
1398         for(nu= cu->editnurb->first; nu; nu= nu->next) {
1399                 if((nu->type & 7)==CU_BEZIER) {
1400                         TransData *head, *tail;
1401                         head = tail = td;
1402                         for(a=0, bezt= nu->bezt; a<nu->pntsu; a++, bezt++) {
1403                                 if(bezt->hide==0) {
1404                                         TransDataCurveHandleFlags *hdata = NULL;
1405                                         
1406                                         if(             propmode ||
1407                                                         ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1408                                                         ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1409                                           ) {
1410                                                 VECCOPY(td->iloc, bezt->vec[0]);
1411                                                 td->loc= bezt->vec[0];
1412                                                 VECCOPY(td->center, bezt->vec[1]);
1413                                                 if (G.f & G_HIDDENHANDLES) {
1414                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1415                                                         else td->flag= 0;
1416                                                 } else {
1417                                                         if(bezt->f1 & SELECT) td->flag= TD_SELECTED;
1418                                                         else td->flag= 0;
1419                                                 }
1420                                                 td->ext = NULL;
1421                                                 td->tdi = NULL;
1422                                                 td->val = NULL;
1423                                                 
1424                                                 hdata = initTransDataCurveHandes(td, bezt);
1425
1426                                                 Mat3CpyMat3(td->smtx, smtx);
1427                                                 Mat3CpyMat3(td->mtx, mtx);
1428
1429                                                 td++;
1430                                                 count++;
1431                                                 tail++;
1432                                         }
1433                                         
1434                                         /* This is the Curve Point, the other two are handles */
1435                                         if(propmode || (bezt->f2 & SELECT)) {
1436                                                 VECCOPY(td->iloc, bezt->vec[1]);
1437                                                 td->loc= bezt->vec[1];
1438                                                 VECCOPY(td->center, td->loc);
1439                                                 if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1440                                                 else td->flag= 0;
1441                                                 td->ext = NULL;
1442                                                 td->tdi = NULL;
1443                                                 
1444                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/ /* TODO - make points scale */
1445                                                         td->val = &(bezt->radius);
1446                                                         td->ival = bezt->radius;
1447                                                 } else if (t->mode==TFM_TILT) {
1448                                                         td->val = &(bezt->alfa);
1449                                                         td->ival = bezt->alfa;
1450                                                 } else {
1451                                                         td->val = NULL;
1452                                                 }
1453
1454                                                 Mat3CpyMat3(td->smtx, smtx);
1455                                                 Mat3CpyMat3(td->mtx, mtx);
1456                                                 
1457                                                 if ((bezt->f1&SELECT)==0 && (bezt->f3&SELECT)==0)
1458                                                 /* If the middle is selected but the sides arnt, this is needed */
1459                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1460                                                         hdata = initTransDataCurveHandes(td, bezt);
1461                                                 }
1462                                                 
1463                                                 td++;
1464                                                 count++;
1465                                                 tail++;
1466                                         }
1467                                         if(             propmode ||
1468                                                         ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) ||
1469                                                         ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0)
1470                                           ) {
1471                                                 VECCOPY(td->iloc, bezt->vec[2]);
1472                                                 td->loc= bezt->vec[2];
1473                                                 VECCOPY(td->center, bezt->vec[1]);
1474                                                 if (G.f & G_HIDDENHANDLES) {
1475                                                         if(bezt->f2 & SELECT) td->flag= TD_SELECTED;
1476                                                         else td->flag= 0;
1477                                                 } else {
1478                                                         if(bezt->f3 & SELECT) td->flag= TD_SELECTED;
1479                                                         else td->flag= 0;
1480                                                 }
1481                                                 td->ext = NULL;
1482                                                 td->tdi = NULL;
1483                                                 td->val = NULL;
1484
1485                                                 if (hdata==NULL) { /* if the handle was not saved by the previous handle */
1486                                                         hdata = initTransDataCurveHandes(td, bezt);
1487                                                 }
1488                                                 
1489                                                 Mat3CpyMat3(td->smtx, smtx);
1490                                                 Mat3CpyMat3(td->mtx, mtx);
1491
1492                                                 td++;
1493                                                 count++;
1494                                                 tail++;
1495                                         }
1496                                 }
1497                                 else if (propmode && head != tail) {
1498                                         calc_distanceCurveVerts(head, tail-1);
1499                                         head = tail;
1500                                 }
1501                         }
1502                         if (propmode && head != tail)
1503                                 calc_distanceCurveVerts(head, tail-1);
1504                         
1505                         /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandes
1506                          * but for now just dont change handle types */
1507                         if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0)
1508                                 testhandlesNurb(nu); /* sets the handles based on their selection, do this after the data is copied to the TransData */
1509                 }
1510                 else {
1511                         TransData *head, *tail;
1512                         head = tail = td;
1513                         for(a= nu->pntsu*nu->pntsv, bp= nu->bp; a>0; a--, bp++) {
1514                                 if(bp->hide==0) {
1515                                         if(propmode || (bp->f1 & SELECT)) {
1516                                                 VECCOPY(td->iloc, bp->vec);
1517                                                 td->loc= bp->vec;
1518                                                 VECCOPY(td->center, td->loc);
1519                                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1520                                                 else td->flag= 0;
1521                                                 td->ext = NULL;
1522                                                 td->tdi = NULL;
1523                                                 
1524                                                 if (t->mode==TFM_CURVE_SHRINKFATTEN || t->mode==TFM_RESIZE) {
1525                                                         td->val = &(bp->radius);
1526                                                         td->ival = bp->radius;
1527                                                 } else {
1528                                                         td->val = &(bp->alfa);
1529                                                         td->ival = bp->alfa;
1530                                                 }
1531
1532                                                 Mat3CpyMat3(td->smtx, smtx);
1533                                                 Mat3CpyMat3(td->mtx, mtx);
1534
1535                                                 td++;
1536                                                 count++;
1537                                                 tail++;
1538                                         }
1539                                 }
1540                                 else if (propmode && head != tail) {
1541                                         calc_distanceCurveVerts(head, tail-1);
1542                                         head = tail;
1543                                 }
1544                         }
1545                         if (propmode && head != tail)
1546                                 calc_distanceCurveVerts(head, tail-1);
1547                 }
1548         }
1549 #endif
1550 }
1551
1552 /* ********************* lattice *************** */
1553
1554 static void createTransLatticeVerts(bContext *C, TransInfo *t)
1555 {
1556         Lattice *latt = ((Lattice*)t->obedit->data)->editlatt;
1557         TransData *td = NULL;
1558         BPoint *bp;
1559         float mtx[3][3], smtx[3][3];
1560         int a;
1561         int count=0, countsel=0;
1562         int propmode = t->flag & T_PROP_EDIT;
1563
1564         bp = latt->def;
1565         a  = latt->pntsu * latt->pntsv * latt->pntsw;
1566         while(a--) {
1567                 if(bp->hide==0) {
1568                         if(bp->f1 & SELECT) countsel++;
1569                         if(propmode) count++;
1570                 }
1571                 bp++;
1572         }
1573         
1574         /* note: in prop mode we need at least 1 selected */
1575         if (countsel==0) return;
1576         
1577         if(propmode) t->total = count; 
1578         else t->total = countsel;
1579         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Lattice EditMode)");
1580         
1581         Mat3CpyMat4(mtx, t->obedit->obmat);
1582         Mat3Inv(smtx, mtx);
1583
1584         td = t->data;
1585         bp = latt->def;
1586         a  = latt->pntsu * latt->pntsv * latt->pntsw;
1587         while(a--) {
1588                 if(propmode || (bp->f1 & SELECT)) {
1589                         if(bp->hide==0) {
1590                                 VECCOPY(td->iloc, bp->vec);
1591                                 td->loc= bp->vec;
1592                                 VECCOPY(td->center, td->loc);
1593                                 if(bp->f1 & SELECT) td->flag= TD_SELECTED;
1594                                 else td->flag= 0;
1595                                 Mat3CpyMat3(td->smtx, smtx);
1596                                 Mat3CpyMat3(td->mtx, mtx);
1597
1598                                 td->ext = NULL;
1599                                 td->tdi = NULL;
1600                                 td->val = NULL;
1601
1602                                 td++;
1603                                 count++;
1604                         }
1605                 }
1606                 bp++;
1607         }
1608 }
1609
1610 /* ******************* particle edit **************** */
1611 static void createTransParticleVerts(bContext *C, TransInfo *t)
1612 {
1613         // TRANSFORM_FIX_ME
1614 #if 0
1615         TransData *td = NULL;
1616         TransDataExtension *tx;
1617         Base *base = BASACT;
1618         Object *ob = OBACT;
1619         ParticleSystem *psys = PE_get_current(ob);
1620         ParticleSystemModifierData *psmd = NULL;
1621         ParticleEditSettings *pset = PE_settings(t->scene);
1622         ParticleData *pa = NULL;
1623         ParticleEdit *edit;
1624         ParticleEditKey *key;
1625         float mat[4][4];
1626         int i,k, totpart, transformparticle;
1627         int count = 0, hasselected = 0;
1628         int propmode = t->flag & T_PROP_EDIT;
1629
1630         if(psys==NULL || t->scene->selectmode==SCE_SELECT_PATH) return;
1631
1632         psmd = psys_get_modifier(ob,psys);
1633
1634         edit = psys->edit;
1635         totpart = psys->totpart;
1636         base->flag |= BA_HAS_RECALC_DATA;
1637
1638         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1639                 pa->flag &= ~PARS_TRANSFORM;
1640                 transformparticle= 0;
1641
1642                 if((pa->flag & PARS_HIDE)==0) {
1643                         for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1644                                 if((key->flag&PEK_HIDE)==0) {
1645                                         if(key->flag&PEK_SELECT) {
1646                                                 hasselected= 1;
1647                                                 transformparticle= 1;
1648                                         }
1649                                         else if(propmode)
1650                                                 transformparticle= 1;
1651                                 }
1652                         }
1653                 }
1654
1655                 if(transformparticle) {
1656                         count += pa->totkey;
1657                         pa->flag |= PARS_TRANSFORM;
1658                 }
1659         }
1660         
1661         /* note: in prop mode we need at least 1 selected */
1662         if (hasselected==0) return;
1663         
1664         t->total = count;
1665         td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Particle Mode)");
1666
1667         if(t->mode == TFM_BAKE_TIME)
1668                 tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "Particle_TransExtension");
1669         else
1670                 tx = t->ext = NULL;
1671
1672         Mat4One(mat);
1673
1674         Mat4Invert(ob->imat,ob->obmat);
1675
1676         for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
1677                 TransData *head, *tail;
1678                 head = tail = td;
1679
1680                 if(!(pa->flag & PARS_TRANSFORM)) continue;
1681
1682                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1683
1684                 for(k=0, key=edit->keys[i]; k<pa->totkey; k++, key++) {
1685                         VECCOPY(key->world_co, key->co);
1686                         Mat4MulVecfl(mat, key->world_co);
1687                         td->loc = key->world_co;
1688
1689                         VECCOPY(td->iloc, td->loc);
1690                         VECCOPY(td->center, td->loc);
1691
1692                         if(key->flag & PEK_SELECT)
1693                                 td->flag |= TD_SELECTED;
1694                         else if(!propmode)
1695                                 td->flag |= TD_SKIP;
1696
1697                         Mat3One(td->mtx);
1698                         Mat3One(td->smtx);
1699
1700                         /* don't allow moving roots */
1701                         if(k==0 && pset->flag & PE_LOCK_FIRST)
1702                                 td->protectflag |= OB_LOCK_LOC;
1703
1704                         td->ob = ob;
1705                         td->ext = tx;
1706                         td->tdi = NULL;
1707                         if(t->mode == TFM_BAKE_TIME) {
1708                                 td->val = key->time;
1709                                 td->ival = *(key->time);
1710                                 /* abuse size and quat for min/max values */
1711                                 td->flag |= TD_NO_EXT;
1712                                 if(k==0) tx->size = 0;
1713                                 else tx->size = (key - 1)->time;
1714
1715                                 if(k == pa->totkey - 1) tx->quat = 0;
1716                                 else tx->quat = (key + 1)->time;
1717                         }
1718
1719                         td++;
1720                         if(tx)
1721                                 tx++;
1722                         tail++;
1723                 }
1724                 if (propmode && head != tail)
1725                         calc_distanceCurveVerts(head, tail - 1);
1726         }
1727 #endif
1728 }
1729
1730 void flushTransParticles(TransInfo *t)
1731 {
1732 #if 0 // TRANSFORM_FIX_ME
1733         Scene *scene = t->scene;
1734         Object *ob = OBACT;
1735         ParticleSystem *psys = PE_get_current(ob);
1736         ParticleSystemModifierData *psmd;
1737         ParticleData *pa;
1738         ParticleEditKey *key;
1739         TransData *td;
1740         float mat[4][4], imat[4][4], co[3];
1741         int i, k, propmode = t->flag & T_PROP_EDIT;
1742
1743         psmd = psys_get_modifier(ob, psys);
1744
1745         /* we do transform in world space, so flush world space position
1746          * back to particle local space */
1747         td= t->data;
1748         for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++, td++) {
1749                 if(!(pa->flag & PARS_TRANSFORM)) continue;
1750
1751                 psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
1752                 Mat4Invert(imat,mat);
1753
1754                 for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
1755                         VECCOPY(co, key->world_co);
1756                         Mat4MulVecfl(imat, co);
1757
1758                         /* optimization for proportional edit */
1759                         if(!propmode || !FloatCompare(key->co, co, 0.0001f)) {
1760                                 VECCOPY(key->co, co);
1761                                 pa->flag |= PARS_EDIT_RECALC;
1762                         }
1763                 }
1764         }
1765
1766         PE_update_object(scene, OBACT, 1);
1767 #endif
1768 }
1769
1770 /* ********************* mesh ****************** */
1771
1772 /* proportional distance based on connectivity  */
1773 #define E_VEC(a)        (vectors + (3 * (a)->tmp.l))
1774 #define E_NEAR(a)       (nears[((a)->tmp.l)])
1775 #define THRESHOLD       0.0001f
1776 static void editmesh_set_connectivity_distance(EditMesh *em, int total, float *vectors, EditVert **nears)
1777 {
1778         EditVert *eve;
1779         EditEdge *eed;
1780         int i= 0, done= 1;
1781
1782         /* f2 flag is used for 'selection' */
1783         /* tmp.l is offset on scratch array   */
1784         for(eve= em->verts.first; eve; eve= eve->next) {
1785                 if(eve->h==0) {
1786                         eve->tmp.l = i++;
1787
1788                         if(eve->f & SELECT) {
1789                                 eve->f2= 2;
1790                                 E_NEAR(eve) = eve;
1791                                 E_VEC(eve)[0] = 0.0f;
1792                                 E_VEC(eve)[1] = 0.0f;
1793                                 E_VEC(eve)[2] = 0.0f;
1794                         }
1795                         else {
1796                                 eve->f2 = 0;
1797                         }
1798                 }
1799         }
1800
1801
1802         /* Floodfill routine */
1803         /*
1804         At worst this is n*n of complexity where n is number of edges 
1805         Best case would be n if the list is ordered perfectly.
1806         Estimate is n log n in average (so not too bad)
1807         */
1808         while(done) {
1809                 done= 0;
1810                 
1811                 for(eed= em->edges.first; eed; eed= eed->next) {
1812                         if(eed->h==0) {
1813                                 EditVert *v1= eed->v1, *v2= eed->v2;
1814                                 float *vec2 = E_VEC(v2);
1815                                 float *vec1 = E_VEC(v1);
1816
1817                                 if (v1->f2 + v2->f2 == 4)
1818                                         continue;
1819
1820                                 if (v1->f2) {
1821                                         if (v2->f2) {
1822                                                 float nvec[3];
1823                                                 float len1 = VecLength(vec1);
1824                                                 float len2 = VecLength(vec2);
1825                                                 float lenn;
1826                                                 /* for v2 if not selected */
1827                                                 if (v2->f2 != 2) {
1828                                                         VecSubf(nvec, v2->co, E_NEAR(v1)->co);
1829                                                         lenn = VecLength(nvec);
1830                                                         /* 1 < n < 2 */
1831                                                         if (lenn - len1 > THRESHOLD && len2 - lenn > THRESHOLD) {
1832                                                                 VECCOPY(vec2, nvec);
1833                                                                 E_NEAR(v2) = E_NEAR(v1);
1834                                                                 done = 1;
1835                                                         }
1836                                                         /* n < 1 < 2 */
1837                                                         else if (len2 - len1 > THRESHOLD && len1 - lenn > THRESHOLD) {
1838                                                                 VECCOPY(vec2, vec1);
1839                                                                 E_NEAR(v2) = E_NEAR(v1);
1840                                                                 done = 1;
1841                                                         }
1842                                                 }
1843                                                 /* for v1 if not selected */
1844                                                 if (v1->f2 != 2) {
1845                                                         VecSubf(nvec, v1->co, E_NEAR(v2)->co);
1846                                                         lenn = VecLength(nvec);
1847                                                         /* 2 < n < 1 */
1848                                                         if (lenn - len2 > THRESHOLD && len1 - lenn > THRESHOLD) {
1849                                                                 VECCOPY(vec1, nvec);
1850                                                                 E_NEAR(v1) = E_NEAR(v2);
1851                                                                 done = 1;
1852                                                         }
1853                                                         /* n < 2 < 1 */
1854                                                         else if (len1 - len2 > THRESHOLD && len2 - lenn > THRESHOLD) {
1855                                                                 VECCOPY(vec1, vec2);
1856                                                                 E_NEAR(v1) = E_NEAR(v2);
1857                                                                 done = 1;
1858                                                         }
1859                                                 }
1860                                         }
1861                                         else {
1862                                                 v2->f2 = 1;
1863                                                 VecSubf(vec2, v2->co, E_NEAR(v1)->co);
1864                                                 /* 2 < 1 */
1865                                                 if (VecLength(vec1) - VecLength(vec2) > THRESHOLD) {
1866                                                         VECCOPY(vec2, vec1);
1867                                                 }
1868                                                 E_NEAR(v2) = E_NEAR(v1);
1869                                                 done = 1;
1870                                         }
1871                                 }
1872                                 else if (v2->f2) {
1873                                         v1->f2 = 1;
1874                                         VecSubf(vec1, v1->co, E_NEAR(v2)->co);
1875                                         /* 2 < 1 */
1876                                         if (VecLength(vec2) - VecLength(vec1) > THRESHOLD) {
1877                                                 VECCOPY(vec1, vec2);
1878                                         }
1879                                         E_NEAR(v1) = E_NEAR(v2);
1880                                         done = 1;
1881                                 }
1882                         }
1883                 }
1884         }
1885 }
1886
1887 /* loop-in-a-loop I know, but we need it! (ton) */
1888 static void get_face_center(float *cent, EditMesh *em, EditVert *eve)
1889 {
1890         EditFace *efa;
1891         
1892         for(efa= em->faces.first; efa; efa= efa->next)
1893                 if(efa->f & SELECT)
1894                         if(efa->v1==eve || efa->v2==eve || efa->v3==eve || efa->v4==eve)
1895                                 break;
1896         if(efa) {
1897                 VECCOPY(cent, efa->cent);
1898         }
1899 }
1900
1901 //way to overwrite what data is edited with transform
1902 //static void VertsToTransData(TransData *td, EditVert *eve, BakeKey *key)
1903 static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert *eve)
1904 {
1905         td->flag = 0;
1906         //if(key)
1907         //      td->loc = key->co;
1908         //else
1909         td->loc = eve->co;
1910         
1911         VECCOPY(td->center, td->loc);
1912         if(t->around==V3D_LOCAL && (em->selectmode & SCE_SELECT_FACE))
1913                 get_face_center(td->center, em, eve);
1914         VECCOPY(td->iloc, td->loc);
1915
1916         // Setting normals
1917         VECCOPY(td->axismtx[2], eve->no);
1918         td->axismtx[0][0]               =
1919                 td->axismtx[0][1]       =
1920                 td->axismtx[0][2]       =
1921                 td->axismtx[1][0]       =
1922                 td->axismtx[1][1]       =
1923                 td->axismtx[1][2]       = 0.0f;
1924
1925         td->ext = NULL;
1926         td->tdi = NULL;
1927         td->val = NULL;
1928         td->extra = NULL;
1929         if (t->mode == TFM_BWEIGHT) {
1930                 td->val = &(eve->bweight);
1931                 td->ival = eve->bweight;
1932         }
1933 }
1934
1935 /* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
1936
1937 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
1938 {
1939         float *vec = userData;
1940         
1941         vec+= 3*index;
1942         VECCOPY(vec, co);
1943 }
1944
1945 static int modifiers_disable_subsurf_temporary(Object *ob)
1946 {
1947         ModifierData *md;
1948         int disabled = 0;
1949         
1950         for(md=ob->modifiers.first; md; md=md->next)
1951                 if(md->type==eModifierType_Subsurf)
1952                         if(md->mode & eModifierMode_OnCage) {
1953                                 md->mode ^= eModifierMode_DisableTemporary;
1954                                 disabled= 1;
1955                         }
1956         
1957         return disabled;
1958 }
1959
1960 /* disable subsurf temporal, get mapped cos, and enable it */
1961 static float *get_crazy_mapped_editverts(TransInfo *t)
1962 {
1963         Mesh *me= t->obedit->data;
1964         DerivedMesh *dm;
1965         float *vertexcos;
1966
1967         /* disable subsurf temporal, get mapped cos, and enable it */
1968         if(modifiers_disable_subsurf_temporary(t->obedit)) {
1969                 /* need to make new derivemesh */
1970                 makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1971         }
1972
1973         /* now get the cage */
1974         dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
1975
1976         vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->totvert, "vertexcos map");
1977         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos);
1978         
1979         dm->release(dm);
1980         
1981         /* set back the flag, no new cage needs to be built, transform does it */
1982         modifiers_disable_subsurf_temporary(t->obedit);
1983         
1984         return vertexcos;
1985 }
1986
1987 #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])
1988 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
1989 {
1990         float vecu[3], vecv[3];
1991         float q1[4], q2[4];
1992         
1993         TAN_MAKE_VEC(vecu, v1, v2);
1994         TAN_MAKE_VEC(vecv, v1, v3);
1995         triatoquat(v1, vecu, vecv, q1);
1996         
1997         TAN_MAKE_VEC(vecu, def1, def2);
1998         TAN_MAKE_VEC(vecv, def1, def3);
1999         triatoquat(def1, vecu, vecv, q2);
2000         
2001         QuatSub(quat, q2, q1);
2002 }
2003 #undef TAN_MAKE_VEC
2004
2005 static void set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
2006 {
2007         EditVert *eve, *prev;
2008         EditFace *efa;
2009         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
2010         intptr_t index= 0;
2011         
2012         /* two abused locations in vertices */
2013         for(eve= em->verts.first; eve; eve= eve->next, index++) {
2014                 eve->tmp.p = NULL;
2015                 eve->prev= (EditVert *)index;
2016         }
2017         
2018         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
2019         for(efa= em->faces.first; efa; efa= efa->next) {
2020                 
2021                 /* retrieve mapped coordinates */
2022                 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
2023                 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
2024                 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
2025
2026                 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
2027                 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
2028                 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
2029
2030                 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
2031                         set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
2032                         efa->v2->tmp.p= (void*)quats;
2033                         quats+= 4;
2034                 }
2035                 
2036                 if(efa->v4) {
2037                         v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
2038                         co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
2039
2040                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2041                                 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
2042                                 efa->v1->tmp.p= (void*)quats;
2043                                 quats+= 4;
2044                         }
2045                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2046                                 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
2047                                 efa->v3->tmp.p= (void*)quats;
2048                                 quats+= 4;
2049                         }
2050                         if(efa->v4->tmp.p==NULL && efa->v4->f1) {
2051                                 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
2052                                 efa->v4->tmp.p= (void*)quats;
2053                                 quats+= 4;
2054                         }
2055                 }
2056                 else {
2057                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
2058                                 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
2059                                 efa->v1->tmp.p= (void*)quats;
2060                                 quats+= 4;
2061                         }
2062                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
2063                                 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
2064                                 efa->v3->tmp.p= (void*)quats;
2065                                 quats+= 4;
2066                         }
2067                 }
2068         }
2069
2070         /* restore abused prev pointer */
2071         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
2072                 eve->prev= prev;
2073
2074 }
2075
2076 void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
2077         BME_Vert *v;
2078         BME_TransData *vtd;
2079         TransData *tob;
2080         int i;
2081
2082         tob = t->data = MEM_callocN(td->len*sizeof(TransData), "TransObData(Bevel tool)");
2083
2084         for (i=0,v=bm->verts.first;v;v=v->next) {
2085                 if ( (vtd = BME_get_transdata(td,v)) ) {
2086                         tob->loc = vtd->loc;
2087                         tob->val = &vtd->factor;
2088                         VECCOPY(tob->iloc,vtd->co);
2089                         VECCOPY(tob->center,vtd->org);
2090                         VECCOPY(tob->axismtx[0],vtd->vec);
2091                         tob->axismtx[1][0] = vtd->max ? *vtd->max : 0;
2092                         tob++;
2093                         i++;
2094                 }
2095         }
2096         /* since td is a memarena, it can hold more transdata than actual elements
2097          * (i.e. we can't depend on td->len to determine the number of actual elements) */
2098         t->total = i;
2099 }
2100
2101 static void createTransEditVerts(bContext *C, TransInfo *t)
2102 {
2103         Scene *scene = CTX_data_scene(C);
2104         TransData *tob = NULL;
2105         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2106         EditVert *eve;
2107         EditVert **nears = NULL;
2108         EditVert *eve_act = NULL;
2109         float *vectors = NULL, *mappedcos = NULL, *quats= NULL;
2110         float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL;
2111         int count=0, countsel=0, a, totleft;
2112         int propmode = t->flag & T_PROP_EDIT;
2113         int mirror = 0;
2114         
2115         if ((t->options & CTX_NO_MIRROR) == 0 && (scene->toolsettings->editbutflag & B_MESH_X_MIRROR))
2116         {
2117                 mirror = 1;
2118         }
2119
2120         // transform now requires awareness for select mode, so we tag the f1 flags in verts
2121         if(scene->selectmode & SCE_SELECT_VERTEX) {
2122                 for(eve= em->verts.first; eve; eve= eve->next) {
2123                         if(eve->h==0 && (eve->f & SELECT)) 
2124                                 eve->f1= SELECT;
2125                         else
2126                                 eve->f1= 0;
2127                 }
2128         }
2129         else if(scene->selectmode & SCE_SELECT_EDGE) {
2130                 EditEdge *eed;
2131                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2132                 for(eed= em->edges.first; eed; eed= eed->next) {
2133                         if(eed->h==0 && (eed->f & SELECT))
2134                                 eed->v1->f1= eed->v2->f1= SELECT;
2135                 }
2136         }
2137         else {
2138                 EditFace *efa;
2139                 for(eve= em->verts.first; eve; eve= eve->next) eve->f1= 0;
2140                 for(efa= em->faces.first; efa; efa= efa->next) {
2141                         if(efa->h==0 && (efa->f & SELECT)) {
2142                                 efa->v1->f1= efa->v2->f1= efa->v3->f1= SELECT;
2143                                 if(efa->v4) efa->v4->f1= SELECT;
2144                         }
2145                 }
2146         }
2147         
2148         /* now we can count */
2149         for(eve= em->verts.first; eve; eve= eve->next) {
2150                 if(eve->h==0) {
2151                         if(eve->f1) countsel++;
2152                         if(propmode) count++;
2153                 }
2154         }
2155         
2156         /* note: in prop mode we need at least 1 selected */
2157         if (countsel==0) return;
2158         
2159         /* check active */
2160         if (em->selected.last) {
2161                 EditSelection *ese = em->selected.last;
2162                 if ( ese->type == EDITVERT ) {
2163                         eve_act = (EditVert *)ese->data;
2164                 }
2165         }
2166
2167         
2168         if(propmode) {
2169                 t->total = count; 
2170         
2171                 /* allocating scratch arrays */
2172                 vectors = (float *)MEM_mallocN(t->total * 3 * sizeof(float), "scratch vectors");
2173                 nears = (EditVert**)MEM_mallocN(t->total * sizeof(EditVert*), "scratch nears");
2174         }
2175         else t->total = countsel;
2176         tob= t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(Mesh EditMode)");
2177         
2178         Mat3CpyMat4(mtx, t->obedit->obmat);
2179         Mat3Inv(smtx, mtx);
2180
2181         if(propmode) editmesh_set_connectivity_distance(em, t->total, vectors, nears);
2182         
2183         /* detect CrazySpace [tm] */
2184         if(propmode==0) {
2185                 if(modifiers_getCageIndex(t->obedit, NULL)>=0) {
2186                         if(modifiers_isDeformed(t->scene, t->obedit)) {
2187                                 /* check if we can use deform matrices for modifier from the
2188                                    start up to stack, they are more accurate than quats */
2189                                 totleft= editmesh_get_first_deform_matrices(t->obedit, em, &defmats, &defcos);
2190
2191                                 /* if we still have more modifiers, also do crazyspace
2192                                    correction with quats, relative to the coordinates after
2193                                    the modifiers that support deform matrices (defcos) */
2194                                 if(totleft > 0) {
2195                                         mappedcos= get_crazy_mapped_editverts(t);
2196                                         quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
2197                                         set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
2198                                         if(mappedcos)
2199                                                 MEM_freeN(mappedcos);
2200                                 }
2201
2202                                 if(defcos)
2203                                         MEM_freeN(defcos);
2204                         }
2205                 }
2206         }
2207         
2208         /* find out which half we do */
2209         if(mirror) {
2210                 for (eve=em->verts.first; eve; eve=eve->next) {
2211                         if(eve->h==0 && eve->f1 && eve->co[0]!=0.0f) {
2212                                 if(eve->co[0]<0.0f)
2213                                         mirror = -1;
2214                                 break;
2215                         }
2216                 }
2217         }
2218         
2219         for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) {
2220                 if(eve->h==0) {
2221                         if(propmode || eve->f1) {
2222                                 VertsToTransData(t, tob, em, eve);
2223                                 
2224                                 /* selected */
2225                                 if(eve->f1) tob->flag |= TD_SELECTED;
2226                                 
2227                                 /* active */
2228                                 if(eve == eve_act) tob->flag |= TD_ACTIVE;
2229                                 
2230                                 if(propmode) {
2231                                         if (eve->f2) {
2232                                                 float vec[3];
2233                                                 VECCOPY(vec, E_VEC(eve));
2234                                                 Mat3MulVecfl(mtx, vec);
2235                                                 tob->dist= VecLength(vec);
2236                                         }
2237                                         else {
2238                                                 tob->flag |= TD_NOTCONNECTED;
2239                                                 tob->dist = MAXFLOAT;
2240                                         }
2241                                 }
2242                                 
2243                                 /* CrazySpace */
2244                                 if(defmats || (quats && eve->tmp.p)) {
2245                                         float mat[3][3], imat[3][3], qmat[3][3];
2246                                         
2247                                         /* use both or either quat and defmat correction */
2248                                         if(quats && eve->tmp.f) {
2249                                                 QuatToMat3(eve->tmp.p, qmat);
2250
2251                                                 if(defmats)
2252                                                         Mat3MulSerie(mat, mtx, qmat, defmats[a],
2253                                                                 NULL, NULL, NULL, NULL, NULL);
2254                                                 else
2255                                                         Mat3MulMat3(mat, mtx, qmat);
2256                                         }
2257                                         else
2258                                                 Mat3MulMat3(mat, mtx, defmats[a]);
2259
2260                                         Mat3Inv(imat, mat);
2261                                         
2262                                         Mat3CpyMat3(tob->smtx, imat);
2263                                         Mat3CpyMat3(tob->mtx, mat);
2264                                 }
2265                                 else {
2266                                         Mat3CpyMat3(tob->smtx, smtx);
2267                                         Mat3CpyMat3(tob->mtx, mtx);
2268                                 }
2269                                 
2270                                 /* Mirror? */
2271                                 if( (mirror>0 && tob->iloc[0]>0.0f) || (mirror<0 && tob->iloc[0]<0.0f)) {
2272                                         EditVert *vmir= editmesh_get_x_mirror_vert(t->obedit, em, tob->iloc);   /* initializes octree on first call */
2273                                         if(vmir != eve) tob->extra = vmir;
2274                                 }
2275                                 tob++;
2276                         }
2277                 }       
2278         }
2279         if (propmode) {
2280                 MEM_freeN(vectors);
2281                 MEM_freeN(nears);
2282         }
2283         /* crazy space free */
2284         if(quats)
2285                 MEM_freeN(quats);
2286         if(defmats)
2287                 MEM_freeN(defmats);
2288 }
2289
2290 /* *** NODE EDITOR *** */
2291 void flushTransNodes(TransInfo *t)
2292 {
2293         int a;
2294         TransData2D *td;
2295         
2296         /* flush to 2d vector from internally used 3d vector */
2297         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2298                 td->loc2d[0]= td->loc[0];
2299                 td->loc2d[1]= td->loc[1];
2300         }
2301 }
2302
2303 /* *** SEQUENCE EDITOR *** */
2304 void flushTransSeq(TransInfo *t)
2305 {
2306         ListBase *seqbasep= ((Editing *)t->scene->ed)->seqbasep;
2307         int a, new_frame;
2308         TransData *td= t->data;
2309         TransData2D *td2d= t->data2d;
2310         TransDataSeq *tdsq= NULL;
2311         Sequence *seq;
2312
2313         
2314
2315         /* prevent updating the same seq twice
2316          * if the transdata order is changed this will mess up
2317          * but so will TransDataSeq */
2318         Sequence *seq_prev= NULL;
2319
2320         /* flush to 2d vector from internally used 3d vector */
2321         for(a=0; a<t->total; a++, td++, td2d++) {
2322
2323                 tdsq= (TransDataSeq *)td->extra;
2324                 seq= tdsq->seq;
2325                 new_frame= (int)(td2d->loc[0] + 0.5f);
2326
2327                 switch (tdsq->sel_flag) {
2328                 case SELECT:
2329                         if (seq->type != SEQ_META) /* for meta's, their children move */
2330                                 seq->start= new_frame - tdsq->start_offset;
2331                         
2332                         if (seq->depth==0) {
2333                                 seq->machine= (int)(td2d->loc[1] + 0.5f);
2334                                 CLAMP(seq->machine, 1, MAXSEQ);
2335                         }
2336                         break;
2337                 case SEQ_LEFTSEL: /* no vertical transform  */
2338                         seq_tx_set_final_left(seq, new_frame);
2339                         seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2340                         fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2341                         break;
2342                 case SEQ_RIGHTSEL: /* no vertical transform  */
2343                         seq_tx_set_final_right(seq, new_frame);
2344                         seq_tx_handle_xlimits(seq, tdsq->flag&SEQ_LEFTSEL, tdsq->flag&SEQ_RIGHTSEL);
2345                         fix_single_seq(seq); /* todo - move this into aftertrans update? - old seq tx needed it anyway */
2346                         break;
2347                 }
2348
2349                 if (seq != seq_prev) {
2350                         if(seq->depth==0) {
2351                                 /* Calculate this strip and all nested strips
2352                                  * children are ALWAYS transformed first
2353                                  * so we dont need to do this in another loop. */
2354                                 calc_sequence(seq);
2355
2356                                 /* test overlap, displayes red outline */
2357                                 seq->flag &= ~SEQ_OVERLAP;
2358                                 if( seq_test_overlap(seqbasep, seq) ) {
2359                                         seq->flag |= SEQ_OVERLAP;
2360                                 }
2361                         }
2362                         else {
2363                                 calc_sequence_disp(seq);
2364                         }
2365                 }
2366                 seq_prev= seq;
2367         }
2368
2369         if (t->mode == TFM_TIME_TRANSLATE) { /* originally TFM_TIME_EXTEND, transform changes */
2370                 /* Special annoying case here, need to calc metas with TFM_TIME_EXTEND only */
2371                 seq= seqbasep->first;
2372
2373                 while(seq) {
2374                         if (seq->type == SEQ_META && seq->flag & SELECT)
2375                                 calc_sequence(seq);
2376                         seq= seq->next;
2377                 }
2378         }
2379 }
2380
2381 /* ********************* UV ****************** */
2382
2383 static void UVsToTransData(TransData *td, TransData2D *td2d, float *uv, int selected)
2384 {
2385         float aspx, aspy;
2386
2387         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2388
2389         /* uv coords are scaled by aspects. this is needed for rotations and
2390            proportional editing to be consistent with the stretchted uv coords
2391            that are displayed. this also means that for display and numinput,
2392            and when the the uv coords are flushed, these are converted each time */
2393         td2d->loc[0] = uv[0]*aspx;
2394         td2d->loc[1] = uv[1]*aspy;
2395         td2d->loc[2] = 0.0f;
2396         td2d->loc2d = uv;
2397
2398         td->flag = 0;
2399         td->loc = td2d->loc;
2400         VECCOPY(td->center, td->loc);
2401         VECCOPY(td->iloc, td->loc);
2402
2403         memset(td->axismtx, 0, sizeof(td->axismtx));
2404         td->axismtx[2][2] = 1.0f;
2405
2406         td->ext= NULL; td->tdi= NULL; td->val= NULL;
2407
2408         if(selected) {
2409                 td->flag |= TD_SELECTED;
2410                 td->dist= 0.0;
2411         }
2412         else {
2413                 td->dist= MAXFLOAT;
2414         }
2415         Mat3One(td->mtx);
2416         Mat3One(td->smtx);
2417 }
2418
2419 static void createTransUVs(bContext *C, TransInfo *t)
2420 {
2421 #if 0 // TRANSFORM_FIX_ME
2422         SpaceImage *sima = (SpaceImage*)CTX_wm_space_data(C);
2423         TransData *td = NULL;
2424         TransData2D *td2d = NULL;
2425         MTFace *tf;
2426         int count=0, countsel=0;
2427         int propmode = t->flag & T_PROP_EDIT;
2428         int efa_s1,efa_s2,efa_s3,efa_s4;
2429
2430         EditMesh *em = ((Mesh *)t->obedit->data)->edit_mesh;
2431         EditFace *efa;
2432         
2433         if(is_uv_tface_editing_allowed()==0) return;
2434
2435         /* count */
2436         if (sima->flag & SI_BE_SQUARE && !propmode) {
2437                 for (efa= em->faces.first; efa; efa= efa->next) {
2438                         /* store face pointer for second loop, prevent second lookup */
2439                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2440                         if (simaFaceDraw_Check(efa, tf)) {
2441                                 efa->tmp.p = tf;
2442                                 
2443                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2444                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2445                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2446                                 if (efa->v4) {
2447                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2448                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2449                                                 countsel += 4; /* all corners of this quad need their edges moved. so we must store TD for each */
2450                                         }
2451                                 } else {
2452                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2453                                         if (efa_s1) countsel++; 
2454                                         if (efa_s2) countsel++; 
2455                                         if (efa_s3) countsel++;
2456                                 }
2457                         } else {
2458                                 efa->tmp.p = NULL;
2459                         }
2460                 }
2461         } else {
2462                 for (efa= em->faces.first; efa; efa= efa->next) {
2463                         tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2464                         if (simaFaceDraw_Check(efa, tf)) {
2465                                 efa->tmp.p = tf;
2466                                 
2467                                 if (simaUVSel_Check(efa, tf, 0)) countsel++; 
2468                                 if (simaUVSel_Check(efa, tf, 1)) countsel++; 
2469                                 if (simaUVSel_Check(efa, tf, 2)) countsel++; 
2470                                 if (efa->v4 && simaUVSel_Check(efa, tf, 3)) countsel++;
2471                                 if(propmode)
2472                                         count += (efa->v4)? 4: 3;
2473                         } else {
2474                                 efa->tmp.p = NULL;
2475                         }
2476                 }
2477         }
2478         
2479         /* note: in prop mode we need at least 1 selected */
2480         if (countsel==0) return;
2481         
2482         t->total= (propmode)? count: countsel;
2483         t->data= MEM_callocN(t->total*sizeof(TransData), "TransObData(UV Editing)");
2484         /* for each 2d uv coord a 3d vector is allocated, so that they can be
2485            treated just as if they were 3d verts */
2486         t->data2d= MEM_callocN(t->total*sizeof(TransData2D), "TransObData2D(UV Editing)");
2487
2488         if(sima->flag & SI_CLIP_UV)
2489                 t->flag |= T_CLIP_UV;
2490
2491         td= t->data;
2492         td2d= t->data2d;
2493         
2494         if (sima->flag & SI_BE_SQUARE && !propmode) {
2495                 for (efa= em->faces.first; efa; efa= efa->next) {
2496                         tf=(MTFace *)efa->tmp.p;
2497                         if (tf) {
2498                                 efa_s1 = simaUVSel_Check(efa, tf, 0);
2499                                 efa_s2 = simaUVSel_Check(efa, tf, 1);
2500                                 efa_s3 = simaUVSel_Check(efa, tf, 2);
2501                                 
2502                                 if (efa->v4) {
2503                                         efa_s4 = simaUVSel_Check(efa, tf, 3);
2504                                         
2505                                         if ( efa_s1 || efa_s2 || efa_s3 || efa_s4 ) {
2506                                                 /* all corners of this quad need their edges moved. so we must store TD for each */
2507
2508                                                 UVsToTransData(td, td2d, tf->uv[0], efa_s1);
2509                                                 if (!efa_s1)    td->flag |= TD_SKIP;
2510                                                 td++; td2d++;
2511
2512                                                 UVsToTransData(td, td2d, tf->uv[1], efa_s2);
2513                                                 if (!efa_s2)    td->flag |= TD_SKIP;
2514                                                 td++; td2d++;
2515
2516                                                 UVsToTransData(td, td2d, tf->uv[2], efa_s3);
2517                                                 if (!efa_s3)    td->flag |= TD_SKIP;
2518                                                 td++; td2d++;
2519
2520                                                 UVsToTransData(td, td2d, tf->uv[3], efa_s4);
2521                                                 if (!efa_s4)    td->flag |= TD_SKIP;
2522                                                 td++; td2d++;
2523                                         }
2524                                 } else {
2525                                         /* tri's are delt with normally when SI_BE_SQUARE's enabled */
2526                                         if (efa_s1) UVsToTransData(td++, td2d++, tf->uv[0], 1); 
2527                                         if (efa_s2) UVsToTransData(td++, td2d++, tf->uv[1], 1); 
2528                                         if (efa_s3) UVsToTransData(td++, td2d++, tf->uv[2], 1);
2529                                 }
2530                         }
2531                 }
2532         } else {
2533                 for (efa= em->faces.first; efa; efa= efa->next) {
2534                         /*tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
2535                         if (simaFaceDraw_Check(efa, tf)) {*/
2536                         if ((tf=(MTFace *)efa->tmp.p)) {
2537                                 if (propmode) {
2538                                         UVsToTransData(td++, td2d++, tf->uv[0], simaUVSel_Check(efa, tf, 0));
2539                                         UVsToTransData(td++, td2d++, tf->uv[1], simaUVSel_Check(efa, tf, 1));
2540                                         UVsToTransData(td++, td2d++, tf->uv[2], simaUVSel_Check(efa, tf, 2));
2541                                         if(efa->v4)
2542                                                 UVsToTransData(td++, td2d++, tf->uv[3], simaUVSel_Check(efa, tf, 3));
2543                                 } else {
2544                                         if(simaUVSel_Check(efa, tf, 0))                         UVsToTransData(td++, td2d++, tf->uv[0], 1);
2545                                         if(simaUVSel_Check(efa, tf, 1))                         UVsToTransData(td++, td2d++, tf->uv[1], 1);
2546                                         if(simaUVSel_Check(efa, tf, 2))                         UVsToTransData(td++, td2d++, tf->uv[2], 1);
2547                                         if(efa->v4 && simaUVSel_Check(efa, tf, 3))      UVsToTransData(td++, td2d++, tf->uv[3], 1);
2548                                 }
2549                         }
2550                 }
2551         }
2552         
2553         if (sima->flag & SI_LIVE_UNWRAP)
2554                 unwrap_lscm_live_begin();
2555 #endif
2556 }
2557
2558 void flushTransUVs(TransInfo *t)
2559 {
2560 #if 0 // TRANSFORM_FIX_ME
2561         TransData2D *td;
2562         int a, width, height;
2563         Object *ob= OBACT;
2564         EditMesh *em = ((Mesh *)ob->data)->edit_mesh;
2565         float aspx, aspy, invx, invy;
2566
2567         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2568         transform_width_height_tface_uv(&width, &height);
2569         invx= 1.0f/aspx;
2570         invy= 1.0f/aspy;
2571
2572         /* flush to 2d vector from internally used 3d vector */
2573         for(a=0, td= t->data2d; a<t->total; a++, td++) {
2574                 td->loc2d[0]= td->loc[0]*invx;
2575                 td->loc2d[1]= td->loc[1]*invy;
2576                 
2577                 if((G.sima->flag & SI_PIXELSNAP) && (t->state != TRANS_CANCEL)) {
2578                         td->loc2d[0]= (float)floor(width*td->loc2d[0] + 0.5f)/width;
2579                         td->loc2d[1]= (float)floor(height*td->loc2d[1] + 0.5f)/height;
2580                 }
2581         }
2582         
2583         if((G.sima->flag & SI_BE_SQUARE) && (t->flag & T_PROP_EDIT)==0 && (t->state != TRANS_CANCEL)) 
2584                 be_square_tface_uv(em);
2585
2586         /* this is overkill if G.sima->lock is not set, but still needed */
2587         object_uvs_changed(ob);
2588 #endif
2589 }
2590
2591 int clipUVTransform(TransInfo *t, float *vec, int resize)
2592 {
2593 #if 0 // TRANSFORM_FIX_ME
2594         TransData *td;
2595         int a, clipx=1, clipy=1;
2596         float aspx, aspy, min[2], max[2];
2597
2598         transform_aspect_ratio_tface_uv(&aspx, &aspy);
2599         min[0]= min[1]= 0.0f;
2600         max[0]= aspx; max[1]= aspy;
2601
2602         for(a=0, td= t->data; a<t->total; a++, td++) {
2603                 DO_MINMAX2(td->loc, min, max);
2604         }
2605
2606         if(resize) {
2607                 if(min[0] < 0.0f && t->center[0] > 0.0f && t->center[0] < aspx*0.5f)
2608                         vec[0] *= t->center[0]/(t->center[0] - min[0]);
2609                 else if(max[0] > aspx && t->center[0] < aspx)
2610                         vec[0] *= (t->center[0] - aspx)/(t->center[0] - max[0]);
2611                 else
2612                         clipx= 0;
2613
2614                 if(min[1] < 0.0f && t->center[1] > 0.0f && t->center[1] < aspy*0.5f)
2615                         vec[1] *= t->center[1]/(t->center[1] - min[1]);
2616                 else if(max[1] > aspy && t->center[1] < aspy)
2617                         vec[1] *= (t->center[1] - aspy)/(t->center[1] - max[1]);
2618                 else
2619                         clipy= 0;
2620         }
2621         else {
2622                 if(min[0] < 0.0f)
2623                         vec[0] -= min[0];
2624                 else if(max[0] > aspx)
2625                         vec[0] -= max[0]-aspx;
2626                 else
2627                         clipx= 0;
2628
2629                 if(min[1] < 0.0f)
2630                         vec[1] -= min[1];
2631                 else if(max[1] > aspy)
2632                         vec[1] -= max[1]-aspy;
2633                 else
2634                         clipy= 0;
2635         }       
2636
2637         return (clipx || clipy);
2638 #endif
2639 return 0;
2640 }
2641
2642 /* ********************* IPO EDITOR ************************* */
2643
2644 /* for IPO Editor transform - but actual creation of transform structures is not performed here
2645  * due to bad globals that would need to be imported specially for this
2646  */
2647 static void createTransIpoData(bContext *C, TransInfo *t)
2648 {
2649         // TRANSFORM_FIX_ME
2650 #if 0
2651         /* in editipo.c due to some globals that are defined in that file... */
2652         make_ipo_transdata(t);
2653 #endif
2654 }
2655
2656 /* this function is called on recalcData to apply the transforms applied
2657  * to the transdata on to the actual keyframe data 
2658  */
2659 void flushTransIpoData(TransInfo *t)
2660 {
2661 #if 0 // TRANSFORM_FIX_ME
2662         TransData2D *td;
2663         int a;
2664         
2665         /* flush to 2d vector from internally used 3d vector */
2666         for (a=0, td= t->data2d; a<t->total; a++, td++) {
2667                 // FIXME: autosnap needs to be here...
2668                 
2669                 /* we need to unapply the nla-scaling from the time in some situations */
2670                 if (NLA_IPO_SCALED)
2671                         td->loc2d[0]= get_action_frame(OBACT, td->loc[0]);
2672                 else
2673                         td->loc2d[0]= td->loc[0];
2674                 
2675                 /* when the icu that point comes from is a bitflag holder, don't allow adjusting values */
2676                 if ((t->data[a].flag & TD_TIMEONLY)==0)
2677                         td->loc2d[1]= td->loc[1];
2678         }
2679 #endif
2680 }
2681
2682 /* ********************* ACTION/NLA EDITOR ****************** */
2683
2684 /* Called by special_aftertrans_update to make sure selected gp-frames replace
2685  * any other gp-frames which may reside on that frame (that are not selected).
2686  * It also makes sure gp-frames are still stored in chronological order after
2687  * transform.
2688  */
2689 static void posttrans_gpd_clean (bGPdata *gpd)
2690 {
2691         bGPDlayer *gpl;
2692         
2693         for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
2694                 ListBase sel_buffer = {NULL, NULL};
2695                 bGPDframe *gpf, *gpfn;
2696                 bGPDframe *gfs, *gfsn;
2697                 
2698                 /* loop 1: loop through and isolate selected gp-frames to buffer 
2699                  * (these need to be sorted as they are isolated)
2700                  */
2701                 for (gpf= gpl->frames.first; gpf; gpf= gpfn) {
2702                         short added= 0;
2703                         gpfn= gpf->next;
2704                         
2705                         if (gpf->flag & GP_FRAME_SELECT) {
2706                                 BLI_remlink(&gpl->frames, gpf);
2707                                 
2708                                 /* find place to add them in buffer
2709                                  * - go backwards as most frames will still be in order,
2710                                  *   so doing it this way will be faster 
2711                                  */
2712                                 for (gfs= sel_buffer.last; gfs; gfs= gfs->prev) {
2713                                         /* if current (gpf) occurs after this one in buffer, add! */
2714                                         if (gfs->framenum < gpf->framenum) {
2715                                                 BLI_insertlinkafter(&sel_buffer, gfs, gpf);
2716                                                 added= 1;
2717                                                 break;
2718                                         }
2719                                 }
2720                                 if (added == 0)
2721                                         BLI_addhead(&sel_buffer, gpf);
2722                         }
2723                 }
2724                 
2725                 /* error checking: it is unlikely, but may be possible to have none selected */
2726                 if (sel_buffer.first == NULL)
2727                         continue;
2728                 
2729                 /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */
2730                 if (gpl->frames.first == NULL) {
2731                         gpl->frames.first= sel_buffer.first;
2732                         gpl->frames.last= sel_buffer.last;
2733                         
2734                         continue;
2735                 }
2736                 
2737                 /* loop 2: remove duplicates of frames in buffers */
2738                 for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) {
2739                         gpfn= gpf->next;
2740                         
2741                         /* loop through sel_buffer, emptying stuff from front of buffer if ok */
2742                         for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) {
2743                                 gfsn= gfs->next;
2744                                 
2745                                 /* if this buffer frame needs to go before current, add it! */
2746                                 if (gfs->framenum < gpf->framenum) {
2747                                         /* transfer buffer frame to frames list (before current) */
2748                                         BLI_remlink(&sel_buffer, gfs);
2749                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2750                                 }
2751                                 /* if this buffer frame is on same frame, replace current with it and stop */
2752                                 else if (gfs->framenum == gpf->framenum) {
2753                                         /* transfer buffer frame to frames list (before current) */
2754                                         BLI_remlink(&sel_buffer, gfs);
2755                                         BLI_insertlinkbefore(&gpl->frames, gpf, gfs);
2756                                         
2757                        &nb