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