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