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