Fix T54766: "Record With"-NLA "Push Down" discards Blend Mode, Extrapolation, and...
[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 #include <string.h>
33 #include <math.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_sys_types.h" /* for intptr_t support */
38
39 #include "DNA_anim_types.h"
40 #include "DNA_armature_types.h"
41 #include "DNA_brush_types.h"
42 #include "DNA_gpencil_types.h"
43 #include "DNA_lattice_types.h"
44 #include "DNA_screen_types.h"
45 #include "DNA_sequence_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_mesh_types.h"
50 #include "DNA_view3d_types.h"
51 #include "DNA_modifier_types.h"
52 #include "DNA_movieclip_types.h"
53 #include "DNA_mask_types.h"
54 #include "DNA_meta_types.h"
55
56 #include "BLI_math.h"
57 #include "BLI_blenlib.h"
58 #include "BLI_rand.h"
59 #include "BLI_utildefines.h"
60
61 #include "BLT_translation.h"
62
63 #include "RNA_access.h"
64
65 #include "BIF_gl.h"
66 #include "BIF_glutil.h"
67
68 #include "BIK_api.h"
69
70 #include "BKE_animsys.h"
71 #include "BKE_action.h"
72 #include "BKE_armature.h"
73 #include "BKE_curve.h"
74 #include "BKE_depsgraph.h"
75 #include "BKE_fcurve.h"
76 #include "BKE_lattice.h"
77 #include "BKE_library.h"
78 #include "BKE_nla.h"
79 #include "BKE_context.h"
80 #include "BKE_paint.h"
81 #include "BKE_sequencer.h"
82 #include "BKE_editmesh.h"
83 #include "BKE_tracking.h"
84 #include "BKE_mask.h"
85
86 #include "ED_anim_api.h"
87 #include "ED_armature.h"
88 #include "ED_image.h"
89 #include "ED_keyframing.h"
90 #include "ED_markers.h"
91 #include "ED_mesh.h"
92 #include "ED_object.h"
93 #include "ED_particle.h"
94 #include "ED_screen_types.h"
95 #include "ED_space_api.h"
96 #include "ED_uvedit.h"
97 #include "ED_view3d.h"
98 #include "ED_curve.h" /* for curve_editnurbs */
99 #include "ED_clip.h"
100 #include "ED_screen.h"
101
102 #include "WM_types.h"
103 #include "WM_api.h"
104
105 #include "UI_resources.h"
106 #include "UI_view2d.h"
107
108 #include "transform.h"
109
110 /* ************************** Functions *************************** */
111
112 void getViewVector(TransInfo *t, float coord[3], float vec[3])
113 {
114         if (t->persp != RV3D_ORTHO) {
115                 sub_v3_v3v3(vec, coord, t->viewinv[3]);
116         }
117         else {
118                 copy_v3_v3(vec, t->viewinv[2]);
119         }
120         normalize_v3(vec);
121 }
122
123 /* ************************** GENERICS **************************** */
124
125
126 static void clipMirrorModifier(TransInfo *t, Object *ob)
127 {
128         ModifierData *md = ob->modifiers.first;
129         float tolerance[3] = {0.0f, 0.0f, 0.0f};
130         int axis = 0;
131         
132         for (; md; md = md->next) {
133                 if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
134                         MirrorModifierData *mmd = (MirrorModifierData *) md;
135                         
136                         if (mmd->flag & MOD_MIR_CLIPPING) {
137                                 axis = 0;
138                                 if (mmd->flag & MOD_MIR_AXIS_X) {
139                                         axis |= 1;
140                                         tolerance[0] = mmd->tolerance;
141                                 }
142                                 if (mmd->flag & MOD_MIR_AXIS_Y) {
143                                         axis |= 2;
144                                         tolerance[1] = mmd->tolerance;
145                                 }
146                                 if (mmd->flag & MOD_MIR_AXIS_Z) {
147                                         axis |= 4;
148                                         tolerance[2] = mmd->tolerance;
149                                 }
150                                 if (axis) {
151                                         float mtx[4][4], imtx[4][4];
152                                         int i;
153                                         TransData *td = t->data;
154                                         
155                                         if (mmd->mirror_ob) {
156                                                 float obinv[4][4];
157                                                 
158                                                 invert_m4_m4(obinv, mmd->mirror_ob->obmat);
159                                                 mul_m4_m4m4(mtx, obinv, ob->obmat);
160                                                 invert_m4_m4(imtx, mtx);
161                                         }
162                                         
163                                         for (i = 0; i < t->total; i++, td++) {
164                                                 int clip;
165                                                 float loc[3], iloc[3];
166                                                 
167                                                 if (td->flag & TD_NOACTION)
168                                                         break;
169                                                 if (td->loc == NULL)
170                                                         break;
171                                                 
172                                                 if (td->flag & TD_SKIP)
173                                                         continue;
174                                                 
175                                                 copy_v3_v3(loc,  td->loc);
176                                                 copy_v3_v3(iloc, td->iloc);
177                                                 
178                                                 if (mmd->mirror_ob) {
179                                                         mul_m4_v3(mtx, loc);
180                                                         mul_m4_v3(mtx, iloc);
181                                                 }
182                                                 
183                                                 clip = 0;
184                                                 if (axis & 1) {
185                                                         if (fabsf(iloc[0]) <= tolerance[0] ||
186                                                             loc[0] * iloc[0] < 0.0f)
187                                                         {
188                                                                 loc[0] = 0.0f;
189                                                                 clip = 1;
190                                                         }
191                                                 }
192                                                 
193                                                 if (axis & 2) {
194                                                         if (fabsf(iloc[1]) <= tolerance[1] ||
195                                                             loc[1] * iloc[1] < 0.0f)
196                                                         {
197                                                                 loc[1] = 0.0f;
198                                                                 clip = 1;
199                                                         }
200                                                 }
201                                                 if (axis & 4) {
202                                                         if (fabsf(iloc[2]) <= tolerance[2] ||
203                                                             loc[2] * iloc[2] < 0.0f)
204                                                         {
205                                                                 loc[2] = 0.0f;
206                                                                 clip = 1;
207                                                         }
208                                                 }
209                                                 if (clip) {
210                                                         if (mmd->mirror_ob) {
211                                                                 mul_m4_v3(imtx, loc);
212                                                         }
213                                                         copy_v3_v3(td->loc, loc);
214                                                 }
215                                         }
216                                 }
217                                 
218                         }
219                 }
220         }
221 }
222
223 /* assumes obedit set to mesh object */
224 static void editbmesh_apply_to_mirror(TransInfo *t)
225 {
226         TransData *td = t->data;
227         BMVert *eve;
228         int i;
229         
230         for (i = 0; i < t->total; i++, td++) {
231                 if (td->flag & TD_NOACTION)
232                         break;
233                 if (td->loc == NULL)
234                         break;
235                 if (td->flag & TD_SKIP)
236                         continue;
237                 
238                 eve = td->extra;
239                 if (eve) {
240                         eve->co[0] = -td->loc[0];
241                         eve->co[1] = td->loc[1];
242                         eve->co[2] = td->loc[2];
243                 }
244                 
245                 if (td->flag & TD_MIRROR_EDGE) {
246                         td->loc[0] = 0;
247                 }
248         }
249 }
250
251 /* for the realtime animation recording feature, handle overlapping data */
252 static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer)
253 {
254         ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
255         
256         /* sanity checks */
257         if (ELEM(NULL, scene, id, sad))
258                 return;
259         
260         /* check if we need a new strip if:
261          *  - if animtimer is running
262          *      - we're not only keying for available channels
263          *      - the option to add new actions for each round is not enabled
264          */
265         if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL) == 0 && (scene->toolsettings->autokey_flag & ANIMRECORD_FLAG_WITHNLA)) {
266                 /* if playback has just looped around, we need to add a new NLA track+strip to allow a clean pass to occur */
267                 if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
268                         AnimData *adt = BKE_animdata_from_id(id);
269                         const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
270                         
271                         /* perform push-down manually with some differences 
272                          * NOTE: BKE_nla_action_pushdown() sync warning...
273                          */
274                         if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
275                                 float astart, aend;
276                                 
277                                 /* only push down if action is more than 1-2 frames long */
278                                 calc_action_range(adt->action, &astart, &aend, 1);
279                                 if (aend > astart + 2.0f) {
280                                         NlaStrip *strip = BKE_nlastack_add_strip(adt, adt->action);
281                                         
282                                         /* clear reference to action now that we've pushed it onto the stack */
283                                         id_us_min(&adt->action->id);
284                                         adt->action = NULL;
285                                         
286                                         /* adjust blending + extend so that they will behave correctly */
287                                         strip->extendmode = NLASTRIP_EXTEND_NOTHING;
288                                         strip->flag &= ~(NLASTRIP_FLAG_AUTO_BLENDS | NLASTRIP_FLAG_SELECT | NLASTRIP_FLAG_ACTIVE);
289                                         
290                                         /* copy current "action blending" settings from adt to the strip,
291                                          * as it was keyframed with these settings, so omitting them will
292                                          * change the effect  [T54766]
293                                          */
294                                         if (is_first == false) {
295                                                 strip->blendmode = adt->act_blendmode;
296                                                 strip->influence = adt->act_influence;
297                                                 
298                                                 if (adt->act_influence < 1.0f) {
299                                                         /* enable "user-controlled" influence (which will insert a default keyframe)
300                                                          * so that the influence doesn't get lost on the new update
301                                                          *
302                                                          * NOTE: An alternative way would have been to instead hack the influence
303                                                          * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
304                                                          * is disabled but auto-blending isn't being used. However, that approach
305                                                          * is a bit hacky/hard to discover, and may cause backwards compatability issues,
306                                                          * so it's better to just do it this way.
307                                                          */
308                                                         strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
309                                                         BKE_nlastrip_validate_fcurves(strip);
310                                                 }
311                                         }
312                                         
313                                         /* also, adjust the AnimData's action extend mode to be on 
314                                          * 'nothing' so that previous result still play 
315                                          */
316                                         adt->act_extendmode = NLASTRIP_EXTEND_NOTHING;
317                                 }
318                         }
319                 }
320         }
321 }
322
323 static bool fcu_test_selected(FCurve *fcu)
324 {
325         BezTriple *bezt = fcu->bezt;
326         unsigned int i;
327
328         if (bezt == NULL) /* ignore baked */
329                 return 0;
330
331         for (i = 0; i < fcu->totvert; i++, bezt++) {
332                 if (BEZT_ISSEL_ANY(bezt)) return 1;
333         }
334
335         return 0;
336 }
337
338 /* helper for recalcData() - for Action Editor transforms */
339 static void recalcData_actedit(TransInfo *t)
340 {
341         Scene *scene = t->scene;
342         SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
343         
344         bAnimContext ac = {NULL};
345         ListBase anim_data = {NULL, NULL};
346         bAnimListElem *ale;
347         int filter;
348         
349         /* initialize relevant anim-context 'context' data from TransInfo data */
350         /* NOTE: sync this with the code in ANIM_animdata_get_context() */
351         ac.scene = t->scene;
352         ac.obact = OBACT;
353         ac.sa = t->sa;
354         ac.ar = t->ar;
355         ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
356         ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
357         ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
358         
359         ANIM_animdata_context_getdata(&ac);
360         
361         /* perform flush */
362         if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
363                 /* flush transform values back to actual coordinates */
364                 flushTransIntFrameActionData(t);
365         }
366         else {
367                 /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
368                 filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA);
369                 ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
370                 
371                 /* just tag these animdata-blocks to recalc, assuming that some data there changed 
372                  * BUT only do this if realtime updates are enabled
373                  */
374                 if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) {
375                         for (ale = anim_data.first; ale; ale = ale->next) {
376                                 /* set refresh tags for objects using this animation */
377                                 ANIM_list_elem_update(t->scene, ale);
378                         }
379                 }
380                 
381                 /* now free temp channels */
382                 ANIM_animdata_freelist(&anim_data);
383         }
384 }
385 /* helper for recalcData() - for Graph Editor transforms */
386 static void recalcData_graphedit(TransInfo *t)
387 {
388         SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
389         Scene *scene;
390         
391         ListBase anim_data = {NULL, NULL};
392         bAnimContext ac = {NULL};
393         int filter;
394         
395         bAnimListElem *ale;
396         int dosort = 0;
397
398         /* initialize relevant anim-context 'context' data from TransInfo data */
399         /* NOTE: sync this with the code in ANIM_animdata_get_context() */
400         scene = ac.scene = t->scene;
401         ac.obact = OBACT;
402         ac.sa = t->sa;
403         ac.ar = t->ar;
404         ac.sl = (t->sa) ? t->sa->spacedata.first : NULL;
405         ac.spacetype = (t->sa) ? t->sa->spacetype : 0;
406         ac.regiontype = (t->ar) ? t->ar->regiontype : 0;
407         
408         ANIM_animdata_context_getdata(&ac);
409         
410         /* do the flush first */
411         flushTransGraphData(t);
412         
413         /* get curves to check if a re-sort is needed */
414         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE);
415         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
416         
417         /* now test if there is a need to re-sort */
418         for (ale = anim_data.first; ale; ale = ale->next) {
419                 FCurve *fcu = (FCurve *)ale->key_data;
420                 
421                 /* ignore FC-Curves without any selected verts */
422                 if (!fcu_test_selected(fcu))
423                         continue;
424
425                 /* watch it: if the time is wrong: do not correct handles yet */
426                 if (test_time_fcurve(fcu))
427                         dosort++;
428                 else
429                         calchandles_fcurve(fcu);
430                 
431                 /* set refresh tags for objects using this animation,
432                  * BUT only if realtime updates are enabled  
433                  */
434                 if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0)
435                         ANIM_list_elem_update(t->scene, ale);
436         }
437         
438         /* do resort and other updates? */
439         if (dosort) remake_graph_transdata(t, &anim_data);
440         
441         /* now free temp channels */
442         ANIM_animdata_freelist(&anim_data);
443 }
444
445 /* helper for recalcData() - for NLA Editor transforms */
446 static void recalcData_nla(TransInfo *t)
447 {
448         TransDataNla *tdn = t->custom.type.data;
449         SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
450         Scene *scene = t->scene;
451         double secf = FPS;
452         int i;
453         
454         /* for each strip we've got, perform some additional validation of the values that got set before
455          * using RNA to set the value (which does some special operations when setting these values to make
456          * sure that everything works ok)
457          */
458         for (i = 0; i < t->total; i++, tdn++) {
459                 NlaStrip *strip = tdn->strip;
460                 PointerRNA strip_ptr;
461                 short pExceeded, nExceeded, iter;
462                 int delta_y1, delta_y2;
463                 
464                 /* if this tdn has no handles, that means it is just a dummy that should be skipped */
465                 if (tdn->handle == 0)
466                         continue;
467                 
468                 /* set refresh tags for objects using this animation,
469                  * BUT only if realtime updates are enabled  
470                  */
471                 if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0)
472                         ANIM_id_update(t->scene, tdn->id);
473                 
474                 /* if canceling transform, just write the values without validating, then move on */
475                 if (t->state == TRANS_CANCEL) {
476                         /* clear the values by directly overwriting the originals, but also need to restore
477                          * endpoints of neighboring transition-strips
478                          */
479                         
480                         /* start */
481                         strip->start = tdn->h1[0];
482                         
483                         if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
484                                 strip->prev->end = tdn->h1[0];
485                         
486                         /* end */
487                         strip->end = tdn->h2[0];
488                         
489                         if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION))
490                                 strip->next->start = tdn->h2[0];
491                         
492                         /* flush transforms to child strips (since this should be a meta) */
493                         BKE_nlameta_flush_transforms(strip);
494                         
495                         /* restore to original track (if needed) */
496                         if (tdn->oldTrack != tdn->nlt) {
497                                 /* just append to end of list for now, since strips get sorted in special_aftertrans_update() */
498                                 BLI_remlink(&tdn->nlt->strips, strip);
499                                 BLI_addtail(&tdn->oldTrack->strips, strip);
500                         }
501                         
502                         continue;
503                 }
504                 
505                 /* firstly, check if the proposed transform locations would overlap with any neighboring strips
506                  * (barring transitions) which are absolute barriers since they are not being moved
507                  *
508                  * this is done as a iterative procedure (done 5 times max for now)
509                  */
510                 for (iter = 0; iter < 5; iter++) {
511                         pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h1[0] < strip->prev->end));
512                         nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && (tdn->h2[0] > strip->next->start));
513                         
514                         if ((pExceeded && nExceeded) || (iter == 4)) {
515                                 /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise)
516                                  *      - simply crop strip to fit within the bounds of the strips bounding it
517                                  *      - if there were no neighbors, clear the transforms (make it default to the strip's current values)
518                                  */
519                                 if (strip->prev && strip->next) {
520                                         tdn->h1[0] = strip->prev->end;
521                                         tdn->h2[0] = strip->next->start;
522                                 }
523                                 else {
524                                         tdn->h1[0] = strip->start;
525                                         tdn->h2[0] = strip->end;
526                                 }
527                         }
528                         else if (nExceeded) {
529                                 /* move backwards */
530                                 float offset = tdn->h2[0] - strip->next->start;
531                                 
532                                 tdn->h1[0] -= offset;
533                                 tdn->h2[0] -= offset;
534                         }
535                         else if (pExceeded) {
536                                 /* more forwards */
537                                 float offset = strip->prev->end - tdn->h1[0];
538                                 
539                                 tdn->h1[0] += offset;
540                                 tdn->h2[0] += offset;
541                         }
542                         else /* all is fine and well */
543                                 break;
544                 }
545                 
546                 /* handle auto-snapping
547                  * NOTE: only do this when transform is still running, or we can't restore
548                  */
549                 if (t->state != TRANS_CANCEL) {
550                         switch (snla->autosnap) {
551                                 case SACTSNAP_FRAME: /* snap to nearest frame */
552                                 case SACTSNAP_STEP: /* frame step - this is basically the same, since we don't have any remapping going on */
553                                 {
554                                         tdn->h1[0] = floorf(tdn->h1[0] + 0.5f);
555                                         tdn->h2[0] = floorf(tdn->h2[0] + 0.5f);
556                                         break;
557                                 }
558                                 
559                                 case SACTSNAP_SECOND: /* snap to nearest second */
560                                 case SACTSNAP_TSTEP: /* second step - this is basically the same, since we don't have any remapping going on */
561                                 {
562                                         /* This case behaves differently from the rest, since lengths of strips
563                                          * may not be multiples of a second. If we just naively resize adjust
564                                          * the handles, things may not work correctly. Instead, we only snap
565                                          * the first handle, and move the other to fit.
566                                          *
567                                          * FIXME: we do run into problems here when user attempts to negatively
568                                          *        scale the strip, as it then just compresses down and refuses
569                                          *        to expand out the other end.
570                                          */
571                                         float h1_new = (float)(floor(((double)tdn->h1[0] / secf) + 0.5) * secf);
572                                         float delta  = h1_new - tdn->h1[0];
573                                         
574                                         tdn->h1[0] = h1_new;
575                                         tdn->h2[0] += delta;
576                                         break;
577                                 }
578                                 
579                                 case SACTSNAP_MARKER: /* snap to nearest marker */
580                                 {
581                                         tdn->h1[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h1[0]);
582                                         tdn->h2[0] = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, tdn->h2[0]);
583                                         break;
584                                 }
585                         }
586                 }
587                 
588                 /* Use RNA to write the values to ensure that constraints on these are obeyed
589                  * (e.g. for transition strips, the values are taken from the neighbors)
590                  * 
591                  * NOTE: we write these twice to avoid truncation errors which can arise when
592                  * moving the strips a large distance using numeric input [#33852] 
593                  */
594                 RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
595                 
596                 RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
597                 RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
598                 
599                 RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
600                 RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
601                 
602                 /* flush transforms to child strips (since this should be a meta) */
603                 BKE_nlameta_flush_transforms(strip);
604                 
605                 
606                 /* now, check if we need to try and move track
607                  *      - we need to calculate both, as only one may have been altered by transform if only 1 handle moved
608                  */
609                 delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
610                 delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
611                 
612                 if (delta_y1 || delta_y2) {
613                         NlaTrack *track;
614                         int delta = (delta_y2) ? delta_y2 : delta_y1;
615                         int n;
616                         
617                         /* move in the requested direction, checking at each layer if there's space for strip to pass through,
618                          * stopping on the last track available or that we're able to fit in
619                          */
620                         if (delta > 0) {
621                                 for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
622                                         /* check if space in this track for the strip */
623                                         if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
624                                                 /* move strip to this track */
625                                                 BLI_remlink(&tdn->nlt->strips, strip);
626                                                 BKE_nlatrack_add_strip(track, strip);
627                                                 
628                                                 tdn->nlt = track;
629                                                 tdn->trackIndex++;
630                                         }
631                                         else /* can't move any further */
632                                                 break;
633                                 }
634                         }
635                         else {
636                                 /* make delta 'positive' before using it, since we now know to go backwards */
637                                 delta = -delta;
638                                 
639                                 for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
640                                         /* check if space in this track for the strip */
641                                         if (BKE_nlatrack_has_space(track, strip->start, strip->end)) {
642                                                 /* move strip to this track */
643                                                 BLI_remlink(&tdn->nlt->strips, strip);
644                                                 BKE_nlatrack_add_strip(track, strip);
645                                                 
646                                                 tdn->nlt = track;
647                                                 tdn->trackIndex--;
648                                         }
649                                         else /* can't move any further */
650                                                 break;
651                                 }
652                         }
653                 }
654         }
655 }
656
657 static void recalcData_mask_common(TransInfo *t)
658 {
659         Mask *mask = CTX_data_edit_mask(t->context);
660
661         flushTransMasking(t);
662
663         DAG_id_tag_update(&mask->id, 0);
664 }
665
666 /* helper for recalcData() - for Image Editor transforms */
667 static void recalcData_image(TransInfo *t)
668 {
669         if (t->options & CTX_MASK) {
670                 recalcData_mask_common(t);
671         }
672         else if (t->options & CTX_PAINT_CURVE) {
673                 flushTransPaintCurve(t);
674         }
675         else if (t->obedit && t->obedit->type == OB_MESH) {
676                 SpaceImage *sima = t->sa->spacedata.first;
677                 
678                 flushTransUVs(t);
679                 if (sima->flag & SI_LIVE_UNWRAP)
680                         ED_uvedit_live_unwrap_re_solve();
681                 
682                 DAG_id_tag_update(t->obedit->data, 0);
683         }
684 }
685
686 /* helper for recalcData() - for Movie Clip transforms */
687 static void recalcData_spaceclip(TransInfo *t)
688 {
689         SpaceClip *sc = t->sa->spacedata.first;
690
691         if (ED_space_clip_check_show_trackedit(sc)) {
692                 MovieClip *clip = ED_space_clip_get_clip(sc);
693                 ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
694                 MovieTrackingTrack *track;
695                 int framenr = ED_space_clip_get_clip_frame_number(sc);
696
697                 flushTransTracking(t);
698
699                 track = tracksbase->first;
700                 while (track) {
701                         if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) {
702                                 MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
703
704                                 if (t->mode == TFM_TRANSLATION) {
705                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
706                                                 BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
707                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
708                                                 BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_POS);
709                                 }
710                                 else if (t->mode == TFM_RESIZE) {
711                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
712                                                 BKE_tracking_marker_clamp(marker, CLAMP_PAT_DIM);
713                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_SEARCH))
714                                                 BKE_tracking_marker_clamp(marker, CLAMP_SEARCH_DIM);
715                                 }
716                                 else if (t->mode == TFM_ROTATION) {
717                                         if (TRACK_AREA_SELECTED(track, TRACK_AREA_PAT))
718                                                 BKE_tracking_marker_clamp(marker, CLAMP_PAT_POS);
719                                 }
720                         }
721
722                         track = track->next;
723                 }
724
725                 DAG_id_tag_update(&clip->id, 0);
726         }
727         else if (t->options & CTX_MASK) {
728                 recalcData_mask_common(t);
729         }
730 }
731
732 /* helper for recalcData() - for object transforms, typically in the 3D view */
733 static void recalcData_objects(TransInfo *t)
734 {
735         Base *base = t->scene->basact;
736
737         if (t->obedit) {
738                 if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
739                         Curve *cu = t->obedit->data;
740                         ListBase *nurbs = BKE_curve_editNurbs_get(cu);
741                         Nurb *nu = nurbs->first;
742                         
743                         if (t->state != TRANS_CANCEL) {
744                                 clipMirrorModifier(t, t->obedit);
745                                 applyProject(t);
746                         }
747                         
748                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
749                                 
750                         if (t->state == TRANS_CANCEL) {
751                                 while (nu) {
752                                         BKE_nurb_handles_calc(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
753                                         nu = nu->next;
754                                 }
755                         }
756                         else {
757                                 /* Normal updating */
758                                 while (nu) {
759                                         BKE_nurb_test2D(nu);
760                                         BKE_nurb_handles_calc(nu);
761                                         nu = nu->next;
762                                 }
763                         }
764                 }
765                 else if (t->obedit->type == OB_LATTICE) {
766                         Lattice *la = t->obedit->data;
767                         
768                         if (t->state != TRANS_CANCEL) {
769                                 applyProject(t);
770                         }
771                         
772                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
773                         
774                         if (la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt);
775                 }
776                 else if (t->obedit->type == OB_MESH) {
777                         BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
778                         /* mirror modifier clipping? */
779                         if (t->state != TRANS_CANCEL) {
780                                 /* apply clipping after so we never project past the clip plane [#25423] */
781                                 applyProject(t);
782                                 clipMirrorModifier(t, t->obedit);
783                         }
784                         if ((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
785                                 editbmesh_apply_to_mirror(t);
786
787                         if (t->mode == TFM_EDGE_SLIDE) {
788                                 projectEdgeSlideData(t, false);
789                         }
790                         else if (t->mode == TFM_VERT_SLIDE) {
791                                 projectVertSlideData(t, false);
792                         }
793
794                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
795                         
796                         EDBM_mesh_normals_update(em);
797                         BKE_editmesh_tessface_calc(em);
798                 }
799                 else if (t->obedit->type == OB_ARMATURE) { /* no recalc flag, does pose */
800                         bArmature *arm = t->obedit->data;
801                         ListBase *edbo = arm->edbo;
802                         EditBone *ebo, *ebo_parent;
803                         TransData *td = t->data;
804                         int i;
805                         
806                         if (t->state != TRANS_CANCEL) {
807                                 applyProject(t);
808                         }
809                         
810                         /* Ensure all bones are correctly adjusted */
811                         for (ebo = edbo->first; ebo; ebo = ebo->next) {
812                                 ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
813                                 
814                                 if (ebo_parent) {
815                                         /* If this bone has a parent tip that has been moved */
816                                         if (ebo_parent->flag & BONE_TIPSEL) {
817                                                 copy_v3_v3(ebo->head, ebo_parent->tail);
818                                                 if (t->mode == TFM_BONE_ENVELOPE) ebo->rad_head = ebo_parent->rad_tail;
819                                         }
820                                         /* If this bone has a parent tip that has NOT been moved */
821                                         else {
822                                                 copy_v3_v3(ebo_parent->tail, ebo->head);
823                                                 if (t->mode == TFM_BONE_ENVELOPE) ebo_parent->rad_tail = ebo->rad_head;
824                                         }
825                                 }
826                                 
827                                 /* on extrude bones, oldlength==0.0f, so we scale radius of points */
828                                 ebo->length = len_v3v3(ebo->head, ebo->tail);
829                                 if (ebo->oldlength == 0.0f) {
830                                         ebo->rad_head = 0.25f * ebo->length;
831                                         ebo->rad_tail = 0.10f * ebo->length;
832                                         ebo->dist = 0.25f * ebo->length;
833                                         if (ebo->parent) {
834                                                 if (ebo->rad_head > ebo->parent->rad_tail)
835                                                         ebo->rad_head = ebo->parent->rad_tail;
836                                         }
837                                 }
838                                 else if (t->mode != TFM_BONE_ENVELOPE) {
839                                         /* if bones change length, lets do that for the deform distance as well */
840                                         ebo->dist *= ebo->length / ebo->oldlength;
841                                         ebo->rad_head *= ebo->length / ebo->oldlength;
842                                         ebo->rad_tail *= ebo->length / ebo->oldlength;
843                                         ebo->oldlength = ebo->length;
844
845                                         if (ebo_parent) {
846                                                 ebo_parent->rad_tail = ebo->rad_head;
847                                         }
848                                 }
849                         }
850                         
851                         if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
852                                 /* fix roll */
853                                 for (i = 0; i < t->total; i++, td++) {
854                                         if (td->extra) {
855                                                 float vec[3], up_axis[3];
856                                                 float qrot[4];
857                                                 float roll;
858                                                 
859                                                 ebo = td->extra;
860
861                                                 if (t->state == TRANS_CANCEL) {
862                                                         /* restore roll */
863                                                         ebo->roll = td->ival;
864                                                 }
865                                                 else {
866                                                         copy_v3_v3(up_axis, td->axismtx[2]);
867
868                                                         sub_v3_v3v3(vec, ebo->tail, ebo->head);
869                                                         normalize_v3(vec);
870                                                         rotation_between_vecs_to_quat(qrot, td->axismtx[1], vec);
871                                                         mul_qt_v3(qrot, up_axis);
872
873                                                         /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */
874                                                         roll = ED_armature_ebone_roll_to_vector(ebo, up_axis, false);
875                                                         ebo->roll = angle_compat_rad(roll, td->ival);
876                                                 }
877                                         }
878                                 }
879                         }
880                         
881                         if (arm->flag & ARM_MIRROR_EDIT) {
882                                 if (t->state != TRANS_CANCEL)
883                                         ED_armature_edit_transform_mirror_update(t->obedit);
884                                 else
885                                         restoreBones(t);
886                         }
887                 }
888                 else {
889                         if (t->state != TRANS_CANCEL) {
890                                 applyProject(t);
891                         }
892                         DAG_id_tag_update(t->obedit->data, 0);  /* sets recalc flags */
893                 }
894         }
895         else if ((t->flag & T_POSE) && t->poseobj) {
896                 Object *ob = t->poseobj;
897                 bArmature *arm = ob->data;
898                 
899                 /* if animtimer is running, and the object already has animation data,
900                  * check if the auto-record feature means that we should record 'samples'
901                  * (i.e. uneditable animation values)
902                  *
903                  * context is needed for keying set poll() functions.
904                  */
905                 // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
906                 if ((t->animtimer) && (t->context) && IS_AUTOKEY_ON(t->scene)) {
907                         int targetless_ik = (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
908                         
909                         animrecord_check_state(t->scene, &ob->id, t->animtimer);
910                         autokeyframe_pose_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
911                 }
912                 
913                 /* old optimize trick... this enforces to bypass the depgraph */
914                 if (!(arm->flag & ARM_DELAYDEFORM)) {
915                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
916                         /* transformation of pose may affect IK tree, make sure it is rebuilt */
917                         BIK_clear_data(ob->pose);
918                 }
919                 else
920                         BKE_pose_where_is(t->scene, ob);
921         }
922         else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) {
923                 if (t->state != TRANS_CANCEL) {
924                         applyProject(t);
925                 }
926                 flushTransParticles(t);
927         }
928         else {
929                 int i;
930                 
931                 if (t->state != TRANS_CANCEL) {
932                         applyProject(t);
933                 }
934                 
935                 for (i = 0; i < t->total; i++) {
936                         TransData *td = t->data + i;
937                         Object *ob = td->ob;
938                         
939                         if (td->flag & TD_NOACTION)
940                                 break;
941                         
942                         if (td->flag & TD_SKIP)
943                                 continue;
944                         
945                         /* if animtimer is running, and the object already has animation data,
946                          * check if the auto-record feature means that we should record 'samples'
947                          * (i.e. uneditable animation values)
948                          */
949                         // TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
950                         if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
951                                 animrecord_check_state(t->scene, &ob->id, t->animtimer);
952                                 autokeyframe_ob_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode);
953                         }
954                         
955                         /* sets recalc flags fully, instead of flushing existing ones 
956                          * otherwise proxies don't function correctly
957                          */
958                         DAG_id_tag_update(&ob->id, OB_RECALC_OB);
959
960                         if (t->flag & T_TEXTURE)
961                                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
962                 }
963         }
964 }
965
966 /* helper for recalcData() - for sequencer transforms */
967 static void recalcData_sequencer(TransInfo *t)
968 {
969         TransData *td;
970         int a;
971         Sequence *seq_prev = NULL;
972
973         for (a = 0, td = t->data; a < t->total; a++, td++) {
974                 TransDataSeq *tdsq = (TransDataSeq *) td->extra;
975                 Sequence *seq = tdsq->seq;
976
977                 if (seq != seq_prev) {
978                         if (BKE_sequence_tx_fullupdate_test(seq)) {
979                                 /* A few effect strip types need a complete recache on transform. */
980                                 BKE_sequence_invalidate_cache(t->scene, seq);
981                         }
982                         else {
983                                 BKE_sequence_invalidate_dependent(t->scene, seq);
984                         }
985                 }
986
987                 seq_prev = seq;
988         }
989
990         BKE_sequencer_preprocessed_cache_cleanup();
991
992         flushTransSeq(t);
993 }
994
995 /* force recalculation of triangles during transformation */
996 static void recalcData_gpencil_strokes(TransInfo *t)
997 {
998         TransData *td = t->data;
999         for (int i = 0; i < t->total; i++, td++) {
1000                 bGPDstroke *gps = td->extra;
1001                 if (gps != NULL) {
1002                         gps->flag |= GP_STROKE_RECALC_CACHES;
1003                 }
1004         }
1005 }
1006
1007 /* called for updating while transform acts, once per redraw */
1008 void recalcData(TransInfo *t)
1009 {
1010         /* if tests must match createTransData for correct updates */
1011         if (t->options & CTX_TEXTURE) {
1012                 recalcData_objects(t);
1013         }
1014         else if (t->options & CTX_EDGE) {
1015                 recalcData_objects(t);
1016         }
1017         else if (t->options & CTX_PAINT_CURVE) {
1018                 flushTransPaintCurve(t);
1019         }
1020         else if (t->options & CTX_GPENCIL_STROKES) {
1021                 /* set recalc triangle cache flag */
1022                 recalcData_gpencil_strokes(t);
1023         }
1024         else if (t->spacetype == SPACE_IMAGE) {
1025                 recalcData_image(t);
1026         }
1027         else if (t->spacetype == SPACE_ACTION) {
1028                 recalcData_actedit(t);
1029         }
1030         else if (t->spacetype == SPACE_NLA) {
1031                 recalcData_nla(t);
1032         }
1033         else if (t->spacetype == SPACE_SEQ) {
1034                 recalcData_sequencer(t);
1035         }
1036         else if (t->spacetype == SPACE_IPO) {
1037                 recalcData_graphedit(t);
1038         }
1039         else if (t->spacetype == SPACE_NODE) {
1040                 flushTransNodes(t);
1041         }
1042         else if (t->spacetype == SPACE_CLIP) {
1043                 recalcData_spaceclip(t);
1044         }
1045         else {
1046                 recalcData_objects(t);
1047         }
1048 }
1049
1050 void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options)
1051 {
1052         float v1[3], v2[3], v3[3];
1053         unsigned char col[3], col2[3];
1054
1055         if (t->spacetype == SPACE_VIEW3D) {
1056                 View3D *v3d = t->view;
1057                 
1058                 glPushMatrix();
1059                 
1060                 //if (t->obedit) glLoadMatrixf(t->obedit->obmat);       // sets opengl viewing
1061                 
1062                 
1063                 copy_v3_v3(v3, dir);
1064                 mul_v3_fl(v3, v3d->far);
1065                 
1066                 sub_v3_v3v3(v2, center, v3);
1067                 add_v3_v3v3(v1, center, v3);
1068                 
1069                 if (options & DRAWLIGHT) {
1070                         col[0] = col[1] = col[2] = 220;
1071                 }
1072                 else {
1073                         UI_GetThemeColor3ubv(TH_GRID, col);
1074                 }
1075                 UI_make_axis_color(col, col2, axis);
1076                 glColor3ubv(col2);
1077                 
1078                 setlinestyle(0);
1079                 glBegin(GL_LINES);
1080                 glVertex3fv(v1);
1081                 glVertex3fv(v2);
1082                 glEnd();
1083                 
1084                 glPopMatrix();
1085         }
1086 }
1087
1088 /**
1089  * Free data before switching to another mode.
1090  */
1091 void resetTransModal(TransInfo *t)
1092 {
1093         if (t->mode == TFM_EDGE_SLIDE) {
1094                 freeEdgeSlideVerts(t, &t->custom.mode);
1095         }
1096         else if (t->mode == TFM_VERT_SLIDE) {
1097                 freeVertSlideVerts(t, &t->custom.mode);
1098         }
1099 }
1100
1101 void resetTransRestrictions(TransInfo *t)
1102 {
1103         t->flag &= ~T_ALL_RESTRICTIONS;
1104 }
1105
1106 static int initTransInfo_edit_pet_to_flag(const int proportional)
1107 {
1108         switch (proportional) {
1109                 case PROP_EDIT_ON:
1110                         return T_PROP_EDIT;
1111                 case PROP_EDIT_CONNECTED:
1112                         return T_PROP_EDIT | T_PROP_CONNECTED;
1113                 case PROP_EDIT_PROJECTED:
1114                         return T_PROP_EDIT | T_PROP_PROJECTED;
1115                 default:
1116                         return 0;
1117         }
1118 }
1119
1120 /**
1121  * Setup internal data, mouse, vectors
1122  *
1123  * \note \a op and \a event can be NULL
1124  *
1125  * \see #saveTransform does the reverse.
1126  */
1127 void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event)
1128 {
1129         Scene *sce = CTX_data_scene(C);
1130         ToolSettings *ts = CTX_data_tool_settings(C);
1131         ARegion *ar = CTX_wm_region(C);
1132         ScrArea *sa = CTX_wm_area(C);
1133         Object *obedit = CTX_data_edit_object(C);
1134         Object *ob = CTX_data_active_object(C);
1135         bGPdata *gpd = CTX_data_gpencil_data(C);
1136         PropertyRNA *prop;
1137         
1138         t->scene = sce;
1139         t->sa = sa;
1140         t->ar = ar;
1141         t->obedit = obedit;
1142         t->settings = ts;
1143         t->reports = op ? op->reports : NULL;
1144
1145         if (obedit) {
1146                 copy_m3_m4(t->obedit_mat, obedit->obmat);
1147                 normalize_m3(t->obedit_mat);
1148         }
1149
1150         t->data = NULL;
1151         t->ext = NULL;
1152         
1153         t->helpline = HLP_NONE;
1154         
1155         t->flag = 0;
1156         
1157         t->redraw = TREDRAW_HARD;  /* redraw first time */
1158         
1159         if (event) {
1160                 t->mouse.imval[0] = event->mval[0];
1161                 t->mouse.imval[1] = event->mval[1];
1162         }
1163         else {
1164                 t->mouse.imval[0] = 0;
1165                 t->mouse.imval[1] = 0;
1166         }
1167         
1168         t->con.imval[0] = t->mouse.imval[0];
1169         t->con.imval[1] = t->mouse.imval[1];
1170         
1171         t->mval[0] = t->mouse.imval[0];
1172         t->mval[1] = t->mouse.imval[1];
1173         
1174         t->transform        = NULL;
1175         t->handleEvent      = NULL;
1176         
1177         t->total            = 0;
1178         
1179         t->val = 0.0f;
1180
1181         zero_v3(t->vec);
1182         zero_v3(t->center);
1183         zero_v3(t->center_global);
1184
1185         unit_m3(t->mat);
1186         
1187         /* if there's an event, we're modal */
1188         if (event) {
1189                 t->flag |= T_MODAL;
1190         }
1191
1192         /* Crease needs edge flag */
1193         if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) {
1194                 t->options |= CTX_EDGE;
1195         }
1196
1197         t->remove_on_cancel = false;
1198
1199         if (op && (prop = RNA_struct_find_property(op->ptr, "remove_on_cancel")) && RNA_property_is_set(op->ptr, prop)) {
1200                 if (RNA_property_boolean_get(op->ptr, prop)) {
1201                         t->remove_on_cancel = true;
1202                 }
1203         }
1204         
1205         /* GPencil editing context */
1206         if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) {
1207                 t->options |= CTX_GPENCIL_STROKES;
1208         }
1209
1210         /* Assign the space type, some exceptions for running in different mode */
1211         if (sa == NULL) {
1212                 /* background mode */
1213                 t->spacetype = SPACE_EMPTY;
1214         }
1215         else if ((ar == NULL) && (sa->spacetype == SPACE_VIEW3D)) {
1216                 /* running in the text editor */
1217                 t->spacetype = SPACE_EMPTY;
1218         }
1219         else {
1220                 /* normal operation */
1221                 t->spacetype = sa->spacetype;
1222         }
1223
1224         /* handle T_ALT_TRANSFORM initialization, we may use for different operators */
1225         if (op) {
1226                 const char *prop_id = NULL;
1227                 if (t->mode == TFM_SHRINKFATTEN) {
1228                         prop_id = "use_even_offset";
1229                 }
1230
1231                 if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id)) &&
1232                     RNA_property_is_set(op->ptr, prop))
1233                 {
1234                         SET_FLAG_FROM_TEST(t->flag, RNA_property_boolean_get(op->ptr, prop), T_ALT_TRANSFORM);
1235                 }
1236         }
1237
1238         if (t->spacetype == SPACE_VIEW3D) {
1239                 View3D *v3d = sa->spacedata.first;
1240                 bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
1241                 
1242                 t->view = v3d;
1243                 t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
1244                 
1245                 /* turn manipulator off during transform */
1246                 // FIXME: but don't do this when USING the manipulator...
1247                 if (t->flag & T_MODAL) {
1248                         t->twtype = v3d->twtype;
1249                         v3d->twtype = 0;
1250                 }
1251
1252                 if (v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
1253                 t->around = v3d->around;
1254                 
1255                 /* bend always uses the cursor */
1256                 if (t->mode == TFM_BEND) {
1257                         t->around = V3D_AROUND_CURSOR;
1258                 }
1259
1260                 t->current_orientation = v3d->twmode;
1261
1262                 /* exceptional case */
1263                 if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
1264                         if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) {
1265                                 const bool use_island = transdata_check_local_islands(t, t->around);
1266
1267                                 if (obedit && !use_island) {
1268                                         t->options |= CTX_NO_PET;
1269                                 }
1270                         }
1271                 }
1272
1273                 if (ob && ob->mode & OB_MODE_ALL_PAINT) {
1274                         Paint *p = BKE_paint_get_active_from_context(C);
1275                         if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
1276                                 t->options |= CTX_PAINT_CURVE;
1277                         }
1278                 }
1279
1280                 /* initialize UV transform from */
1281                 if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) {
1282                         if (RNA_property_is_set(op->ptr, prop)) {
1283                                 if (RNA_property_boolean_get(op->ptr, prop)) {
1284                                         t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT;
1285                                 }
1286                                 else {
1287                                         t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT;
1288                                 }
1289                         }
1290                         else {
1291                                 RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0);
1292                         }
1293                 }
1294
1295         }
1296         else if (t->spacetype == SPACE_IMAGE) {
1297                 SpaceImage *sima = sa->spacedata.first;
1298                 // XXX for now, get View2D from the active region
1299                 t->view = &ar->v2d;
1300                 t->around = sima->around;
1301
1302                 if (ED_space_image_show_uvedit(sima, t->obedit)) {
1303                         /* UV transform */
1304                 }
1305                 else if (sima->mode == SI_MODE_MASK) {
1306                         t->options |= CTX_MASK;
1307                 }
1308                 else if (sima->mode == SI_MODE_PAINT) {
1309                         Paint *p = &sce->toolsettings->imapaint.paint;
1310                         if (p->brush && (p->brush->flag & BRUSH_CURVE)) {
1311                                 t->options |= CTX_PAINT_CURVE;
1312                         }
1313                 }
1314                 /* image not in uv edit, nor in mask mode, can happen for some tools */
1315         }
1316         else if (t->spacetype == SPACE_NODE) {
1317                 // XXX for now, get View2D from the active region
1318                 t->view = &ar->v2d;
1319                 t->around = V3D_AROUND_CENTER_BOUNDS;
1320         }
1321         else if (t->spacetype == SPACE_IPO) {
1322                 SpaceIpo *sipo = sa->spacedata.first;
1323                 t->view = &ar->v2d;
1324                 t->around = sipo->around;
1325         }
1326         else if (t->spacetype == SPACE_CLIP) {
1327                 SpaceClip *sclip = sa->spacedata.first;
1328                 t->view = &ar->v2d;
1329                 t->around = sclip->around;
1330
1331                 if (ED_space_clip_check_show_trackedit(sclip))
1332                         t->options |= CTX_MOVIECLIP;
1333                 else if (ED_space_clip_check_show_maskedit(sclip))
1334                         t->options |= CTX_MASK;
1335         }
1336         else {
1337                 if (ar) {
1338                         // XXX for now, get View2D  from the active region
1339                         t->view = &ar->v2d;
1340                         // XXX for now, the center point is the midpoint of the data
1341                 }
1342                 else {
1343                         t->view = NULL;
1344                 }
1345                 t->around = V3D_AROUND_CENTER_BOUNDS;
1346         }
1347
1348         if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
1349                    RNA_property_is_set(op->ptr, prop)))
1350         {
1351                 t->current_orientation = RNA_property_enum_get(op->ptr, prop);
1352
1353                 if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) {
1354                         t->current_orientation = V3D_MANIP_GLOBAL;
1355                 }
1356         }
1357
1358         if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) &&
1359                    RNA_property_is_set(op->ptr, prop)))
1360         {
1361                 if (RNA_property_boolean_get(op->ptr, prop)) {
1362                         t->flag |= T_RELEASE_CONFIRM;
1363                 }
1364         }
1365         else {
1366                 if (U.flag & USER_RELEASECONFIRM) {
1367                         t->flag |= T_RELEASE_CONFIRM;
1368                 }
1369         }
1370
1371         if (op && ((prop = RNA_struct_find_property(op->ptr, "mirror")) &&
1372                    RNA_property_is_set(op->ptr, prop)))
1373         {
1374                 if (RNA_property_boolean_get(op->ptr, prop)) {
1375                         t->flag |= T_MIRROR;
1376                         t->mirror = 1;
1377                 }
1378         }
1379         // Need stuff to take it from edit mesh or whatnot here
1380         else if (t->spacetype == SPACE_VIEW3D) {
1381                 if (t->obedit && t->obedit->type == OB_MESH && (((Mesh *)t->obedit->data)->editflag & ME_EDIT_MIRROR_X)) {
1382                         t->flag |= T_MIRROR;
1383                         t->mirror = 1;
1384                 }
1385         }
1386         
1387         /* setting PET flag only if property exist in operator. Otherwise, assume it's not supported */
1388         if (op && (prop = RNA_struct_find_property(op->ptr, "proportional"))) {
1389                 if (RNA_property_is_set(op->ptr, prop)) {
1390                         t->flag |= initTransInfo_edit_pet_to_flag(RNA_property_enum_get(op->ptr, prop));
1391                 }
1392                 else {
1393                         /* use settings from scene only if modal */
1394                         if (t->flag & T_MODAL) {
1395                                 if ((t->options & CTX_NO_PET) == 0) {
1396                                         if (t->spacetype == SPACE_IPO) {
1397                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_fcurve);
1398                                         }
1399                                         else if (t->spacetype == SPACE_ACTION) {
1400                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
1401                                         }
1402                                         else if (t->obedit) {
1403                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
1404                                         }
1405                                         else if (t->options & CTX_GPENCIL_STROKES) {
1406                                                 t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
1407                                         }
1408                                         else if (t->options & CTX_MASK) {
1409                                                 if (ts->proportional_mask) {
1410                                                         t->flag |= T_PROP_EDIT;
1411
1412                                                         if (ts->proportional == PROP_EDIT_CONNECTED) {
1413                                                                 t->flag |= T_PROP_CONNECTED;
1414                                                         }
1415                                                 }
1416                                         }
1417                                         else if (t->obedit == NULL && ts->proportional_objects) {
1418                                                 t->flag |= T_PROP_EDIT;
1419                                         }
1420                                 }
1421                         }
1422                 }
1423                 
1424                 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) &&
1425                            RNA_property_is_set(op->ptr, prop)))
1426                 {
1427                         t->prop_size = RNA_property_float_get(op->ptr, prop);
1428                 }
1429                 else {
1430                         t->prop_size = ts->proportional_size;
1431                 }
1432                 
1433                 
1434                 /* TRANSFORM_FIX_ME rna restrictions */
1435                 if (t->prop_size <= 0.00001f) {
1436                         printf("Proportional size (%f) under 0.00001, resetting to 1!\n", t->prop_size);
1437                         t->prop_size = 1.0f;
1438                 }
1439                 
1440                 if (op && ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) &&
1441                            RNA_property_is_set(op->ptr, prop)))
1442                 {
1443                         t->prop_mode = RNA_property_enum_get(op->ptr, prop);
1444                 }
1445                 else {
1446                         t->prop_mode = ts->prop_mode;
1447                 }
1448         }
1449         else { /* add not pet option to context when not available */
1450                 t->options |= CTX_NO_PET;
1451         }
1452         
1453         // Mirror is not supported with PET, turn it off.
1454 #if 0
1455         if (t->flag & T_PROP_EDIT) {
1456                 t->flag &= ~T_MIRROR;
1457         }
1458 #endif
1459
1460         setTransformViewAspect(t, t->aspect);
1461
1462         if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && RNA_property_is_set(op->ptr, prop)) {
1463                 RNA_property_float_get_array(op->ptr, prop, t->center);
1464                 mul_v3_v3(t->center, t->aspect);
1465                 t->flag |= T_OVERRIDE_CENTER;
1466         }
1467
1468         setTransformViewMatrices(t);
1469         initNumInput(&t->num);
1470 }
1471
1472 /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
1473 void postTrans(bContext *C, TransInfo *t)
1474 {
1475         TransData *td;
1476         
1477         if (t->draw_handle_view)
1478                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
1479         if (t->draw_handle_apply)
1480                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_apply);
1481         if (t->draw_handle_pixel)
1482                 ED_region_draw_cb_exit(t->ar->type, t->draw_handle_pixel);
1483         if (t->draw_handle_cursor)
1484                 WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
1485
1486         /* Free all custom-data */
1487         {
1488                 TransCustomData *custom_data = &t->custom.first_elem;
1489                 for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
1490                         if (custom_data->free_cb) {
1491                                 /* Can take over freeing t->data and data2d etc... */
1492                                 custom_data->free_cb(t, custom_data);
1493                                 BLI_assert(custom_data->data == NULL);
1494                         }
1495                         else if ((custom_data->data != NULL) && custom_data->use_free) {
1496                                 MEM_freeN(custom_data->data);
1497                                 custom_data->data = NULL;
1498                         }
1499                 }
1500         }
1501
1502         /* postTrans can be called when nothing is selected, so data is NULL already */
1503         if (t->data) {
1504                 
1505                 /* free data malloced per trans-data */
1506                 if ((t->obedit && ELEM(t->obedit->type, OB_CURVE, OB_SURF)) ||
1507                     (t->spacetype == SPACE_IPO))
1508                 {
1509                         int a;
1510                         for (a = 0, td = t->data; a < t->total; a++, td++) {
1511                                 if (td->flag & TD_BEZTRIPLE) {
1512                                         MEM_freeN(td->hdata);
1513                                 }
1514                         }
1515                 }
1516                 MEM_freeN(t->data);
1517         }
1518         
1519         BLI_freelistN(&t->tsnap.points);
1520
1521         if (t->ext) MEM_freeN(t->ext);
1522         if (t->data2d) {
1523                 MEM_freeN(t->data2d);
1524                 t->data2d = NULL;
1525         }
1526         
1527         if (t->spacetype == SPACE_IMAGE) {
1528                 if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
1529                         /* pass */
1530                 }
1531                 else {
1532                         SpaceImage *sima = t->sa->spacedata.first;
1533                         if (sima->flag & SI_LIVE_UNWRAP)
1534                                 ED_uvedit_live_unwrap_end(t->state == TRANS_CANCEL);
1535                 }
1536         }
1537         else if (t->spacetype == SPACE_VIEW3D) {
1538                 View3D *v3d = t->sa->spacedata.first;
1539                 /* restore manipulator */
1540                 if (t->flag & T_MODAL) {
1541                         v3d->twtype = t->twtype;
1542                 }
1543         }
1544         
1545         if (t->mouse.data) {
1546                 MEM_freeN(t->mouse.data);
1547         }
1548
1549         freeSnapping(t);
1550 }
1551
1552 void applyTransObjects(TransInfo *t)
1553 {
1554         TransData *td;
1555         
1556         for (td = t->data; td < t->data + t->total; td++) {
1557                 copy_v3_v3(td->iloc, td->loc);
1558                 if (td->ext->rot) {
1559                         copy_v3_v3(td->ext->irot, td->ext->rot);
1560                 }
1561                 if (td->ext->size) {
1562                         copy_v3_v3(td->ext->isize, td->ext->size);
1563                 }
1564         }
1565         recalcData(t);
1566 }
1567
1568 static void restoreElement(TransData *td)
1569 {
1570         /* TransData for crease has no loc */
1571         if (td->loc) {
1572                 copy_v3_v3(td->loc, td->iloc);
1573         }
1574         if (td->val) {
1575                 *td->val = td->ival;
1576         }
1577
1578         if (td->ext && (td->flag & TD_NO_EXT) == 0) {
1579                 if (td->ext->rot) {
1580                         copy_v3_v3(td->ext->rot, td->ext->irot);
1581                 }
1582                 if (td->ext->rotAngle) {
1583                         *td->ext->rotAngle = td->ext->irotAngle;
1584                 }
1585                 if (td->ext->rotAxis) {
1586                         copy_v3_v3(td->ext->rotAxis, td->ext->irotAxis);
1587                 }
1588                 /* XXX, drotAngle & drotAxis not used yet */
1589                 if (td->ext->size) {
1590                         copy_v3_v3(td->ext->size, td->ext->isize);
1591                 }
1592                 if (td->ext->quat) {
1593                         copy_qt_qt(td->ext->quat, td->ext->iquat);
1594                 }
1595         }
1596         
1597         if (td->flag & TD_BEZTRIPLE) {
1598                 *(td->hdata->h1) = td->hdata->ih1;
1599                 *(td->hdata->h2) = td->hdata->ih2;
1600         }
1601 }
1602
1603 void restoreTransObjects(TransInfo *t)
1604 {
1605         TransData *td;
1606         TransData2D *td2d;
1607
1608         for (td = t->data; td < t->data + t->total; td++) {
1609                 restoreElement(td);
1610         }
1611         
1612         for (td2d = t->data2d; t->data2d && td2d < t->data2d + t->total; td2d++) {
1613                 if (td2d->h1) {
1614                         td2d->h1[0] = td2d->ih1[0];
1615                         td2d->h1[1] = td2d->ih1[1];
1616                 }
1617                 if (td2d->h2) {
1618                         td2d->h2[0] = td2d->ih2[0];
1619                         td2d->h2[1] = td2d->ih2[1];
1620                 }
1621         }
1622
1623         unit_m3(t->mat);
1624         
1625         recalcData(t);
1626 }
1627
1628 void calculateCenter2D(TransInfo *t)
1629 {
1630         BLI_assert(!is_zero_v3(t->aspect));
1631
1632         if (t->flag & (T_EDIT | T_POSE)) {
1633                 Object *ob = t->obedit ? t->obedit : t->poseobj;
1634                 float vec[3];
1635                 
1636                 copy_v3_v3(vec, t->center);
1637                 mul_m4_v3(ob->obmat, vec);
1638                 projectFloatView(t, vec, t->center2d);
1639         }
1640         else {
1641                 projectFloatView(t, t->center, t->center2d);
1642         }
1643 }
1644
1645 void calculateCenterGlobal(
1646         TransInfo *t, const float center_local[3],
1647         float r_center_global[3])
1648 {
1649         /* setting constraint center */
1650         /* note, init functions may over-ride t->center */
1651         if (t->flag & (T_EDIT | T_POSE)) {
1652                 Object *ob = t->obedit ? t->obedit : t->poseobj;
1653                 mul_v3_m4v3(r_center_global, ob->obmat, center_local);
1654         }
1655         else {
1656                 copy_v3_v3(r_center_global, center_local);
1657         }
1658 }
1659
1660 void calculateCenterCursor(TransInfo *t, float r_center[3])
1661 {
1662         const float *cursor;
1663         
1664         cursor = ED_view3d_cursor3d_get(t->scene, t->view);
1665         copy_v3_v3(r_center, cursor);
1666         
1667         /* If edit or pose mode, move cursor in local space */
1668         if (t->flag & (T_EDIT | T_POSE)) {
1669                 Object *ob = t->obedit ? t->obedit : t->poseobj;
1670                 float mat[3][3], imat[3][3];
1671                 
1672                 sub_v3_v3v3(r_center, r_center, ob->obmat[3]);
1673                 copy_m3_m4(mat, ob->obmat);
1674                 invert_m3_m3(imat, mat);
1675                 mul_m3_v3(imat, r_center);
1676         }
1677         else if (t->options & CTX_PAINT_CURVE) {
1678                 if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
1679                         r_center[0] = t->ar->winx / 2.0f;
1680                         r_center[1] = t->ar->winy / 2.0f;
1681                 }
1682                 r_center[2] = 0.0f;
1683         }
1684 }
1685
1686 void calculateCenterCursor2D(TransInfo *t, float r_center[2])
1687 {
1688         const float *cursor = NULL;
1689         
1690         if (t->spacetype == SPACE_IMAGE) {
1691                 SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
1692                 cursor = sima->cursor;
1693         }
1694         else if (t->spacetype == SPACE_CLIP) {
1695                 SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
1696                 cursor = space_clip->cursor;
1697         }
1698
1699         if (cursor) {
1700                 if (t->options & CTX_MASK) {
1701                         float co[2];
1702
1703                         if (t->spacetype == SPACE_IMAGE) {
1704                                 SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first;
1705                                 BKE_mask_coord_from_image(sima->image, &sima->iuser, co, cursor);
1706                         }
1707                         else if (t->spacetype == SPACE_CLIP) {
1708                                 SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first;
1709                                 BKE_mask_coord_from_movieclip(space_clip->clip, &space_clip->user, co, cursor);
1710                         }
1711                         else {
1712                                 BLI_assert(!"Shall not happen");
1713                         }
1714
1715                         r_center[0] = co[0] * t->aspect[0];
1716                         r_center[1] = co[1] * t->aspect[1];
1717                 }
1718                 else if (t->options & CTX_PAINT_CURVE) {
1719                         if (t->spacetype == SPACE_IMAGE) {
1720                                 r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]);
1721                                 r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]);
1722                         }
1723                 }
1724                 else {
1725                         r_center[0] = cursor[0] * t->aspect[0];
1726                         r_center[1] = cursor[1] * t->aspect[1];
1727                 }
1728         }
1729 }
1730
1731 void calculateCenterCursorGraph2D(TransInfo *t, float r_center[2])
1732 {
1733         SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
1734         Scene *scene = t->scene;
1735         
1736         /* cursor is combination of current frame, and graph-editor cursor value */
1737         if (sipo->mode == SIPO_MODE_DRIVERS) {
1738                 r_center[0] = sipo->cursorTime;
1739                 r_center[1] = sipo->cursorVal;
1740         }
1741         else {
1742                 r_center[0] = (float)(scene->r.cfra);
1743                 r_center[1] = sipo->cursorVal;
1744         }
1745 }
1746
1747 void calculateCenterMedian(TransInfo *t, float r_center[3])
1748 {
1749         float partial[3] = {0.0f, 0.0f, 0.0f};
1750         int total = 0;
1751         int i;
1752         
1753         for (i = 0; i < t->total; i++) {
1754                 if (t->data[i].flag & TD_SELECTED) {
1755                         if (!(t->data[i].flag & TD_NOCENTER)) {
1756                                 add_v3_v3(partial, t->data[i].center);
1757                                 total++;
1758                         }
1759                 }
1760         }
1761         if (total) {
1762                 mul_v3_fl(partial, 1.0f / (float)total);
1763         }
1764         copy_v3_v3(r_center, partial);
1765 }
1766
1767 void calculateCenterBound(TransInfo *t, float r_center[3])
1768 {
1769         float max[3];
1770         float min[3];
1771         int i;
1772         for (i = 0; i < t->total; i++) {
1773                 if (i) {
1774                         if (t->data[i].flag & TD_SELECTED) {
1775                                 if (!(t->data[i].flag & TD_NOCENTER))
1776                                         minmax_v3v3_v3(min, max, t->data[i].center);
1777                         }
1778                 }
1779                 else {
1780                         copy_v3_v3(max, t->data[i].center);
1781                         copy_v3_v3(min, t->data[i].center);
1782                 }
1783         }
1784         mid_v3_v3v3(r_center, min, max);
1785 }
1786
1787 /**
1788  * \param select_only only get active center from data being transformed.
1789  */
1790 bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
1791 {
1792         bool ok = false;
1793
1794         if (t->obedit) {
1795                 if (ED_object_editmode_calc_active_center(t->obedit, select_only, r_center)) {
1796                         ok = true;
1797                 }
1798         }
1799         else if (t->flag & T_POSE) {
1800                 Scene *scene = t->scene;
1801                 Object *ob = OBACT;
1802                 if (ob) {
1803                         bPoseChannel *pchan = BKE_pose_channel_active(ob);
1804                         if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
1805                                 copy_v3_v3(r_center, pchan->pose_head);
1806                                 ok = true;
1807                         }
1808                 }
1809         }
1810         else if (t->options & CTX_PAINT_CURVE) {
1811                 Paint *p = BKE_paint_get_active(t->scene);
1812                 Brush *br = p->brush;
1813                 PaintCurve *pc = br->paint_curve;
1814                 copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
1815                 r_center[2] = 0.0f;
1816                 ok = true;
1817         }
1818         else {
1819                 /* object mode */
1820                 Scene *scene = t->scene;
1821                 Object *ob = OBACT;
1822                 if (ob && (!select_only || (ob->flag & SELECT))) {
1823                         copy_v3_v3(r_center, ob->obmat[3]);
1824                         ok = true;
1825                 }
1826         }
1827
1828         return ok;
1829 }
1830
1831 static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
1832 {
1833         switch (around) {
1834                 case V3D_AROUND_CENTER_BOUNDS:
1835                         calculateCenterBound(t, r_center);
1836                         break;
1837                 case V3D_AROUND_CENTER_MEAN:
1838                         calculateCenterMedian(t, r_center);
1839                         break;
1840                 case V3D_AROUND_CURSOR:
1841                         if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
1842                                 calculateCenterCursor2D(t, r_center);
1843                         else if (t->spacetype == SPACE_IPO)
1844                                 calculateCenterCursorGraph2D(t, r_center);
1845                         else
1846                                 calculateCenterCursor(t, r_center);
1847                         break;
1848                 case V3D_AROUND_LOCAL_ORIGINS:
1849                         /* Individual element center uses median center for helpline and such */
1850                         calculateCenterMedian(t, r_center);
1851                         break;
1852                 case V3D_AROUND_ACTIVE:
1853                 {
1854                         if (calculateCenterActive(t, false, r_center)) {
1855                                 /* pass */
1856                         }
1857                         else {
1858                                 /* fallback */
1859                                 calculateCenterMedian(t, r_center);
1860                         }
1861                         break;
1862                 }
1863         }
1864 }
1865
1866 void calculateCenter(TransInfo *t)
1867 {
1868         if ((t->flag & T_OVERRIDE_CENTER) == 0) {
1869                 calculateCenter_FromAround(t, t->around, t->center);
1870         }
1871         calculateCenterGlobal(t, t->center, t->center_global);
1872
1873         /* avoid calculating again */
1874         {
1875                 TransCenterData *cd = &t->center_cache[t->around];
1876                 copy_v3_v3(cd->local, t->center);
1877                 copy_v3_v3(cd->global, t->center_global);
1878                 cd->is_set = true;
1879         }
1880
1881         calculateCenter2D(t);
1882
1883         /* for panning from cameraview */
1884         if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) {
1885                 if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) {
1886                         
1887                         if (t->flag & T_CAMERA) {
1888                                 float axis[3];
1889                                 /* persinv is nasty, use viewinv instead, always right */
1890                                 copy_v3_v3(axis, t->viewinv[2]);
1891                                 normalize_v3(axis);
1892                                 
1893                                 /* 6.0 = 6 grid units */
1894                                 axis[0] = t->center[0] - 6.0f * axis[0];
1895                                 axis[1] = t->center[1] - 6.0f * axis[1];
1896                                 axis[2] = t->center[2] - 6.0f * axis[2];
1897                                 
1898                                 projectFloatView(t, axis, t->center2d);
1899                                 
1900                                 /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
1901                                 if (t->mode == TFM_TRANSLATION) {
1902                                         copy_v3_v3(t->center, axis);
1903                                         copy_v3_v3(t->center_global, t->center);
1904                                 }
1905                         }
1906                 }
1907         }
1908         
1909         if (t->spacetype == SPACE_VIEW3D) {
1910                 /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */
1911
1912                 /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW
1913                  * and never used in other cases.
1914                  *
1915                  * We need special case here as well, since ED_view3d_calc_zfac will crash when called
1916                  * for a region different from RGN_TYPE_WINDOW.
1917                  */
1918                 if (t->ar->regiontype == RGN_TYPE_WINDOW) {
1919                         t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, t->center_global, NULL);
1920                 }
1921                 else {
1922                         t->zfac = 0.0f;
1923                 }
1924         }
1925 }
1926
1927 BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1), "test size");
1928
1929 /**
1930  * Lazy initialize transform center data, when we need to access center values from other types.
1931  */
1932 const TransCenterData *transformCenter_from_type(TransInfo *t, int around)
1933 {
1934         BLI_assert(around <= V3D_AROUND_ACTIVE);
1935         TransCenterData *cd = &t->center_cache[around];
1936         if (cd->is_set == false) {
1937                 calculateCenter_FromAround(t, around, cd->local);
1938                 calculateCenterGlobal(t, cd->local, cd->global);
1939                 cd->is_set = true;
1940         }
1941         return cd;
1942 }
1943
1944 void calculatePropRatio(TransInfo *t)
1945 {
1946         TransData *td = t->data;
1947         int i;
1948         float dist;
1949         const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
1950
1951         t->proptext[0] = '\0';
1952
1953         if (t->flag & T_PROP_EDIT) {
1954                 const char *pet_id = NULL;
1955                 for (i = 0; i < t->total; i++, td++) {
1956                         if (td->flag & TD_SELECTED) {
1957                                 td->factor = 1.0f;
1958                         }
1959                         else if (t->flag & T_MIRROR && td->loc[0] * t->mirror < -0.00001f) {
1960                                 td->flag |= TD_SKIP;
1961                                 td->factor = 0.0f;
1962                                 restoreElement(td);
1963                         }
1964                         else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
1965                                  (connected == 0 && td->rdist > t->prop_size))
1966                         {
1967                                 /*
1968                                  * The elements are sorted according to their dist member in the array,
1969                                  * that means we can stop when it finds one element outside of the propsize.
1970                                  * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
1971                                  */
1972                                 
1973                                 td->factor = 0.0f;
1974                                 restoreElement(td);
1975                         }
1976                         else {
1977                                 /* Use rdist for falloff calculations, it is the real distance */
1978                                 td->flag &= ~TD_NOACTION;
1979                                 
1980                                 if (connected)
1981                                         dist = (t->prop_size - td->dist) / t->prop_size;
1982                                 else
1983                                         dist = (t->prop_size - td->rdist) / t->prop_size;
1984
1985                                 /*
1986                                  * Clamp to positive numbers.
1987                                  * Certain corner cases with connectivity and individual centers
1988                                  * can give values of rdist larger than propsize.
1989                                  */
1990                                 if (dist < 0.0f)
1991                                         dist = 0.0f;
1992                                 
1993                                 switch (t->prop_mode) {
1994                                         case PROP_SHARP:
1995                                                 td->factor = dist * dist;
1996                                                 break;
1997                                         case PROP_SMOOTH:
1998                                                 td->factor = 3.0f * dist * dist - 2.0f * dist * dist * dist;
1999                                                 break;
2000                                         case PROP_ROOT:
2001                                                 td->factor = sqrtf(dist);
2002                                                 break;
2003                                         case PROP_LIN:
2004                                                 td->factor = dist;
2005                                                 break;
2006                                         case PROP_CONST:
2007                                                 td->factor = 1.0f;
2008                                                 break;
2009                                         case PROP_SPHERE:
2010                                                 td->factor = sqrtf(2 * dist - dist * dist);
2011                                                 break;
2012                                         case PROP_RANDOM:
2013                                                 td->factor = BLI_frand() * dist;
2014                                                 break;
2015                                         case PROP_INVSQUARE:
2016                                                 td->factor = dist * (2.0f - dist);
2017                                                 break;
2018                                         default:
2019                                                 td->factor = 1;
2020                                                 break;
2021                                 }
2022                         }
2023                 }
2024                 switch (t->prop_mode) {
2025                         case PROP_SHARP:
2026                                 pet_id = N_("(Sharp)");
2027                                 break;
2028                         case PROP_SMOOTH:
2029                                 pet_id = N_("(Smooth)");
2030                                 break;
2031                         case PROP_ROOT:
2032                                 pet_id = N_("(Root)");
2033                                 break;
2034                         case PROP_LIN:
2035                                 pet_id = N_("(Linear)");
2036                                 break;
2037                         case PROP_CONST:
2038                                 pet_id = N_("(Constant)");
2039                                 break;
2040                         case PROP_SPHERE:
2041                                 pet_id = N_("(Sphere)");
2042                                 break;
2043                         case PROP_RANDOM:
2044                                 pet_id = N_("(Random)");
2045                                 break;
2046                         case PROP_INVSQUARE:
2047                                 pet_id = N_("(InvSquare)");
2048                                 break;
2049                         default:
2050                                 break;
2051                 }
2052
2053                 if (pet_id) {
2054                         BLI_strncpy(t->proptext, IFACE_(pet_id), sizeof(t->proptext));
2055                 }
2056         }
2057         else {
2058                 for (i = 0; i < t->total; i++, td++) {
2059                         td->factor = 1.0;
2060                 }
2061         }
2062 }
2063
2064 /**
2065  * Rotate an element, low level code, ignore protected channels.
2066  * (use for objects or pose-bones)
2067  * Similar to #ElementRotation.
2068  */
2069 void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot)
2070 {
2071         float totmat[3][3];
2072         float smat[3][3];
2073         float fmat[3][3];
2074         float obmat[3][3];
2075
2076         float dmat[3][3];  /* delta rotation */
2077         float dmat_inv[3][3];
2078
2079         mul_m3_m3m3(totmat, mat, td->mtx);
2080         mul_m3_m3m3(smat, td->smtx, mat);
2081
2082         /* logic from BKE_object_rot_to_mat3 */
2083         if (use_drot) {
2084                 if (td->ext->rotOrder > 0) {
2085                         eulO_to_mat3(dmat, td->ext->drot, td->ext->rotOrder);
2086                 }
2087                 else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
2088 #if 0
2089                         axis_angle_to_mat3(dmat, td->ext->drotAxis, td->ext->drotAngle);
2090 #else
2091                         unit_m3(dmat);
2092 #endif
2093                 }
2094                 else {
2095                         float tquat[4];
2096                         normalize_qt_qt(tquat, td->ext->dquat);
2097                         quat_to_mat3(dmat, tquat);
2098                 }
2099
2100                 invert_m3_m3(dmat_inv, dmat);
2101         }
2102
2103
2104         if (td->ext->rotOrder == ROT_MODE_QUAT) {
2105                 float quat[4];
2106
2107                 /* calculate the total rotatation */
2108                 quat_to_mat3(obmat, td->ext->iquat);
2109                 if (use_drot) {
2110                         mul_m3_m3m3(obmat, dmat, obmat);
2111                 }
2112
2113                 /* mat = transform, obmat = object rotation */
2114                 mul_m3_m3m3(fmat, smat, obmat);
2115
2116                 if (use_drot) {
2117                         mul_m3_m3m3(fmat, dmat_inv, fmat);
2118                 }
2119
2120                 mat3_to_quat(quat, fmat);
2121
2122                 /* apply */
2123                 copy_qt_qt(td->ext->quat, quat);
2124         }
2125         else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) {
2126                 float axis[3], angle;
2127
2128                 /* calculate the total rotatation */
2129                 axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle);
2130                 if (use_drot) {
2131                         mul_m3_m3m3(obmat, dmat, obmat);
2132                 }
2133
2134                 /* mat = transform, obmat = object rotation */
2135                 mul_m3_m3m3(fmat, smat, obmat);
2136
2137                 if (use_drot) {
2138                         mul_m3_m3m3(fmat, dmat_inv, fmat);
2139                 }
2140
2141                 mat3_to_axis_angle(axis, &angle, fmat);
2142
2143                 /* apply */
2144                 copy_v3_v3(td->ext->rotAxis, axis);
2145                 *td->ext->rotAngle = angle;
2146         }
2147         else {
2148                 float eul[3];
2149
2150                 /* calculate the total rotatation */
2151                 eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder);
2152                 if (use_drot) {
2153                         mul_m3_m3m3(obmat, dmat, obmat);
2154                 }
2155
2156                 /* mat = transform, obmat = object rotation */
2157                 mul_m3_m3m3(fmat, smat, obmat);
2158
2159                 if (use_drot) {
2160                         mul_m3_m3m3(fmat, dmat_inv, fmat);
2161                 }
2162
2163                 mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat);
2164
2165                 /* apply */
2166                 copy_v3_v3(td->ext->rot, eul);
2167         }
2168 }
2169