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