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