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