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