Blender  V3.3
transform_convert_graph.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "DNA_anim_types.h"
9 #include "DNA_space_types.h"
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_math.h"
14 
15 #include "BKE_context.h"
16 #include "BKE_fcurve.h"
17 #include "BKE_nla.h"
18 #include "BKE_report.h"
19 
20 #include "ED_anim_api.h"
21 #include "ED_keyframes_edit.h"
22 #include "ED_markers.h"
23 
24 #include "UI_view2d.h"
25 
26 #include "transform.h"
27 #include "transform_convert.h"
28 #include "transform_mode.h"
29 #include "transform_snap.h"
30 
31 typedef struct TransDataGraph {
32  float unit_scale;
33  float offset;
35 
36 /* -------------------------------------------------------------------- */
40 /* Helper function for createTransGraphEditData, which is responsible for associating
41  * source data with transform data
42  */
43 static void bezt_to_transdata(TransData *td,
44  TransData2D *td2d,
45  TransDataGraph *tdg,
46  AnimData *adt,
47  BezTriple *bezt,
48  int bi,
49  bool selected,
50  bool ishandle,
51  bool intvals,
52  const float mtx[3][3],
53  const float smtx[3][3],
54  float unit_scale,
55  float offset)
56 {
57  float *loc = bezt->vec[bi];
58  const float *cent = bezt->vec[1];
59 
60  /* New location from td gets dumped onto the old-location of td2d, which then
61  * gets copied to the actual data at td2d->loc2d (bezt->vec[n])
62  *
63  * Due to NLA mapping, we apply NLA mapping to some of the verts here,
64  * and then that mapping will be undone after transform is done.
65  */
66 
67  if (adt) {
68  td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP);
69  td2d->loc[1] = (loc[1] + offset) * unit_scale;
70  td2d->loc[2] = 0.0f;
71  td2d->loc2d = loc;
72 
73  td->loc = td2d->loc;
74  td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP);
75  td->center[1] = (cent[1] + offset) * unit_scale;
76  td->center[2] = 0.0f;
77 
78  copy_v3_v3(td->iloc, td->loc);
79  }
80  else {
81  td2d->loc[0] = loc[0];
82  td2d->loc[1] = (loc[1] + offset) * unit_scale;
83  td2d->loc[2] = 0.0f;
84  td2d->loc2d = loc;
85 
86  td->loc = td2d->loc;
87  copy_v3_v3(td->center, cent);
88  td->center[1] = (td->center[1] + offset) * unit_scale;
89  copy_v3_v3(td->iloc, td->loc);
90  }
91 
92  if (!ishandle) {
93  td2d->h1 = bezt->vec[0];
94  td2d->h2 = bezt->vec[2];
95  copy_v2_v2(td2d->ih1, td2d->h1);
96  copy_v2_v2(td2d->ih2, td2d->h2);
97  }
98  else {
99  td2d->h1 = NULL;
100  td2d->h2 = NULL;
101  }
102 
103  memset(td->axismtx, 0, sizeof(td->axismtx));
104  td->axismtx[2][2] = 1.0f;
105 
106  td->ext = NULL;
107  td->val = NULL;
108 
109  /* store AnimData info in td->extra, for applying mapping when flushing */
110  td->extra = adt;
111 
112  if (selected) {
113  td->flag |= TD_SELECTED;
114  td->dist = 0.0f;
115  }
116  else {
117  td->dist = FLT_MAX;
118  }
119 
120  if (ishandle) {
121  td->flag |= TD_NOTIMESNAP;
122  }
123  if (intvals) {
124  td->flag |= TD_INTVALUES;
125  }
126 
127  /* copy space-conversion matrices for dealing with non-uniform scales */
128  copy_m3_m3(td->mtx, mtx);
129  copy_m3_m3(td->smtx, smtx);
130 
131  tdg->unit_scale = unit_scale;
132  tdg->offset = offset;
133 }
134 
136 {
138 }
139 
141 {
142  return ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (graph_edit_is_translation_mode(t) == false));
143 }
144 
150  const BezTriple *bezt,
151  const bool use_handle,
152  bool *r_left_handle,
153  bool *r_key,
154  bool *r_right_handle)
155 {
156  SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
157  bool key = (bezt->f2 & SELECT) != 0;
158  bool left = use_handle ? ((bezt->f1 & SELECT) != 0) : key;
159  bool right = use_handle ? ((bezt->f3 & SELECT) != 0) : key;
160 
161  if (use_handle && t->is_launch_event_drag) {
163  key = right = false;
164  }
166  left = key = false;
167  }
168  }
169 
170  /* Whenever we move the key, we also move both handles. */
171  if (key) {
172  left = right = true;
173  }
174 
175  *r_key = key;
176  *r_left_handle = left;
177  *r_right_handle = right;
178 }
179 
181  TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
182 {
183  int j = 0;
184  TransData *td_iter = td_start;
185  bool sel_key, sel_left, sel_right;
186 
187  td->dist = FLT_MAX;
188  for (; j < fcu->totvert; j++) {
189  BezTriple *bezt = fcu->bezt + j;
190  if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
191  graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
192 
193  if (sel_left || sel_key || sel_right) {
194  td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0]));
195  }
196 
197  td_iter += 3;
198  }
199  }
200 }
201 
212 {
213  SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
214  Scene *scene = t->scene;
215  ARegion *region = t->region;
216  View2D *v2d = &region->v2d;
217 
218  TransData *td = NULL;
219  TransData2D *td2d = NULL;
220  TransDataGraph *tdg = NULL;
221 
222  bAnimContext ac;
223  ListBase anim_data = {NULL, NULL};
224  bAnimListElem *ale;
225  int filter;
226 
227  BezTriple *bezt;
228  int count = 0, i;
229  float mtx[3][3], smtx[3][3];
230  const bool use_handle = !(sipo->flag & SIPO_NOHANDLES);
231  const bool use_local_center = graph_edit_use_local_center(t);
232  const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
233  short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS;
234  bool sel_key, sel_left, sel_right;
235 
236  /* determine what type of data we are operating on */
237  if (ANIM_animdata_get_context(C, &ac) == 0) {
238  return;
239  }
240 
241  anim_map_flag |= ANIM_get_normalization_flags(&ac);
242 
243  /* filter data */
246  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
247 
248  /* which side of the current frame should be allowed */
249  /* XXX we still want this mode, but how to get this using standard transform too? */
250  if (t->mode == TFM_TIME_EXTEND) {
251  t->frame_side = transform_convert_frame_side_dir_get(t, (float)scene->r.cfra);
252  }
253  else {
254  /* normal transform - both sides of current frame are considered */
255  t->frame_side = 'B';
256  }
257 
258  /* Loop 1: count how many BezTriples (specifically their verts)
259  * are selected (or should be edited). */
260  for (ale = anim_data.first; ale; ale = ale->next) {
261  AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
262  FCurve *fcu = (FCurve *)ale->key_data;
263  float cfra;
264  int curvecount = 0;
265  bool selected = false;
266 
267  /* F-Curve may not have any keyframes */
268  if (fcu->bezt == NULL) {
269  continue;
270  }
271 
272  /* convert current-frame to action-time (slightly less accurate, especially under
273  * higher scaling ratios, but is faster than converting all points)
274  */
275  if (adt) {
277  }
278  else {
279  cfra = (float)scene->r.cfra;
280  }
281 
282  for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
283  /* Only include BezTriples whose 'keyframe'
284  * occurs on the same side of the current frame as mouse. */
285  if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
286  graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
287 
288  if (is_prop_edit) {
289  curvecount += 3;
290  if (sel_key || sel_left || sel_right) {
291  selected = true;
292  }
293  }
294  else {
295  if (sel_left) {
296  count++;
297  }
298 
299  if (sel_right) {
300  count++;
301  }
302 
303  /* only include main vert if selected */
304  if (sel_key && !use_local_center) {
305  count++;
306  }
307  }
308  }
309  }
310 
311  if (is_prop_edit) {
312  if (selected) {
313  count += curvecount;
314  ale->tag = true;
315  }
316  }
317  }
318 
319  /* stop if trying to build list if nothing selected */
320  if (count == 0) {
321  /* cleanup temp list */
322  ANIM_animdata_freelist(&anim_data);
323  return;
324  }
325 
327 
328  /* allocate memory for data */
329  tc->data_len = count;
330 
331  tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData (Graph Editor)");
332  /* For each 2d vert a 3d vector is allocated,
333  * so that they can be treated just as if they were 3d verts. */
334  tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)");
335  tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph");
336  tc->custom.type.use_free = true;
337 
338  td = tc->data;
339  td2d = tc->data_2d;
340  tdg = tc->custom.type.data;
341 
342  /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */
343  unit_m3(mtx);
344  unit_m3(smtx);
345 
346  if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
347  float xscale, yscale;
348 
349  /* apply scale factors to x and y axes of space-conversion matrices */
350  UI_view2d_scale_get(v2d, &xscale, &yscale);
351 
352  /* mtx is data to global (i.e. view) conversion */
353  mul_v3_fl(mtx[0], xscale);
354  mul_v3_fl(mtx[1], yscale);
355 
356  /* smtx is global (i.e. view) to data conversion */
357  if (IS_EQF(xscale, 0.0f) == 0) {
358  mul_v3_fl(smtx[0], 1.0f / xscale);
359  }
360  if (IS_EQF(yscale, 0.0f) == 0) {
361  mul_v3_fl(smtx[1], 1.0f / yscale);
362  }
363  }
364 
365  /* loop 2: build transdata arrays */
366  for (ale = anim_data.first; ale; ale = ale->next) {
367  AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
368  FCurve *fcu = (FCurve *)ale->key_data;
369  bool intvals = (fcu->flag & FCURVE_INT_VALUES) != 0;
370  float unit_scale, offset;
371  float cfra;
372 
373  /* F-Curve may not have any keyframes */
374  if (fcu->bezt == NULL || (is_prop_edit && ale->tag == 0)) {
375  continue;
376  }
377 
378  /* convert current-frame to action-time (slightly less accurate, especially under
379  * higher scaling ratios, but is faster than converting all points)
380  */
381  if (adt) {
383  }
384  else {
385  cfra = (float)scene->r.cfra;
386  }
387 
388  unit_scale = ANIM_unit_mapping_get_factor(
389  ac.scene, ale->id, ale->key_data, anim_map_flag, &offset);
390 
391  for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
392  /* Ensure temp flag is cleared for all triples, we use it. */
393  bezt->f1 &= ~BEZT_FLAG_TEMP_TAG;
394  bezt->f2 &= ~BEZT_FLAG_TEMP_TAG;
395  bezt->f3 &= ~BEZT_FLAG_TEMP_TAG;
396 
397  /* only include BezTriples whose 'keyframe' occurs on the same side
398  * of the current frame as mouse (if applicable) */
399  if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
401 
402  graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
403 
404  if (is_prop_edit) {
405  bool is_sel = (sel_key || sel_left || sel_right);
406  /* we always select all handles for proportional editing if central handle is selected */
407  initTransDataCurveHandles(td, bezt);
408  bezt_to_transdata(td++,
409  td2d++,
410  tdg++,
411  adt,
412  bezt,
413  0,
414  is_sel,
415  true,
416  intvals,
417  mtx,
418  smtx,
419  unit_scale,
420  offset);
421  initTransDataCurveHandles(td, bezt);
422  bezt_to_transdata(td++,
423  td2d++,
424  tdg++,
425  adt,
426  bezt,
427  1,
428  is_sel,
429  false,
430  intvals,
431  mtx,
432  smtx,
433  unit_scale,
434  offset);
435  initTransDataCurveHandles(td, bezt);
436  bezt_to_transdata(td++,
437  td2d++,
438  tdg++,
439  adt,
440  bezt,
441  2,
442  is_sel,
443  true,
444  intvals,
445  mtx,
446  smtx,
447  unit_scale,
448  offset);
449 
450  if (is_sel) {
451  bezt->f1 |= BEZT_FLAG_TEMP_TAG;
452  bezt->f2 |= BEZT_FLAG_TEMP_TAG;
453  bezt->f3 |= BEZT_FLAG_TEMP_TAG;
454  }
455  }
456  else {
457  /* only include handles if selected, irrespective of the interpolation modes.
458  * also, only treat handles specially if the center point isn't selected.
459  */
460  if (sel_left) {
461  hdata = initTransDataCurveHandles(td, bezt);
462  bezt_to_transdata(td++,
463  td2d++,
464  tdg++,
465  adt,
466  bezt,
467  0,
468  sel_left,
469  true,
470  intvals,
471  mtx,
472  smtx,
473  unit_scale,
474  offset);
475  bezt->f1 |= BEZT_FLAG_TEMP_TAG;
476  }
477 
478  if (sel_right) {
479  if (hdata == NULL) {
480  hdata = initTransDataCurveHandles(td, bezt);
481  }
482  bezt_to_transdata(td++,
483  td2d++,
484  tdg++,
485  adt,
486  bezt,
487  2,
488  sel_right,
489  true,
490  intvals,
491  mtx,
492  smtx,
493  unit_scale,
494  offset);
495  bezt->f3 |= BEZT_FLAG_TEMP_TAG;
496  }
497 
498  /* only include main vert if selected */
499  if (sel_key && !use_local_center) {
500  /* move handles relative to center */
502  if (sel_left) {
503  td->flag |= TD_MOVEHANDLE1;
504  }
505  if (sel_right) {
506  td->flag |= TD_MOVEHANDLE2;
507  }
508  }
509 
510  /* if handles were not selected, store their selection status */
511  if (!(sel_left) || !(sel_right)) {
512  if (hdata == NULL) {
513  hdata = initTransDataCurveHandles(td, bezt);
514  }
515  }
516 
517  bezt_to_transdata(td++,
518  td2d++,
519  tdg++,
520  adt,
521  bezt,
522  1,
523  sel_key,
524  false,
525  intvals,
526  mtx,
527  smtx,
528  unit_scale,
529  offset);
530  bezt->f2 |= BEZT_FLAG_TEMP_TAG;
531  }
532  /* Special hack (must be done after #initTransDataCurveHandles(),
533  * as that stores handle settings to restore...):
534  *
535  * - Check if we've got entire BezTriple selected and we're scaling/rotating that point,
536  * then check if we're using auto-handles.
537  * - If so, change them auto-handles to aligned handles so that handles get affected too
538  */
539  if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM) && ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM) &&
540  ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) {
541  if (hdata && (sel_left) && (sel_right)) {
542  bezt->h1 = HD_ALIGN;
543  bezt->h2 = HD_ALIGN;
544  }
545  }
546  }
547  }
548  }
549 
550  /* Sets handles based on the selection */
551  testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
552  }
553 
554  if (is_prop_edit) {
555  /* loop 2: build transdata arrays */
556  td = tc->data;
557 
558  for (ale = anim_data.first; ale; ale = ale->next) {
559  AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
560  FCurve *fcu = (FCurve *)ale->key_data;
561  TransData *td_start = td;
562  float cfra;
563 
564  /* F-Curve may not have any keyframes */
565  if (fcu->bezt == NULL || (ale->tag == 0)) {
566  continue;
567  }
568 
569  /* convert current-frame to action-time (slightly less accurate, especially under
570  * higher scaling ratios, but is faster than converting all points)
571  */
572  if (adt) {
574  }
575  else {
576  cfra = (float)scene->r.cfra;
577  }
578 
579  for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
580  /* only include BezTriples whose 'keyframe' occurs on the
581  * same side of the current frame as mouse (if applicable) */
582  if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) {
583  graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right);
584 
585  if (sel_left || sel_key) {
586  td->dist = td->rdist = 0.0f;
587  }
588  else {
589  graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
590  }
591  td++;
592 
593  if (sel_key) {
594  td->dist = td->rdist = 0.0f;
595  }
596  else {
597  graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
598  }
599  td++;
600 
601  if (sel_right || sel_key) {
602  td->dist = td->rdist = 0.0f;
603  }
604  else {
605  graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle);
606  }
607  td++;
608  }
609  }
610  }
611  }
612 
613  /* cleanup temp list */
614  ANIM_animdata_freelist(&anim_data);
615 }
616 
619 /* -------------------------------------------------------------------- */
623 static bool fcu_test_selected(FCurve *fcu)
624 {
625  BezTriple *bezt = fcu->bezt;
626  uint i;
627 
628  if (bezt == NULL) { /* ignore baked */
629  return 0;
630  }
631 
632  for (i = 0; i < fcu->totvert; i++, bezt++) {
633  if (BEZT_ISSEL_ANY(bezt)) {
634  return 1;
635  }
636  }
637 
638  return 0;
639 }
640 
641 /* this function is called on recalcData to apply the transforms applied
642  * to the transdata on to the actual keyframe data
643  */
645 {
646  TransData *td;
647  TransData2D *td2d;
648  TransDataGraph *tdg;
649  int a;
650 
651  const short autosnap = getAnimEdit_SnapMode(t);
653 
654  /* flush to 2d vector from internally used 3d vector */
655  for (a = 0, td = tc->data, td2d = tc->data_2d, tdg = tc->custom.type.data; a < tc->data_len;
656  a++, td++, td2d++, tdg++) {
657  /* pointers to relevant AnimData blocks are stored in the td->extra pointers */
658  AnimData *adt = (AnimData *)td->extra;
659 
660  float inv_unit_scale = 1.0f / tdg->unit_scale;
661 
662  /* Handle snapping for time values:
663  * - We should still be in NLA-mapping time-space.
664  * - Only apply to keyframes (but never to handles).
665  * - Don't do this when canceling, or else these changes won't go away.
666  */
667  if ((autosnap != SACTSNAP_OFF) && (t->state != TRANS_CANCEL) && !(td->flag & TD_NOTIMESNAP)) {
668  transform_snap_anim_flush_data(t, td, autosnap, td->loc);
669  }
670 
671  /* we need to unapply the nla-mapping from the time in some situations */
672  if (adt) {
673  td2d->loc2d[0] = BKE_nla_tweakedit_remap(adt, td2d->loc[0], NLATIME_CONVERT_UNMAP);
674  }
675  else {
676  td2d->loc2d[0] = td2d->loc[0];
677  }
678 
679  /* if int-values only, truncate to integers */
680  if (td->flag & TD_INTVALUES) {
681  td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f);
682  }
683  else {
684  td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset;
685  }
686 
687  transform_convert_flush_handle2D(td, td2d, inv_unit_scale);
688  }
689 }
690 
691 /* struct for use in re-sorting BezTriples during Graph Editor transform */
692 typedef struct BeztMap {
694  uint oldIndex; /* index of bezt in fcu->bezt array before sorting */
695  uint newIndex; /* index of bezt in fcu->bezt array after sorting */
696  short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */
697  char pipo, cipo; /* interpolation of current and next segments */
699 
700 /* This function converts an FCurve's BezTriple array to a BeztMap array
701  * NOTE: this allocates memory that will need to get freed later
702  */
703 static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert)
704 {
705  BezTriple *bezt = bezts;
706  BezTriple *prevbezt = NULL;
707  BeztMap *bezm, *bezms;
708  int i;
709 
710  /* allocate memory for this array */
711  if (totvert == 0 || bezts == NULL) {
712  return NULL;
713  }
714  bezm = bezms = MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps");
715 
716  /* assign beztriples to beztmaps */
717  for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) {
718  bezm->bezt = bezt;
719 
720  bezm->oldIndex = i;
721  bezm->newIndex = i;
722 
723  bezm->pipo = (prevbezt) ? prevbezt->ipo : bezt->ipo;
724  bezm->cipo = bezt->ipo;
725  }
726 
727  return bezms;
728 }
729 
730 /* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */
731 static void sort_time_beztmaps(BeztMap *bezms, int totvert)
732 {
733  BeztMap *bezm;
734  int i, ok = 1;
735 
736  /* keep repeating the process until nothing is out of place anymore */
737  while (ok) {
738  ok = 0;
739 
740  bezm = bezms;
741  i = totvert;
742  while (i--) {
743  /* is current bezm out of order (i.e. occurs later than next)? */
744  if (i > 0) {
745  if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) {
746  bezm->newIndex++;
747  (bezm + 1)->newIndex--;
748 
749  SWAP(BeztMap, *bezm, *(bezm + 1));
750 
751  ok = 1;
752  }
753  }
754 
755  /* do we need to check if the handles need to be swapped?
756  * optimization: this only needs to be performed in the first loop
757  */
758  if (bezm->swapHs == 0) {
759  if ((bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) &&
760  (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0])) {
761  /* handles need to be swapped */
762  bezm->swapHs = 1;
763  }
764  else {
765  /* handles need to be cleared */
766  bezm->swapHs = -1;
767  }
768  }
769 
770  bezm++;
771  }
772  }
773 }
774 
775 /* This function firstly adjusts the pointers that the transdata has to each BezTriple */
776 static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert)
777 {
778  BezTriple *bezts = fcu->bezt;
779  BeztMap *bezm;
780  TransData2D *td2d;
781  TransData *td;
782  int i, j;
783  char *adjusted;
784 
786 
787  /* dynamically allocate an array of chars to mark whether an TransData's
788  * pointers have been fixed already, so that we don't override ones that are
789  * already done
790  */
791  adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map");
792 
793  /* for each beztmap item, find if it is used anywhere */
794  bezm = bezms;
795  for (i = 0; i < totvert; i++, bezm++) {
796  /* loop through transdata, testing if we have a hit
797  * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
798  */
799  td2d = tc->data_2d;
800  td = tc->data;
801  for (j = 0; j < tc->data_len; j++, td2d++, td++) {
802  /* skip item if already marked */
803  if (adjusted[j] != 0) {
804  continue;
805  }
806 
807  /* update all transdata pointers, no need to check for selections etc,
808  * since only points that are really needed were created as transdata
809  */
810  if (td2d->loc2d == bezm->bezt->vec[0]) {
811  if (bezm->swapHs == 1) {
812  td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
813  }
814  else {
815  td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
816  }
817  adjusted[j] = 1;
818  }
819  else if (td2d->loc2d == bezm->bezt->vec[2]) {
820  if (bezm->swapHs == 1) {
821  td2d->loc2d = (bezts + bezm->newIndex)->vec[0];
822  }
823  else {
824  td2d->loc2d = (bezts + bezm->newIndex)->vec[2];
825  }
826  adjusted[j] = 1;
827  }
828  else if (td2d->loc2d == bezm->bezt->vec[1]) {
829  td2d->loc2d = (bezts + bezm->newIndex)->vec[1];
830 
831  /* if only control point is selected, the handle pointers need to be updated as well */
832  if (td2d->h1) {
833  td2d->h1 = (bezts + bezm->newIndex)->vec[0];
834  }
835  if (td2d->h2) {
836  td2d->h2 = (bezts + bezm->newIndex)->vec[2];
837  }
838 
839  adjusted[j] = 1;
840  }
841 
842  /* the handle type pointer has to be updated too */
843  if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) {
844  if (bezm->swapHs == 1) {
845  td->hdata->h1 = &(bezts + bezm->newIndex)->h2;
846  td->hdata->h2 = &(bezts + bezm->newIndex)->h1;
847  }
848  else {
849  td->hdata->h1 = &(bezts + bezm->newIndex)->h1;
850  td->hdata->h2 = &(bezts + bezm->newIndex)->h2;
851  }
852  }
853  }
854  }
855 
856  /* free temp memory used for 'adjusted' array */
857  MEM_freeN(adjusted);
858 }
859 
860 /* This function is called by recalcData during the Transform loop to recalculate
861  * the handles of curves and sort the keyframes so that the curves draw correctly.
862  * It is only called if some keyframes have moved out of order.
863  *
864  * anim_data is the list of channels (F-Curves) retrieved already containing the
865  * channels to work on. It should not be freed here as it may still need to be used.
866  */
867 static void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
868 {
869  SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
870  bAnimListElem *ale;
871  const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
872 
873  /* sort and reassign verts */
874  for (ale = anim_data->first; ale; ale = ale->next) {
875  FCurve *fcu = (FCurve *)ale->key_data;
876 
877  if (fcu->bezt) {
878  BeztMap *bezm;
879 
880  /* Adjust transform-data pointers. */
881  /* NOTE: none of these functions use 'use_handle', it could be removed. */
882  bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert);
883  sort_time_beztmaps(bezm, fcu->totvert);
884  beztmap_to_data(t, fcu, bezm, fcu->totvert);
885 
886  /* free mapping stuff */
887  MEM_freeN(bezm);
888 
889  /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */
890  sort_time_fcurve(fcu);
891 
892  /* make sure handles are all set correctly */
893  testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
894  }
895  }
896 }
897 
899 {
900  SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
901  ViewLayer *view_layer = t->view_layer;
902 
903  ListBase anim_data = {NULL, NULL};
904  bAnimContext ac = {NULL};
905  int filter;
906 
907  bAnimListElem *ale;
908  int dosort = 0;
909 
910  /* initialize relevant anim-context 'context' data from TransInfo data */
911  /* NOTE: sync this with the code in ANIM_animdata_get_context() */
912  ac.bmain = CTX_data_main(t->context);
913  ac.scene = t->scene;
914  ac.view_layer = t->view_layer;
915  ac.obact = OBACT(view_layer);
916  ac.area = t->area;
917  ac.region = t->region;
918  ac.sl = (t->area) ? t->area->spacedata.first : NULL;
919  ac.spacetype = (t->area) ? t->area->spacetype : 0;
920  ac.regiontype = (t->region) ? t->region->regiontype : 0;
921 
923 
924  /* do the flush first */
926 
927  /* get curves to check if a re-sort is needed */
930  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
931 
932  /* now test if there is a need to re-sort */
933  for (ale = anim_data.first; ale; ale = ale->next) {
934  FCurve *fcu = (FCurve *)ale->key_data;
935 
936  /* ignore FC-Curves without any selected verts */
937  if (!fcu_test_selected(fcu)) {
938  continue;
939  }
940 
941  /* watch it: if the time is wrong: do not correct handles yet */
942  if (test_time_fcurve(fcu)) {
943  dosort++;
944  }
945  else {
947  }
948 
949  /* set refresh tags for objects using this animation,
950  * BUT only if realtime updates are enabled
951  */
952  if ((sipo->flag & SIPO_NOREALTIMEUPDATES) == 0) {
953  ANIM_list_elem_update(CTX_data_main(t->context), t->scene, ale);
954  }
955  }
956 
957  /* do resort and other updates? */
958  if (dosort) {
959  remake_graph_transdata(t, &anim_data);
960  }
961 
962  /* now free temp channels */
963  ANIM_animdata_freelist(&anim_data);
964 }
965 
968 /* -------------------------------------------------------------------- */
973 {
974  SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first;
975  bAnimContext ac;
976  const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0;
977 
978  const bool canceled = (t->state == TRANS_CANCEL);
979  const bool duplicate = (t->mode == TFM_TIME_DUPLICATE);
980 
981  /* initialize relevant anim-context 'context' data */
982  if (ANIM_animdata_get_context(C, &ac) == 0) {
983  return;
984  }
985 
986  if (ac.datatype) {
987  ListBase anim_data = {NULL, NULL};
988  bAnimListElem *ale;
991 
992  /* get channels to work on */
993  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
994 
995  for (ale = anim_data.first; ale; ale = ale->next) {
996  AnimData *adt = ANIM_nla_mapping_get(&ac, ale);
997  FCurve *fcu = (FCurve *)ale->key_data;
998 
999  /* 3 cases here for curve cleanups:
1000  * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
1001  * 2) canceled == 0 -> user confirmed the transform,
1002  * so duplicates should be removed
1003  * 3) canceled + duplicate -> user canceled the transform,
1004  * but we made duplicates, so get rid of these
1005  */
1006  if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) {
1007  if (adt) {
1008  ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
1009  posttrans_fcurve_clean(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
1010  ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
1011  }
1012  else {
1013  posttrans_fcurve_clean(fcu, BEZT_FLAG_TEMP_TAG, use_handle);
1014  }
1015  }
1016  }
1017 
1018  /* free temp memory */
1019  ANIM_animdata_freelist(&anim_data);
1020  }
1021 
1022  /* Make sure all F-Curves are set correctly, but not if transform was
1023  * canceled, since then curves were already restored to initial state.
1024  * NOTE: if the refresh is really needed after cancel then some way
1025  * has to be added to not update handle types (see bug 22289).
1026  */
1027  if (!canceled) {
1029  }
1030 }
1031 
1035  /* flags */ (T_POINTS | T_2D_EDIT),
1036  /* createTransData */ createTransGraphEditData,
1037  /* recalcData */ recalcData_graphedit,
1038  /* special_aftertrans_update */ special_aftertrans_update__graph,
1039 };
typedef float(TangentPoint)[2]
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
void testhandles_fcurve(struct FCurve *fcu, eBezTriple_Flag sel_flag, bool use_handle)
Definition: fcurve.c:1308
void BKE_fcurve_handles_recalc_ex(struct FCurve *fcu, eBezTriple_Flag handle_sel_flag)
Definition: fcurve.c:1220
bool test_time_fcurve(struct FCurve *fcu)
Definition: fcurve.c:1369
void sort_time_fcurve(struct FCurve *fcu)
Definition: fcurve.c:1327
@ NLATIME_CONVERT_MAP
Definition: BKE_nla.h:360
@ NLATIME_CONVERT_UNMAP
Definition: BKE_nla.h:357
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode)
Definition: nla.c:642
MINLINE float min_ff(float a, float b)
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:67
#define SWAP(type, a, b)
#define ELEM(...)
#define IS_EQF(a, b)
@ SACTSNAP_OFF
@ FCURVE_INT_VALUES
#define BEZT_ISSEL_ANY(bezt)
@ HD_AUTO_ANIM
@ HD_AUTO
@ HD_ALIGN
@ BEZT_FLAG_TEMP_TAG
#define OBACT(_view_layer)
@ SIPO_NOREALTIMEUPDATES
@ SIPO_NOTRANSKEYCULL
@ SIPO_NOHANDLES
@ SIPO_RUNTIME_FLAG_TWEAK_HANDLES_RIGHT
@ SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT
@ V3D_AROUND_LOCAL_ORIGINS
@ ANIMFILTER_FOREDIT
Definition: ED_anim_api.h:312
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:292
@ ANIMFILTER_CURVE_VISIBLE
Definition: ED_anim_api.h:297
@ ANIMFILTER_FCURVESONLY
Definition: ED_anim_api.h:328
@ ANIM_UNITCONV_ONLYSEL
Definition: ED_anim_api.h:936
@ ANIM_UNITCONV_SELVERTS
Definition: ED_anim_api.h:938
@ TFM_RESIZE
Definition: ED_transform.h:32
@ TFM_TIME_TRANSLATE
Definition: ED_transform.h:50
@ TFM_TIME_SLIDE
Definition: ED_transform.h:51
@ TFM_ROTATION
Definition: ED_transform.h:31
@ TFM_TIME_DUPLICATE
Definition: ED_transform.h:54
@ TFM_TIME_EXTEND
Definition: ED_transform.h:53
@ TFM_TRANSLATION
Definition: ED_transform.h:30
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble right
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
void UI_view2d_scale_get(const struct View2D *v2d, float *r_x, float *r_y)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:397
void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale)
Definition: anim_deps.c:44
AnimData * ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale)
Definition: anim_draw.c:216
void ANIM_nla_mapping_apply_fcurve(AnimData *adt, FCurve *fcu, bool restore, bool only_keys)
Definition: anim_draw.c:291
float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short flag, float *r_offset)
Definition: anim_draw.c:485
short ANIM_get_normalization_flags(bAnimContext *ac)
Definition: anim_draw.c:318
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:379
bool ANIM_animdata_context_getdata(bAnimContext *ac)
Definition: anim_filter.c:349
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3447
#define SELECT
Scene scene
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
int count
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void ANIM_editkeyframes_refresh(bAnimContext *ac)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
static int left
#define floorf(x)
Definition: metal/compat.h:224
static unsigned a[3]
Definition: RandGen.cpp:78
#define TRANS_DATA_CONTAINER_FIRST_SINGLE(t)
uint8_t h1
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
uint8_t h2
BezTriple * bezt
BezTriple * bezt
short flag
unsigned int totvert
void * first
Definition: DNA_listBase.h:31
struct RenderData r
SpaceGraph_Runtime runtime
float * loc2d
float ih2[2]
float ih1[2]
float loc[3]
TransDataCurveHandleFlags * hdata
float smtx[3][3]
float axismtx[3][3]
float mtx[3][3]
TransDataExtension * ext
float * val
struct ARegion * region
Definition: ED_anim_api.h:76
struct Scene * scene
Definition: ED_anim_api.h:84
short spacetype
Definition: ED_anim_api.h:67
short datatype
Definition: ED_anim_api.h:62
void * data
Definition: ED_anim_api.h:60
struct ScrArea * area
Definition: ED_anim_api.h:72
struct Object * obact
Definition: ED_anim_api.h:90
short regiontype
Definition: ED_anim_api.h:69
struct ViewLayer * view_layer
Definition: ED_anim_api.h:86
struct Main * bmain
Definition: ED_anim_api.h:82
struct SpaceLink * sl
Definition: ED_anim_api.h:74
struct bAnimListElem * next
Definition: ED_anim_api.h:127
void * key_data
Definition: ED_anim_api.h:146
struct ID * id
Definition: ED_anim_api.h:160
void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float y_fac)
bool FrameOnMouseSide(char side, float frame, float cframe)
void posttrans_fcurve_clean(FCurve *fcu, const int sel_flag, const bool use_handle)
TransDataCurveHandleFlags * initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
char transform_convert_frame_side_dir_get(TransInfo *t, float cframe)
conversion and adaptation of different datablocks to a common struct.
static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph *tdg, AnimData *adt, BezTriple *bezt, int bi, bool selected, bool ishandle, bool intvals, const float mtx[3][3], const float smtx[3][3], float unit_scale, float offset)
static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert)
static void createTransGraphEditData(bContext *C, TransInfo *t)
static void remake_graph_transdata(TransInfo *t, ListBase *anim_data)
static void flushTransGraphData(TransInfo *t)
static void recalcData_graphedit(TransInfo *t)
static bool fcu_test_selected(FCurve *fcu)
struct TransDataGraph TransDataGraph
static bool graph_edit_use_local_center(TransInfo *t)
TransConvertTypeInfo TransConvertType_Graph
static void graph_key_shortest_dist(TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle)
static void special_aftertrans_update__graph(bContext *C, TransInfo *t)
static BeztMap * bezt_to_beztmaps(BezTriple *bezts, int totvert)
struct BeztMap BeztMap
static void sort_time_beztmaps(BeztMap *bezms, int totvert)
static void graph_bezt_get_transform_selection(const TransInfo *t, const BezTriple *bezt, const bool use_handle, bool *r_left_handle, bool *r_key, bool *r_right_handle)
static bool graph_edit_is_translation_mode(TransInfo *t)
@ TD_BEZTRIPLE
@ TD_MOVEHANDLE1
@ TD_INTVALUES
@ TD_SELECTED
@ TD_NOTIMESNAP
@ TD_MOVEHANDLE2
transform modes used by different operators.
short getAnimEdit_SnapMode(TransInfo *t)
void transform_snap_anim_flush_data(TransInfo *t, TransData *td, eAnimEdit_AutoSnap autosnap, float *r_val_final)