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