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