svn merge ^/trunk/blender -r43482:43524
[blender.git] / source / blender / editors / transform / transform_generics.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/transform/transform_generics.c
29  *  \ingroup edtransform
30  */
31
32
33 #include <string.h>
34 #include <math.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLO_sys_types.h" // for intptr_t support
39
40 #include "DNA_anim_types.h"
41 #include "DNA_armature_types.h"
42 #include "DNA_lattice_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_space_types.h"
45 #include "DNA_scene_types.h"
46 #include "DNA_object_types.h"
47 #include "DNA_meshdata_types.h"
48 #include "DNA_view3d_types.h"
49 #include "DNA_modifier_types.h"
50 #include "DNA_movieclip_types.h"
51
52 #include "RNA_access.h"
53
54 //#include "BIF_screen.h"
55 //#include "BIF_mywindow.h"
56 #include "BIF_gl.h"
57 #include "BIF_glutil.h"
58 //#include "BIF_editmesh.h"
59 //#include "BIF_editsima.h"
60 //#include "BIF_editparticle.h"
61 //#include "BIF_meshtools.h"
62
63 #include "BKE_animsys.h"
64 #include "BKE_action.h"
65 #include "BKE_armature.h"
66 #include "BKE_curve.h"
67 #include "BKE_depsgraph.h"
68 #include "BKE_displist.h"
69 #include "BKE_fcurve.h"
70 #include "BKE_lattice.h"
71 #include "BKE_mesh.h"
72 #include "BKE_nla.h"
73 #include "BKE_context.h"
74 #include "BKE_tessmesh.h"
75 #include "BKE_tracking.h"
76
77 #include "ED_anim_api.h"
78 #include "ED_armature.h"
79 #include "ED_image.h"
80 #include "ED_keyframing.h"
81 #include "ED_markers.h"
82 #include "ED_mesh.h"
83 #include "ED_particle.h"
84 #include "ED_screen_types.h"
85 #include "ED_space_api.h"
86 #include "ED_uvedit.h"
87 #include "ED_view3d.h"
88 #include "ED_curve.h" /* for curve_editnurbs */
89 #include "ED_clip.h"
90
91 //#include "BDR_unwrapper.h"
92
93 #include "BLI_math.h"
94 #include "BLI_blenlib.h"
95 #include "BLI_editVert.h"
96 #include "BLI_rand.h"
97 #include "BLI_utildefines.h"
98
99 #include "WM_types.h"
100 #include "WM_api.h"
101
102 #include "UI_resources.h"
103
104 //#include "blendef.h"
105 //
106 //#include "mydevice.h"
107
108 #include "transform.h"
109
110 extern ListBase editelems;
111
112 /* ************************** Functions *************************** */
113
114 void getViewVector(TransInfo *t, float coord[3], float vec[3])
115 {
116         if (t->persp != RV3D_ORTHO)
117         {
118                 float p1[4], p2[4];
119                 
120                 copy_v3_v3(p1, coord);
121                 p1[3] = 1.0f;
122                 copy_v3_v3(p2, p1);
123                 p2[3] = 1.0f;
124                 mul_m4_v4(t->viewmat, p2);
125                 
126                 p2[0] = 2.0f * p2[0];
127                 p2[1] = 2.0f * p2[1];
128                 p2[2] = 2.0f * p2[2];
129                 
130                 mul_m4_v4(t->viewinv, p2);
131                 
132                 sub_v3_v3v3(vec, p1, p2);
133         }
134         else {
135                 copy_v3_v3(vec, t->viewinv[2]);
136         }
137         normalize_v3(vec);
138 }
139
140 /* ************************** GENERICS **************************** */
141
142 static void clipMirrorModifier(TransInfo *t, Object *ob)
143 {
144         ModifierData *md= ob->modifiers.first;
145         float tolerance[3] = {0.0f, 0.0f, 0.0f};
146         int axis = 0;
147         
148         for (; md; md=md->next) {
149                 if ((md->type==eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
150                         MirrorModifierData *mmd = (MirrorModifierData*) md;
151                         
152                         if(mmd->flag & MOD_MIR_CLIPPING) {
153                                 axis = 0;
154                                 if(mmd->flag & MOD_MIR_AXIS_X) {
155                                         axis |= 1;
156                                         tolerance[0] = mmd->tolerance;
157                                 }
158                                 if(mmd->flag & MOD_MIR_AXIS_Y) {
159                                         axis |= 2;
160                                         tolerance[1] = mmd->tolerance;
161                                 }
162                                 if(mmd->flag & MOD_MIR_AXIS_Z) {
163                                         axis |= 4;
164                                         tolerance[2] = mmd->tolerance;
165                                 }
166                                 if (axis) {
167                                         float mtx[4][4], imtx[4][4];
168                                         int i;
169                                         TransData *td = t->data;
170                                         
171                                         if (mmd->mirror_ob) {
172                                                 float obinv[4][4];
173                                                 
174                                                 invert_m4_m4(obinv, mmd->mirror_ob->obmat);
175                                                 mult_m4_m4m4(mtx, obinv, ob->obmat);
176                                                 invert_m4_m4(imtx, mtx);
177                                         }
178                                         
179                                         for(i = 0 ; i < t->total; i++, td++) {
180                                                 int clip;
181                                                 float loc[3], iloc[3];
182                                                 
183                                                 if (td->flag & TD_NOACTION)
184                                                         break;
185                                                 if (td->loc==NULL)
186                                                         break;
187                                                 
188                                                 if (td->flag & TD_SKIP)
189                                                         continue;
190                                                 
191                                                 copy_v3_v3(loc,  td->loc);
192                                                 copy_v3_v3(iloc, td->iloc);
193                                                 
194                                                 if (mmd->mirror_ob) {
195                                                         mul_m4_v3(mtx, loc);
196                                                         mul_m4_v3(mtx, iloc);
197                                                 }
198                                                 
199                                                 clip = 0;
200                                                 if(axis & 1) {
201                                                         if(fabsf(iloc[0])<=tolerance[0] ||
202                                                            loc[0]*iloc[0]<0.0f)
203                                                         {
204                                                                 loc[0]= 0.0f;
205                                                                 clip = 1;
206                                                         }
207                                                 }
208                                                 
209                                                 if(axis & 2) {
210                                                         if(fabs(iloc[1])<=tolerance[1] ||
211                                                            loc[1]*iloc[1]<0.0f)
212                                                         {
213                                                                 loc[1]= 0.0f;
214                                                                 clip = 1;
215                                                         }
216                                                 }
217                                                 if(axis & 4) {
218                                                         if(fabs(iloc[2])<=tolerance[2] ||
219                                                            loc[2]*iloc[2]<0.0f)
220                                                         {
221                                                                 loc[2]= 0.0f;
222                                                                 clip = 1;
223                                                         }
224                                                 }
225                                                 if (clip) {
226                                                         if (mmd->mirror_ob) {
227                                                                 mul_m4_v3(imtx, loc);
228                                                         }
229                                                         copy_v3_v3(td->loc, loc);
230                                                 }
231                                         }
232                                 }
233                                 
234                         }
235                 }
236         }
237 }
238
239 /* assumes obedit set to mesh object */
240 static void editbmesh_apply_to_mirror(TransInfo *t)
241 {
242         TransData *td = t->data;
243         BMVert *eve;
244         int i;
245         
246         for(i = 0 ; i < t->total; i++, td++) {
247                 if (td->flag & TD_NOACTION)
248                         break;
249                 if (td->loc==NULL)
250                         break;
251                 if (td->flag & TD_SKIP)
252                         continue;
253                 
254                 eve = td->extra;
255                 if (eve) {
256                         eve->co[0]= -td->loc[0];
257                         eve->co[1]= td->loc[1];
258                         eve->co[2]= td->loc[2];
259                 }
260                 
261                 if (td->flag & TD_MIRROR_EDGE)
262                 {
263                         td->loc[0] = 0;
264                 }
265         }
266 }
267
268 /* for the realtime animation recording feature, handle overlapping data */
269 static void animrecord_check_state (Scene *scene, ID *id, wmTimer *animtimer)
270 {
271         ScreenAnimData *sad= (animtimer) ? animtimer->customdata : NULL;
272         
273         /* sanity checks */
274         if ELEM3(NULL, scene, id, sad)
275                 return;
276         
277         /* check if we need a new strip if:
278          *      - if animtimer is running 
279          *      - we're not only keying for available channels
280          *      - the option to add new actions for each round is not enabled
281          */
282         if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)==0 && (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) {
283                 /* if playback has just looped around, we need to add a new NLA track+strip to allow a clean pass to occur */
284                 if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
285                         AnimData *adt= BKE_animdata_from_id(id);
286                         
287                         /* perform push-down manually with some differences 
288                          * NOTE: BKE_nla_action_pushdown() sync warning...
289                          */
290                         if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
291                                 float astart, aend;
292                                 
293                                 /* only push down if action is more than 1-2 frames long */
294                                 calc_action_range(adt->action, &astart, &aend, 1);
295                                 if (aend > astart+2.0f) {
296                                         NlaStrip *strip= add_nlastrip_to_stack(adt, adt->action);
297                                         
298                                         /* clear reference to action now that we've pushed it onto the stack */
299                                         adt->action->id.us--;
300                                         adt->action= NULL;
301                                         
302                                         /* adjust blending + extend so that they will behave correctly */
303                                         strip->extendmode= NLASTRIP_EXTEND_NOTHING;
304                                         strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE);
305                                         
306                                         /* also, adjust the AnimData's action extend mode to be on 
307                                          * 'nothing' so that previous result still play 
308                                          */
309                                         adt->act_extendmode= NLASTRIP_EXTEND_NOTHING;
310                                 }
311                         }
312                 }
313         }
314 }
315
316 static int fcu_test_selected(FCurve *fcu)
317 {
318         BezTriple *bezt= fcu->bezt;
319         unsigned int i;
320
321         if (bezt==NULL) /* ignore baked */
322                 return 0;
323
324         for (i=0; i < fcu->totvert; i++, bezt++) {
325                 if (BEZSELECTED(bezt)) return 1;
326         }
327
328         return 0;
329 }
330
331 /* helper for recalcData() - for Action Editor transforms */
332 static void recalcData_actedit(TransInfo *t)
333 {
334         Scene *scene= t->scene;
335         SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first;
336         
337         bAnimContext ac= {NULL};
338         ListBase anim_data = {NULL, NULL};
339         bAnimListElem *ale;
340         int filter;
341         
342         /* initialise relevant anim-context 'context' data from TransInfo data */
343                 /* NOTE: sync this with the code in ANIM_animdata_get_context() */
344         ac.scene= t->scene;
345         ac.obact= OBACT;
346         ac.sa= t->sa;
347         ac.ar= t->ar;
348         ac.sl= (t->sa)? t->sa->spacedata.first : NULL;
349         ac.spacetype= (t->sa)? t->sa->spacetype : 0;
350         ac.regiontype= (t->ar)? t->ar->regiontype : 0;
351         
352         ANIM_animdata_context_getdata(&ac);
353         
354         /* perform flush */
355         if (ac.datatype == ANIMCONT_GPENCIL) {
356                 /* flush transform values back to actual coordinates */
357                 flushTransGPactionData(t);
358         }
359         else {
360                 /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
361                 filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
362                 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
363                 
364                 /* just tag these animdata-blocks to recalc, assuming that some data there changed 
365                  * BUT only do this if realtime updates are enabled
366                  */
367                 if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) {
368                         for (ale= anim_data.first; ale; ale= ale->next) {
369                                 /* set refresh tags for objects using this animation */
370                                 ANIM_list_elem_update(t->scene, ale);
371                         }
372                 }
373                 
374                 /* now free temp channels */
375                 BLI_freelistN(&anim_data);
376         }
377 }
378 /* helper for recalcData() - for Graph Editor transforms */
379 static void recalcData_graphedit(TransInfo *t)
380 {
381         SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
382         Scene *scene;
383         
384         ListBase anim_data = {NULL, NULL};
385         bAnimContext ac= {NULL};
386         int filter;
387         
388         bAnimListElem *ale;
389         int dosort = 0;
390         
391         
392         /* initialise relevant anim-context 'context' data from TransInfo data */
393                 /* NOTE: sync this with the code in ANIM_animdata_get_context() */
394         scene= ac.scene= t->scene;
395         ac.obact= OBACT;
396         ac.sa= t->sa;
397         ac.ar= t->ar;
398         ac.sl= (t->sa)? t->sa->spacedata.first : NULL;
399         ac.spacetype= (t->sa)? t->sa->spacetype : 0;
400         ac.regiontype= (t->ar)? t->ar->regiontype : 0;
401         
402         ANIM_animdata_context_getdata(&ac);
403         
404         /* do the flush first */
405         flushTransGraphData(t);
406         
407         /* get curves to check if a re-sort is needed */
408         filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
409         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
410         
411         /* now test if there is a need to re-sort */
412         for (ale= anim_data.first; ale; ale= ale->next) {
413                 FCurve *fcu= (FCurve *)ale->key_data;
414                 
415                 /* ignore unselected fcurves */
416                 if (!fcu_test_selected(fcu))
417                         continue;
418                 
419                 // fixme: only do this for selected verts...
420                 ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL|ANIM_UNITCONV_SELVERTS|ANIM_UNITCONV_RESTORE);
421                 
422                 
423                 /* watch it: if the time is wrong: do not correct handles yet */
424                 if (test_time_fcurve(fcu))
425                         dosort++;
426                 else
427                         calchandles_fcurve(fcu);
428                 
429                 /* set refresh tags for objects using this animation,
430                  * BUT only if realtime updates are enabled  
431                  */
432                 if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
433                         ANIM_list_elem_update(t->scene, ale);
434         }
435         
436         /* do resort and other updates? */
437         if (dosort) remake_graph_transdata(t, &anim_data);
438         
439         /* now free temp channels */
440         BLI_freelistN(&anim_data);
441 }
442
443 /* helper for recalcData() - for NLA Editor transforms */
444 static void recalcData_nla(TransInfo *t)
445 {
446         TransDataNla *tdn= (TransDataNla *)t->customData;
447         SpaceNla *snla= (SpaceNla *)t->sa->spacedata.first;
448         Scene *scene= t->scene;
449         double secf= FPS;
450         int i;
451         
452         /* for each strip we've got, perform some additional validation of the values that got set before
453          * using RNA to set the value (which does some special operations when setting these values to make
454          * sure that everything works ok)
455          */
456         for (i = 0; i < t->total; i++, tdn++) {
457                 NlaStrip *strip= tdn->strip;
458                 PointerRNA strip_ptr;
459                 short pExceeded, nExceeded, iter;
460                 int delta_y1, delta_y2;
461                 
462                 /* if this tdn has no handles, that means it is just a dummy that should be skipped */
463                 if (tdn->handle == 0)
464                         continue;
465                 
466                 /* set refresh tags for objects using this animation,
467                  * BUT only if realtime updates are enabled  
468                  */
469                 if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0)
470                         ANIM_id_update(t->scene, tdn->id);
471                 
472                 /* if cancelling transform, just write the values without validating, then move on */
473                 if (t->state == TRANS_CANCEL) {
474                         /* clear the values by directly overwriting the originals, but also need to restore
475                          * endpoints of neighboring transition-strips
476                          */
477                         
478                         /* start */
479                         strip->start= tdn->h1[0];
480                         
481                         if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
482                                 strip->prev->end= tdn->h1[0];
483                         
484                         /* end */
485                         strip->end= tdn->h2[0];
486                         
487                         if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
488                                 strip->next->start= tdn->h2[0];
489                         
490                         /* flush transforms to child strips (since this should be a meta) */
491                         BKE_nlameta_flush_transforms(strip);
492                         
493                         /* restore to original track (if needed) */
494                         if (tdn->oldTrack != tdn->nlt) {
495                                 /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
496                                 BLI_remlink(&tdn->nlt->strips, strip);
497                                 BLI_addtail(&tdn->oldTrack->strips, strip);
498                         }
499                         
500                         continue;
501                 }
502                 
503                 /* firstly, check if the proposed transform locations would overlap with any neighbouring strips
504                  * (barring transitions) which are absolute barriers since they are not being moved
505                  *
506                  * this is done as a iterative procedure (done 5 times max for now)
507                  */
508                 for (iter=0; iter < 5; iter++) {
509                         pExceeded= ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end));
510                         nExceeded= ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start));
511                         
512                         if ((pExceeded && nExceeded) || (iter == 4) ) {
513                                 /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
514                                  *      - simply crop strip to fit within the bounds of the strips bounding it
515                                  *      - if there were no neighbours, clear the transforms (make it default to the strip's current values)
516                                  */
517                                 if (strip->prev && strip->next) {
518                                         tdn->h1[0]= strip->prev->end;
519                                         tdn->h2[0]= strip->next->start;
520                                 }
521                                 else {
522                                         tdn->h1[0]= strip->start;
523                                         tdn->h2[0]= strip->end;
524                                 }
525                         }
526                         else if (nExceeded) {
527                                 /* move backwards */
528                                 float offset= tdn->h2[0] - strip->next->start;
529                                 
530                                 tdn->h1[0] -= offset;
531                                 tdn->h2[0] -= offset;
532                         }
533                         else if (pExceeded) {
534                                 /* more forwards */
535                                 float offset= strip->prev->end - tdn->h1[0];
536                                 
537                                 tdn->h1[0] += offset;
538                                 tdn->h2[0] += offset;
539                         }
540                         else /* all is fine and well */
541                                 break;
542                 }
543                 
544                 /* handle auto-snapping */
545                 switch (snla->autosnap) {
546                         case SACTSNAP_FRAME: /* snap to nearest frame/time  */
547                                 if (snla->flag & SNLA_DRAWTIME) {
548                                         tdn->h1[0]= (float)( floor((tdn->h1[0]/secf) + 0.5f) * secf );
549                                         tdn->h2[0]= (float)( floor((tdn->h2[0]/secf) + 0.5f) * secf );
550                                 }
551                                 else {
552                                         tdn->h1[0]= (float)( floor(tdn->h1[0]+0.5f) );
553                                         tdn->h2[0]= (float)( floor(tdn->h2[0]+0.5f) );
554                                 }
555                                 break;
556                         
557                         case SACTSNAP_MARKER: /* snap to nearest marker */
558                                 tdn->h1[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
559                                 tdn->h2[0]= (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
560                                 break;
561                 }
562                 
563                 /* use RNA to write the values... */
564                 // TODO: do we need to write in 2 passes to make sure that no truncation goes on?
565                 RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
566                 
567                 RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
568                 RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
569                 
570                 /* flush transforms to child strips (since this should be a meta) */
571                 BKE_nlameta_flush_transforms(strip);
572                 
573                 
574                 /* now, check if we need to try and move track
575                  *      - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
576                  */
577                 delta_y1= ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
578                 delta_y2= ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
579                 
580                 if (delta_y1 || delta_y2) {
581                         NlaTrack *track;
582                         int delta = (delta_y2) ? delta_y2 : delta_y1;
583                         int n;
584                         
585                         /* move in the requested direction, checking at each layer if there's space for strip to pass through,
586                          * stopping on the last track available or that we're able to fit in
587                          */
588                         if (delta > 0) {
589                                 for (track=tdn->nlt->next, n=0; (track) && (n < delta); track=track->next, n++) {
590                                         /* check if space in this track for the strip */
591                                         if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
592                                                 /* move strip to this track */
593                                                 BLI_remlink(&tdn->nlt->strips, strip);
594                                                 BKE_nlatrack_add_strip(track, strip);
595                                                 
596                                                 tdn->nlt= track;
597                                                 tdn->trackIndex++;
598                                         }
599                                         else /* can't move any further */
600                                                 break;
601                                 }
602                         }
603                         else {
604                                 /* make delta 'positive' before using it, since we now know to go backwards */
605                                 delta= -delta;
606                                 
607                                 for (track=tdn->nlt->prev, n=0; (track) && (n < delta); track=track->prev, n++) {
608                                         /* check if space in this track for the strip */
609                                         if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
610                                                 /* move strip to this track */
611                                                 BLI_remlink(&tdn->nlt->strips, strip);
612                                                 BKE_nlatrack_add_strip(track, strip);
613                                                 
614                                                 tdn->nlt= track;
615                                                 tdn->trackIndex--;
616                                         }
617                                         else /* can't move any further */
618                                                 break;
619                                 }
620                         }
621                 }
622         }
623 }
624
625 /* helper for recalcData() - for Image Editor transforms */
626 static void recalcData_image(TransInfo *t)
627 {
628         if (t->obedit && t->obedit->type == OB_MESH) {
629                 SpaceImage *sima= t->sa->spacedata.first;
630                 
631                 flushTransUVs(t);
632                 if(sima->flag & SI_LIVE_UNWRAP)
633                         ED_uvedit_live_unwrap_re_solve();
634                 
635                 DAG_id_tag_update(t->obedit->data, 0);
636         }
637 }
638
639 /* helper for recalcData() - for Movie Clip transforms */
640 static void recalcData_clip(TransInfo *t)
641 {
642         SpaceClip *sc= t->sa->spacedata.first;
643         MovieClip *clip= ED_space_clip(sc);
644         ListBase *tracksbase= BKE_tracking_get_tracks(&clip->tracking);
645         MovieTrackingTrack *track;
646         
647         flushTransTracking(t);
648         
649         track= tracksbase->first;
650         while(track) {
651                 if(TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED)==0) {
652                         if (t->mode == TFM_TRANSLATION) {
653                                 if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
654                                         BKE_tracking_clamp_track(track, CLAMP_PAT_POS);
655                                 if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
656                                         BKE_tracking_clamp_track(track, CLAMP_SEARCH_POS);
657                         }
658                         else if (t->mode == TFM_RESIZE) {
659                                 if(TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
660                                         BKE_tracking_clamp_track(track, CLAMP_PAT_DIM);
661                                 if(TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
662                                         BKE_tracking_clamp_track(track, CLAMP_SEARCH_DIM);
663                         }
664                 }
665                 
666                 track= track->next;
667         }
668         
669         DAG_id_tag_update(&clip->id, 0);
670 }
671
672 /* helper for recalcData() - for 3d-view transforms */
673 static void recalcData_view3d(TransInfo *t)
674 {
675         Base *base = t->scene->basact;
676         
677         if (t->obedit) {
678                 if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
679                         Curve *cu= t->obedit->data;
680                         ListBase *nurbs= curve_editnurbs(cu);
681                         Nurb *nu= nurbs->first;
682                         
683                         if(t->state != TRANS_CANCEL) {
684                                 clipMirrorModifier(t, t->obedit);
685                                 applyProject(t);
686                         }
687                         
688                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
689                                 
690                         if (t->state == TRANS_CANCEL) {
691                                 while(nu) {
692                                         calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
693                                         nu= nu->next;
694                                 }
695                         } 
696                         else {
697                                 /* Normal updating */
698                                 while(nu) {
699                                         test2DNurb(nu);
700                                         calchandlesNurb(nu);
701                                         nu= nu->next;
702                                 }
703                         }
704                 }
705                 else if(t->obedit->type==OB_LATTICE) {
706                         Lattice *la= t->obedit->data;
707                         
708                         if(t->state != TRANS_CANCEL) {
709                                 applyProject(t);
710                         }
711                         
712                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
713                         
714                         if(la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt);
715                 }
716                 else if (t->obedit->type == OB_MESH) {
717                         BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
718                         /* mirror modifier clipping? */
719                         if(t->state != TRANS_CANCEL) {
720                                 /* apply clipping after so we never project past the clip plane [#25423] */
721                                 applyProject(t);
722                                 clipMirrorModifier(t, t->obedit);
723                         }
724                         if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
725                                 editbmesh_apply_to_mirror(t);
726                                 
727                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
728                         
729                         EDBM_RecalcNormals(em);
730                         BMEdit_RecalcTesselation(em);
731                 }
732                 else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
733                         bArmature *arm= t->obedit->data;
734                         ListBase *edbo = arm->edbo;
735                         EditBone *ebo;
736                         TransData *td = t->data;
737                         int i;
738                         
739                         if(t->state != TRANS_CANCEL) {
740                                 applyProject(t);
741                         }
742                         
743                         /* Ensure all bones are correctly adjusted */
744                         for (ebo = edbo->first; ebo; ebo = ebo->next){
745                                 
746                                 if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
747                                         /* If this bone has a parent tip that has been moved */
748                                         if (ebo->parent->flag & BONE_TIPSEL){
749                                                 copy_v3_v3 (ebo->head, ebo->parent->tail);
750                                                 if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
751                                         }
752                                         /* If this bone has a parent tip that has NOT been moved */
753                                         else{
754                                                 copy_v3_v3 (ebo->parent->tail, ebo->head);
755                                                 if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
756                                         }
757                                 }
758                                 
759                                 /* on extrude bones, oldlength==0.0f, so we scale radius of points */
760                                 ebo->length= len_v3v3(ebo->head, ebo->tail);
761                                 if(ebo->oldlength==0.0f) {
762                                         ebo->rad_head= 0.25f*ebo->length;
763                                         ebo->rad_tail= 0.10f*ebo->length;
764                                         ebo->dist= 0.25f*ebo->length;
765                                         if(ebo->parent) {
766                                                 if(ebo->rad_head > ebo->parent->rad_tail)
767                                                         ebo->rad_head= ebo->parent->rad_tail;
768                                         }
769                                 }
770                                 else if(t->mode!=TFM_BONE_ENVELOPE) {
771                                         /* if bones change length, lets do that for the deform distance as well */
772                                         ebo->dist*= ebo->length/ebo->oldlength;
773                                         ebo->rad_head*= ebo->length/ebo->oldlength;
774                                         ebo->rad_tail*= ebo->length/ebo->oldlength;
775                                         ebo->oldlength= ebo->length;
776                                 }
777                         }
778                         
779                         
780                         if (t->mode != TFM_BONE_ROLL)
781                         {
782                                 /* fix roll */
783                                 for(i = 0; i < t->total; i++, td++)
784                                 {
785                                         if (td->extra)
786                                         {
787                                                 float vec[3], up_axis[3];
788                                                 float qrot[4];
789                                                 
790                                                 ebo = td->extra;
791                                                 copy_v3_v3(up_axis, td->axismtx[2]);
792                                                 
793                                                 if (t->mode != TFM_ROTATION)
794                                                 {
795                                                         sub_v3_v3v3(vec, ebo->tail, ebo->head);
796                                                         normalize_v3(vec);
797                                                         rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
798                                                         mul_qt_v3(qrot, up_axis);
799                                                 }
800                                                 else
801                                                 {
802                                                         mul_m3_v3(t->mat, up_axis);
803                                                 }
804                                                 
805                                                 ebo->roll = ED_rollBoneToVector(ebo, up_axis, FALSE);
806                                         }
807                                 }
808                         }
809                         
810                         if(arm->flag & ARM_MIRROR_EDIT)
811                                 transform_armature_mirror_update(t->obedit);
812                         
813                 }
814                 else
815                 {
816                         if(t->state != TRANS_CANCEL) {
817                                 applyProject(t);
818                         }
819                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
820                 }
821         }
822         else if( (t->flag & T_POSE) && t->poseobj) {
823                 Object *ob= t->poseobj;
824                 bArmature *arm= ob->data;
825                 
826                 /* if animtimer is running, and the object already has animation data,
827                  * check if the auto-record feature means that we should record 'samples'
828                  * (i.e. uneditable animation values)
829                  *
830                  * context is needed for keying set poll() functions.
831                  */
832                 // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
833                 if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) {
834                         int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
835                         
836                         animrecord_check_state(t->scene, &ob->id, t->animtimer);
837                         autokeyframe_pose_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
838                 }
839                 
840                 /* old optimize trick... this enforces to bypass the depgraph */
841                 if (!(arm->flag & ARM_DELAYDEFORM)) {
842                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
843                 }
844                 else
845                         where_is_pose(t->scene, ob);
846         }
847         else if(base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) {
848                 if(t->state != TRANS_CANCEL) {
849                         applyProject(t);
850                 }
851                 flushTransParticles(t);
852         }
853         else {
854                 int i;
855                 
856                 if(t->state != TRANS_CANCEL) {
857                         applyProject(t);
858                 }
859                 
860                 for (i = 0; i < t->total; i++) {
861                         TransData *td = t->data + i;
862                         Object *ob = td->ob;
863                         
864                         if (td->flag & TD_NOACTION)
865                                 break;
866                         
867                         if (td->flag & TD_SKIP)
868                                 continue;
869                         
870                         /* if animtimer is running, and the object already has animation data,
871                          * check if the auto-record feature means that we should record 'samples'
872                          * (i.e. uneditable animation values)
873                          */
874                         // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
875                         if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
876                                 animrecord_check_state(t->scene, &ob->id, t->animtimer);
877                                 autokeyframe_ob_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode);
878                         }
879                         
880                         /* sets recalc flags fully, instead of flushing existing ones 
881                          * otherwise proxies don't function correctly
882                          */
883                         DAG_id_tag_update(&ob->id, OB_RECALC_OB);
884                 }
885         }
886 }
887
888 /* called for updating while transform acts, once per redraw */
889 void recalcData(TransInfo *t)
890 {
891         if (t->spacetype==SPACE_NODE) {
892                 flushTransNodes(t);
893         }
894         else if (t->spacetype==SPACE_SEQ) {
895                 flushTransSeq(t);
896         }
897         else if (t->spacetype == SPACE_ACTION) {
898                 recalcData_actedit(t);
899         }
900         else if (t->spacetype == SPACE_IPO) {
901                 recalcData_graphedit(t);
902         }
903         else if (t->spacetype == SPACE_NLA) {
904                 recalcData_nla(t);
905         }
906         else if (t->spacetype == SPACE_IMAGE) {
907                 recalcData_image(t);
908         }
909         else if (t->spacetype == SPACE_VIEW3D) {
910                 recalcData_view3d(t);
911         }
912         else if (t->spacetype == SPACE_CLIP) {
913                 recalcData_clip(t);
914         }
915 }
916
917 void drawLine(TransInfo *t, float *center, float *dir, char axis, short options)
918 {
919         float v1[3], v2[3], v3[3];
920         unsigned char col[3], col2[3];
921
922         if (t->spacetype == SPACE_VIEW3D)
923         {
924                 View3D *v3d = t->view;
925                 
926                 glPushMatrix();
927                 
928                 //if(t->obedit) glLoadMatrixf(t->obedit->obmat);        // sets opengl viewing
929                 
930                 
931                 copy_v3_v3(v3, dir);
932                 mul_v3_fl(v3, v3d->far);
933                 
934                 sub_v3_v3v3(v2, center, v3);
935                 add_v3_v3v3(v1, center, v3);
936                 
937                 if (options & DRAWLIGHT) {
938                         col[0] = col[1] = col[2] = 220;
939                 }
940                 else {
941                         UI_GetThemeColor3ubv(TH_GRID, col);
942                 }
943                 UI_make_axis_color(col, col2, axis);
944                 glColor3ubv(col2);
945                 
946                 setlinestyle(0);
947                 glBegin(GL_LINE_STRIP);
948                         glVertex3fv(v1);
949                         glVertex3fv(v2);
950                 glEnd();
951                 
952                 glPopMatrix();
953         }
954 }
955
956 void resetTransRestrictions(TransInfo *t)
957 {
958         t->flag &= ~T_ALL_RESTRICTIONS;
959 }
960
961 /* the *op can be NULL */
962 int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event)
963 {
964         Scene *sce = CTX_data_scene(C);
965         ToolSettings *ts = CTX_data_tool_settings(C);
966         ARegion *ar = CTX_wm_region(C);
967         ScrArea *sa = CTX_wm_area(C);
968         Object *obedit = CTX_data_edit_object(C);
969         
970         /* moving: is shown in drawobject() (transform color) */
971 //  TRANSFORM_FIX_ME
972 //      if(obedit || (t->flag & T_POSE) ) G.moving= G_TRANSFORM_EDIT;
973 //      else if(G.f & G_PARTICLEEDIT) G.moving= G_TRANSFORM_PARTICLE;
974 //      else G.moving= G_TRANSFORM_OBJ;
975         
976         t->scene = sce;
977         t->sa = sa;
978         t->ar = ar;
979         t->obedit = obedit;
980         t->settings = ts;
981         
982         t->data = NULL;
983         t->ext = NULL;
984         
985         t->helpline = HLP_NONE;
986         
987         t->flag = 0;
988         
989         t->redraw = 1; /* redraw first time */
990         
991         if (event)
992         {
993                 copy_v2_v2_int(t->imval, event->mval);
994                 t->event_type = event->type;
995         }
996         else
997         {
998                 t->imval[0] = 0;
999                 t->imval[1] = 0;
1000         }
1001         
1002         t->con.imval[0] = t->imval[0];
1003         t->con.imval[1] = t->imval[1];
1004         
1005         t->mval[0] = t->imval[0];
1006         t->mval[1] = t->imval[1];
1007         
1008         t->transform            = NULL;
1009         t->handleEvent          = NULL;
1010         
1011         t->total                        = 0;
1012         
1013         t->val = 0.0f;
1014         
1015         t->vec[0]                       =
1016                 t->vec[1]               =
1017                 t->vec[2]               = 0.0f;
1018         
1019         t->center[0]            =
1020                 t->center[1]    =
1021                 t->center[2]    = 0.0f;
1022         
1023         unit_m3(t->mat);
1024         
1025         /* if there's an event, we're modal */
1026         if (event) {
1027                 t->flag |= T_MODAL;
1028         }
1029
1030         /* Crease needs edge flag */
1031         if (t->mode == TFM_CREASE) {
1032                 t->options |= CTX_EDGE;
1033         }
1034
1035
1036         /* Assign the space type, some exceptions for running in different mode */
1037         if(sa == NULL) {
1038                 /* background mode */
1039                 t->spacetype= SPACE_EMPTY;
1040         }
1041         else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
1042                 /* running in the text editor */
1043                 t->spacetype= SPACE_EMPTY;
1044         }
1045         else {
1046                 /* normal operation */
1047                 t->spacetype= sa->spacetype;
1048         }
1049
1050
1051         if(t->spacetype == SPACE_VIEW3D)
1052         {
1053                 View3D *v3d = sa->spacedata.first;
1054                 
1055                 t->view = v3d;
1056                 t->animtimer= CTX_wm_screen(C)->animtimer;
1057                 
1058                 /* turn manipulator off during transform */
1059                 // FIXME: but don't do this when USING the manipulator...
1060                 if (t->flag & T_MODAL) {
1061                         t->twtype = v3d->twtype;
1062                         v3d->twtype = 0;
1063                 }
1064
1065                 if(v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
1066                 t->around = v3d->around;
1067                 
1068                 if (op && RNA_struct_find_property(op->ptr, "constraint_orientation") && RNA_struct_property_is_set(op->ptr, "constraint_orientation"))
1069                 {
1070                         t->current_orientation = RNA_enum_get(op->ptr, "constraint_orientation");
1071                         
1072                         if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C))
1073                         {
1074                                 t->current_orientation = V3D_MANIP_GLOBAL;
1075                         }
1076                 }
1077                 else
1078                 {
1079                         t->current_orientation = v3d->twmode;
1080                 }
1081
1082                 /* exceptional case */
1083                 if(t->around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
1084                         if(ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
1085                                 t->options |= CTX_NO_PET;
1086                         }
1087                 }
1088
1089                 /* initialize UV transform from */
1090                 if (op && RNA_struct_find_property(op->ptr, "correct_uv")) {
1091                         if(RNA_struct_property_is_set(op->ptr, "correct_uv")) {
1092                                 if(RNA_boolean_get(op->ptr, "correct_uv")) {
1093                                         t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
1094                                 }
1095                                 else {
1096                                         t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
1097                                 }
1098                         }
1099                         else {
1100                                 RNA_boolean_set(op->ptr, "correct_uv", t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT);
1101                         }
1102                 }
1103
1104         }
1105         else if(t->spacetype==SPACE_IMAGE)
1106         {
1107                 SpaceImage *sima = sa->spacedata.first;
1108                 // XXX for now, get View2D from the active region
1109                 t->view = &ar->v2d;
1110                 t->around = sima->around;
1111         }
1112         else if(t->spacetype==SPACE_NODE)
1113         {
1114                 // XXX for now, get View2D from the active region
1115                 t->view = &ar->v2d;
1116                 t->around = V3D_CENTER;
1117         }
1118         else if(t->spacetype==SPACE_IPO) 
1119         {
1120                 SpaceIpo *sipo= sa->spacedata.first;
1121                 t->view = &ar->v2d;
1122                 t->around = sipo->around;
1123         }
1124         else
1125         {
1126                 if(ar) {
1127                         // XXX for now, get View2D  from the active region
1128                         t->view = &ar->v2d;
1129                         // XXX for now, the center point is the midpoint of the data
1130                 }
1131                 else {
1132                         t->view= NULL;
1133                 }
1134                 t->around = V3D_CENTER;
1135         }
1136         
1137         if (op && RNA_struct_property_is_set(op->ptr, "release_confirm"))
1138         {
1139                 if (RNA_boolean_get(op->ptr, "release_confirm"))
1140                 {
1141                         t->flag |= T_RELEASE_CONFIRM;
1142                 }
1143         }
1144         else
1145         {
1146                 if (U.flag & USER_RELEASECONFIRM)
1147                 {
1148                         t->flag |= T_RELEASE_CONFIRM;
1149                 }
1150         }
1151
1152         if (op && RNA_struct_find_property(op->ptr, "mirror") && RNA_struct_property_is_set(op->ptr, "mirror"))
1153         {
1154                 if (RNA_boolean_get(op->ptr, "mirror"))
1155                 {
1156                         t->flag |= T_MIRROR;
1157                         t->mirror = 1;
1158                 }
1159         }
1160         // Need stuff to take it from edit mesh or whatnot here
1161         else if (t->spacetype == SPACE_VIEW3D)
1162         {
1163                 if (t->obedit && t->obedit->type == OB_MESH && (((Mesh *)t->obedit->data)->editflag & ME_EDIT_MIRROR_X))
1164                 {
1165                         t->flag |= T_MIRROR;
1166                         t->mirror = 1;
1167                 }
1168         }
1169         
1170         /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
1171         if (op && RNA_struct_find_property(op->ptr, "proportional"))
1172         {
1173                 if (RNA_struct_property_is_set(op->ptr, "proportional"))
1174                 {
1175                         switch(RNA_enum_get(op->ptr, "proportional"))
1176                         {
1177                         case PROP_EDIT_CONNECTED:
1178                                 t->flag |= T_PROP_CONNECTED;
1179                         case PROP_EDIT_ON:
1180                                 t->flag |= T_PROP_EDIT;
1181                                 break;
1182                         }
1183                 }
1184                 else
1185                 {
1186                         /* use settings from scene only if modal */
1187                         if (t->flag & T_MODAL)
1188                         {
1189                                 if ((t->options & CTX_NO_PET) == 0)
1190                                 {
1191                                         if (t->obedit && ts->proportional != PROP_EDIT_OFF)
1192                                         {
1193                                                 t->flag |= T_PROP_EDIT;
1194
1195                                                 if(ts->proportional == PROP_EDIT_CONNECTED)
1196                                                         t->flag |= T_PROP_CONNECTED;
1197                                         }
1198                                         else if (t->obedit == NULL && ts->proportional_objects)
1199                                         {
1200                                                 t->flag |= T_PROP_EDIT;
1201                                         }
1202                                 }
1203                         }
1204                 }
1205                 
1206                 if (op && RNA_struct_find_property(op->ptr, "proportional_size") && RNA_struct_property_is_set(op->ptr, "proportional_size"))
1207                 {
1208                         t->prop_size = RNA_float_get(op->ptr, "proportional_size");
1209                 }
1210                 else
1211                 {
1212                         t->prop_size = ts->proportional_size;
1213                 }
1214                 
1215                 
1216                 /* TRANSFORM_FIX_ME rna restrictions */
1217                 if (t->prop_size <= 0.00001f)
1218                 {
1219                         printf("Proportional size (%f) under 0.00001, reseting to 1!\n", t->prop_size);
1220                         t->prop_size = 1.0f;
1221                 }
1222                 
1223                 if (op && RNA_struct_find_property(op->ptr, "proportional_edit_falloff") && RNA_struct_property_is_set(op->ptr, "proportional_edit_falloff"))
1224                 {
1225                         t->prop_mode = RNA_enum_get(op->ptr, "proportional_edit_falloff");
1226                 }
1227                 else
1228                 {
1229                         t->prop_mode = ts->prop_mode;
1230                 }
1231         }
1232         else /* add not pet option to context when not available */
1233         {
1234                 t->options |= CTX_NO_PET;
1235         }
1236         
1237         // Mirror is not supported with PET, turn it off.
1238         if (t->flag & T_PROP_EDIT)
1239         {
1240                 t->flag &= ~T_MIRROR;
1241         }
1242
1243         setTransformViewMatrices(t);
1244         initNumInput(&t->num);
1245         
1246         return 1;
1247 }
1248
1249 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
1250 void postTrans (bContext *C, TransInfo *t)
1251 {
1252         TransData *td;
1253         
1254         if (t->draw_handle_view)
1255                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
1256         if (t->draw_handle_apply)
1257                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
1258         if (t->draw_handle_pixel)
1259                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
1260         if (t->draw_handle_cursor)
1261                 WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
1262
1263         if (t->customFree) {
1264                 /* Can take over freeing t->data and data2d etc... */
1265                 t->customFree(t);
1266         }
1267         else if (t->customData) {
1268                 MEM_freeN(t->customData);
1269         }
1270
1271         /* postTrans can be called when nothing is selected, so data is NULL already */
1272         if (t->data) {
1273                 int a;
1274                 
1275                 /* free data malloced per trans-data */
1276                 for(a=0, td= t->data; a<t->total; a++, td++) {
1277                         if (td->flag & TD_BEZTRIPLE) 
1278                                 MEM_freeN(td->hdata);
1279                 }
1280                 MEM_freeN(t->data);
1281         }
1282         
1283         BLI_freelistN(&t->tsnap.points);
1284
1285         if (t->ext) MEM_freeN(t->ext);
1286         if (t->data2d) {
1287                 MEM_freeN(t->data2d);
1288                 t->data2d= NULL;
1289         }
1290         
1291         if(t->spacetype==SPACE_IMAGE) {
1292                 SpaceImage *sima= t->sa->spacedata.first;
1293                 if(sima->flag & SI_LIVE_UNWRAP)
1294                         ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
1295         }
1296         else if(t->spacetype==SPACE_VIEW3D) {
1297                 View3D *v3d = t->sa->spacedata.first;
1298                 /* restore manipulator */
1299                 if (t->flag & T_MODAL) {
1300                         v3d->twtype = t->twtype;
1301                 }
1302         }
1303         
1304         if (t->mouse.data)
1305         {
1306                 MEM_freeN(t->mouse.data);
1307         }
1308 }
1309
1310 void applyTransObjects(TransInfo *t)
1311 {
1312         TransData *td;
1313         
1314         for (td = t->data; td < t->data + t->total; td++) {
1315                 copy_v3_v3(td->iloc, td->loc);
1316                 if (td->ext->rot) {
1317                         copy_v3_v3(td->ext->irot, td->ext->rot);
1318                 }
1319                 if (td->ext->size) {
1320                         copy_v3_v3(td->ext->isize, td->ext->size);
1321                 }
1322         }
1323         recalcData(t);
1324 }
1325
1326 static void restoreElement(TransData *td)
1327 {
1328         /* TransData for crease has no loc */
1329         if (td->loc) {
1330                 copy_v3_v3(td->loc, td->iloc);
1331         }
1332         if (td->val) {
1333                 *td->val = td->ival;
1334         }
1335
1336         if (td->ext && (td->flag&TD_NO_EXT)==0) {
1337                 if (td->ext->rot) {
1338                         copy_v3_v3(td->ext->rot, td->ext->irot);
1339                 }
1340                 if(td->ext->rotAngle) {
1341                         *td->ext->rotAngle= td->ext->irotAngle;
1342                 }
1343                 if(td->ext->rotAxis) {
1344                         copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
1345                 }
1346                 /* XXX, drotAngle & drotAxis not used yet */
1347                 if (td->ext->size) {
1348                         copy_v3_v3(td->ext->size, td->ext->isize);
1349                 }
1350                 if (td->ext->quat) {
1351                         copy_qt_qt(td->ext->quat, td->ext->iquat);
1352                 }
1353         }
1354         
1355         if (td->flag & TD_BEZTRIPLE) {
1356                 *(td->hdata->h1) = td->hdata->ih1;
1357                 *(td->hdata->h2) = td->hdata->ih2;
1358         }
1359 }
1360
1361 void restoreTransObjects(TransInfo *t)
1362 {
1363         TransData *td;
1364         TransData2D *td2d;
1365
1366         for (td = t->data; td < t->data + t->total; td++) {
1367                 restoreElement(td);
1368         }
1369         
1370         for (td2d=t->data2d; t->data2d && td2d < t->data2d + t->total; td2d++) {
1371                 if (td2d->h1) {
1372                         td2d->h1[0] = td2d->ih1[0];
1373                         td2d->h1[1] = td2d->ih1[1];
1374                 }
1375                 if (td2d->h2) {
1376                         td2d->h2[0] = td2d->ih2[0];
1377                         td2d->h2[1] = td2d->ih2[1];
1378                 }
1379         }
1380
1381         unit_m3(t->mat);
1382         
1383         recalcData(t);
1384 }
1385
1386 void calculateCenter2D(TransInfo *t)
1387 {
1388         if (t->flag & (T_EDIT|T_POSE)) {
1389                 Object *ob= t->obedit?t->obedit:t->poseobj;
1390                 float vec[3];
1391                 
1392                 copy_v3_v3(vec, t->center);
1393                 mul_m4_v3(ob->obmat, vec);
1394                 projectIntView(t, vec, t->center2d);
1395         }
1396         else {
1397                 projectIntView(t, t->center, t->center2d);
1398         }
1399 }
1400
1401 void calculateCenterCursor(TransInfo *t)
1402 {
1403         float *cursor;
1404         
1405         cursor = give_cursor(t->scene, t->view);
1406         copy_v3_v3(t->center, cursor);
1407         
1408         /* If edit or pose mode, move cursor in local space */
1409         if (t->flag & (T_EDIT|T_POSE)) {
1410                 Object *ob = t->obedit?t->obedit:t->poseobj;
1411                 float mat[3][3], imat[3][3];
1412                 
1413                 sub_v3_v3v3(t->center, t->center, ob->obmat[3]);
1414                 copy_m3_m4(mat, ob->obmat);
1415                 invert_m3_m3(imat, mat);
1416                 mul_m3_v3(imat, t->center);
1417         }
1418         
1419         calculateCenter2D(t);
1420 }
1421
1422 void calculateCenterCursor2D(TransInfo *t)
1423 {
1424         float aspx=1.0, aspy=1.0;
1425         float *cursor= NULL;
1426         
1427         if(t->spacetype==SPACE_IMAGE) {
1428                 SpaceImage *sima= (SpaceImage *)t->sa->spacedata.first;
1429                 /* only space supported right now but may change */
1430                 ED_space_image_uv_aspect(sima, &aspx, &aspy);
1431                 cursor = sima->cursor;
1432         }
1433         
1434         if (cursor) {
1435                 t->center[0] = cursor[0] * aspx;
1436                 t->center[1] = cursor[1] * aspy;
1437         }
1438         
1439         calculateCenter2D(t);
1440 }
1441
1442 static void calculateCenterCursorGraph2D(TransInfo *t)
1443 {
1444         SpaceIpo *sipo= (SpaceIpo *)t->sa->spacedata.first;
1445         Scene *scene= t->scene;
1446         
1447         /* cursor is combination of current frame, and graph-editor cursor value */
1448         t->center[0]= (float)(scene->r.cfra);
1449         t->center[1]= sipo->cursorVal;
1450         
1451         calculateCenter2D(t);
1452 }
1453
1454 void calculateCenterMedian(TransInfo *t)
1455 {
1456         float partial[3] = {0.0f, 0.0f, 0.0f};
1457         int total = 0;
1458         int i;
1459         
1460         for(i = 0; i < t->total; i++) {
1461                 if (t->data[i].flag & TD_SELECTED) {
1462                         if (!(t->data[i].flag & TD_NOCENTER))
1463                         {
1464                                 add_v3_v3(partial, t->data[i].center);
1465                                 total++;
1466                         }
1467                 }
1468                 else {
1469                         /*
1470                            All the selected elements are at the head of the array
1471                            which means we can stop when it finds unselected data
1472                         */
1473                         break;
1474                 }
1475         }
1476         if(i)
1477                 mul_v3_fl(partial, 1.0f / total);
1478         copy_v3_v3(t->center, partial);
1479         
1480         calculateCenter2D(t);
1481 }
1482
1483 void calculateCenterBound(TransInfo *t)
1484 {
1485         float max[3];
1486         float min[3];
1487         int i;
1488         for(i = 0; i < t->total; i++) {
1489                 if (i) {
1490                         if (t->data[i].flag & TD_SELECTED) {
1491                                 if (!(t->data[i].flag & TD_NOCENTER))
1492                                         minmax_v3v3_v3(min, max, t->data[i].center);
1493                         }
1494                         else {
1495                                 /*
1496                                    All the selected elements are at the head of the array
1497                                    which means we can stop when it finds unselected data
1498                                 */
1499                                 break;
1500                         }
1501                 }
1502                 else {
1503                         copy_v3_v3(max, t->data[i].center);
1504                         copy_v3_v3(min, t->data[i].center);
1505                 }
1506         }
1507         add_v3_v3v3(t->center, min, max);
1508         mul_v3_fl(t->center, 0.5);
1509         
1510         calculateCenter2D(t);
1511 }
1512
1513 void calculateCenter(TransInfo *t)
1514 {
1515         switch(t->around) {
1516         case V3D_CENTER:
1517                 calculateCenterBound(t);
1518                 break;
1519         case V3D_CENTROID:
1520                 calculateCenterMedian(t);
1521                 break;
1522         case V3D_CURSOR:
1523                 if(t->spacetype==SPACE_IMAGE)
1524                         calculateCenterCursor2D(t);
1525                 else if(t->spacetype==SPACE_IPO)
1526                         calculateCenterCursorGraph2D(t);
1527                 else
1528                         calculateCenterCursor(t);
1529                 break;
1530         case V3D_LOCAL:
1531                 /* Individual element center uses median center for helpline and such */
1532                 calculateCenterMedian(t);
1533                 break;
1534         case V3D_ACTIVE:
1535                 {
1536                 /* set median, and if if if... do object center */
1537                 
1538                 /* EDIT MODE ACTIVE EDITMODE ELEMENT */
1539
1540                 if (t->obedit) {
1541                         if (t->obedit && t->obedit->type == OB_MESH) {
1542                                 BMEditSelection ese;
1543                                 BMEditMesh *em = ((Mesh*)t->obedit->data)->edit_btmesh;
1544
1545                                 if (EDBM_get_actSelection(em, &ese)) {
1546                                         EDBM_editselection_center(em, t->center, &ese);
1547                                         calculateCenter2D(t);
1548                                         break;
1549                                 }
1550                         }
1551                         else if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
1552                                 float center[3];
1553                                 Curve *cu= (Curve *)t->obedit->data;
1554
1555                                 if (ED_curve_actSelection(cu, center)) {
1556                                         copy_v3_v3(t->center, center);
1557                                         calculateCenter2D(t);
1558                                         break;
1559                                 }
1560                         }
1561                 } /* END EDIT MODE ACTIVE ELEMENT */
1562
1563                 calculateCenterMedian(t);
1564                 if((t->flag & (T_EDIT|T_POSE))==0)
1565                 {
1566                         Scene *scene = t->scene;
1567                         Object *ob= OBACT;
1568                         if(ob)
1569                         {
1570                                 copy_v3_v3(t->center, ob->obmat[3]);
1571                                 projectIntView(t, t->center, t->center2d);
1572                         }
1573                 }
1574                 
1575                 }
1576         }
1577         
1578         /* setting constraint center */
1579         copy_v3_v3(t->con.center, t->center);
1580         if(t->flag & (T_EDIT|T_POSE))
1581         {
1582                 Object *ob= t->obedit?t->obedit:t->poseobj;
1583                 mul_m4_v3(ob->obmat, t->con.center);
1584         }
1585         
1586         /* for panning from cameraview */
1587         if(t->flag & T_OBJECT)
1588         {
1589                 if(t->spacetype==SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW)
1590                 {
1591                         View3D *v3d = t->view;
1592                         Scene *scene = t->scene;
1593                         RegionView3D *rv3d = t->ar->regiondata;
1594                         
1595                         if(v3d->camera == OBACT && rv3d->persp==RV3D_CAMOB)
1596                         {
1597                                 float axis[3];
1598                                 /* persinv is nasty, use viewinv instead, always right */
1599                                 copy_v3_v3(axis, t->viewinv[2]);
1600                                 normalize_v3(axis);
1601                                 
1602                                 /* 6.0 = 6 grid units */
1603                                 axis[0]= t->center[0]- 6.0f*axis[0];
1604                                 axis[1]= t->center[1]- 6.0f*axis[1];
1605                                 axis[2]= t->center[2]- 6.0f*axis[2];
1606                                 
1607                                 projectIntView(t, axis, t->center2d);
1608                                 
1609                                 /* rotate only needs correct 2d center, grab needs initgrabz() value */
1610                                 if(t->mode==TFM_TRANSLATION)
1611                                 {
1612                                         copy_v3_v3(t->center, axis);
1613                                         copy_v3_v3(t->con.center, t->center);
1614                                 }
1615                         }
1616                 }
1617         }
1618         
1619         if(t->spacetype==SPACE_VIEW3D)
1620         {
1621                 /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */
1622                 if(t->flag & (T_EDIT|T_POSE)) {
1623                         Object *ob= t->obedit?t->obedit:t->poseobj;
1624                         float vec[3];
1625                         
1626                         copy_v3_v3(vec, t->center);
1627                         mul_m4_v3(ob->obmat, vec);
1628                         initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]);
1629                 }
1630                 else {
1631                         initgrabz(t->ar->regiondata, t->center[0], t->center[1], t->center[2]);
1632                 }
1633         }
1634 }
1635
1636 void calculatePropRatio(TransInfo *t)
1637 {
1638         TransData *td = t->data;
1639         int i;
1640         float dist;
1641         short connected = t->flag & T_PROP_CONNECTED;
1642
1643         if (t->flag & T_PROP_EDIT) {
1644                 for(i = 0 ; i < t->total; i++, td++) {
1645                         if (td->flag & TD_SELECTED) {
1646                                 td->factor = 1.0f;
1647                         }
1648                         else if (t->flag & T_MIRROR && td->loc[0] * t->mirror < -0.00001f)
1649                         {
1650                                 td->flag |= TD_SKIP;
1651                                 td->factor = 0.0f;
1652                                 restoreElement(td);
1653                         }
1654                         else if ((connected &&
1655                                                 (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size))
1656                                 ||
1657                                         (connected == 0 &&
1658                                                 td->rdist > t->prop_size)) {
1659                                 /*
1660                                    The elements are sorted according to their dist member in the array,
1661                                    that means we can stop when it finds one element outside of the propsize.
1662                                 */
1663                                 td->flag |= TD_NOACTION;
1664                                 td->factor = 0.0f;
1665                                 restoreElement(td);
1666                         }
1667                         else {
1668                                 /* Use rdist for falloff calculations, it is the real distance */
1669                                 td->flag &= ~TD_NOACTION;
1670                                 
1671                                 if (connected)
1672                                         dist= (t->prop_size-td->dist)/t->prop_size;
1673                                 else
1674                                         dist= (t->prop_size-td->rdist)/t->prop_size;
1675
1676                                 /*
1677                                  * Clamp to positive numbers.
1678                                  * Certain corner cases with connectivity and individual centers
1679                                  * can give values of rdist larger than propsize.
1680                                  */
1681                                 if (dist < 0.0f)
1682                                         dist = 0.0f;
1683                                 
1684                                 switch(t->prop_mode) {
1685                                 case PROP_SHARP:
1686                                         td->factor= dist*dist;
1687                                         break;
1688                                 case PROP_SMOOTH:
1689                                         td->factor= 3.0f*dist*dist - 2.0f*dist*dist*dist;
1690                                         break;
1691                                 case PROP_ROOT:
1692                                         td->factor = (float)sqrt(dist);
1693                                         break;
1694                                 case PROP_LIN:
1695                                         td->factor = dist;
1696                                         break;
1697                                 case PROP_CONST:
1698                                         td->factor = 1.0f;
1699                                         break;
1700                                 case PROP_SPHERE:
1701                                         td->factor = (float)sqrt(2*dist - dist * dist);
1702                                         break;
1703                                 case PROP_RANDOM:
1704                                         BLI_srand( BLI_rand() ); /* random seed */
1705                                         td->factor = BLI_frand()*dist;
1706                                         break;
1707                                 default:
1708                                         td->factor = 1;
1709                                 }
1710                         }
1711                 }
1712                 switch(t->prop_mode) {
1713                 case PROP_SHARP:
1714                         strcpy(t->proptext, "(Sharp)");
1715                         break;
1716                 case PROP_SMOOTH:
1717                         strcpy(t->proptext, "(Smooth)");
1718                         break;
1719                 case PROP_ROOT:
1720                         strcpy(t->proptext, "(Root)");
1721                         break;
1722                 case PROP_LIN:
1723                         strcpy(t->proptext, "(Linear)");
1724                         break;
1725                 case PROP_CONST:
1726                         strcpy(t->proptext, "(Constant)");
1727                         break;
1728                 case PROP_SPHERE:
1729                         strcpy(t->proptext, "(Sphere)");
1730                         break;
1731                 case PROP_RANDOM:
1732                         strcpy(t->proptext, "(Random)");
1733                         break;
1734                 default:
1735                         t->proptext[0]= '\0';
1736                 }
1737         }
1738         else {
1739                 for(i = 0 ; i < t->total; i++, td++) {
1740                         td->factor = 1.0;
1741                 }
1742                 t->proptext[0]= '\0';
1743         }
1744 }