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