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