Blender  V3.3
graph_draw.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright Blender Foundation. */
3 
8 #include <float.h>
9 #include <math.h>
10 #include <stdio.h>
11 #include <string.h>
12 
13 #include "BLI_blenlib.h"
14 #include "BLI_math.h"
15 #include "BLI_utildefines.h"
16 
17 #include "DNA_anim_types.h"
18 #include "DNA_screen_types.h"
19 #include "DNA_space_types.h"
20 #include "DNA_userdef_types.h"
22 
23 #include "BKE_action.h"
24 #include "BKE_anim_data.h"
25 #include "BKE_context.h"
26 #include "BKE_curve.h"
27 #include "BKE_fcurve.h"
28 #include "BKE_nla.h"
29 
30 #include "GPU_immediate.h"
31 #include "GPU_matrix.h"
32 #include "GPU_state.h"
33 
34 #include "ED_anim_api.h"
35 
36 #include "graph_intern.h"
37 
38 #include "UI_interface.h"
39 #include "UI_resources.h"
40 #include "UI_view2d.h"
41 
42 static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu);
43 
44 /* -------------------------------------------------------------------- */
48 /* determine the alpha value that should be used when
49  * drawing components for some F-Curve (fcu)
50  * - selected F-Curves should be more visible than partially visible ones
51  */
52 static float fcurve_display_alpha(FCurve *fcu)
53 {
54  return (fcu->flag & FCURVE_SELECTED) ? 1.0f : U.fcu_inactive_alpha;
55 }
56 
59 /* -------------------------------------------------------------------- */
63 /* Envelope -------------- */
64 
65 /* TODO: draw a shaded poly showing the region of influence too!!! */
70  View2D *v2d,
71  AnimData *adt_nla_remap)
72 {
73  FMod_Envelope *env = (FMod_Envelope *)fcm->data;
74  FCM_EnvelopeData *fed;
75  const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
76  int i;
77 
78  const uint shdr_pos = GPU_vertformat_attr_add(
80 
81  GPU_line_width(1.0f);
82 
84 
85  float viewport_size[4];
86  GPU_viewport_size_get_f(viewport_size);
87  immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
88 
89  immUniform1i("colors_len", 0); /* Simple dashes. */
90  immUniformColor3f(0.0f, 0.0f, 0.0f);
91  immUniform1f("dash_width", 10.0f);
92  immUniform1f("dash_factor", 0.5f);
93 
94  /* draw two black lines showing the standard reference levels */
95 
97  immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->min);
98  immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->min);
99 
100  immVertex2f(shdr_pos, v2d->cur.xmin, env->midval + env->max);
101  immVertex2f(shdr_pos, v2d->cur.xmax, env->midval + env->max);
102  immEnd();
103 
105 
106  if (env->totvert > 0) {
107  /* set size of vertices (non-adjustable for now) */
108  GPU_point_size(2.0f);
109 
111 
112  /* for now, point color is fixed, and is white */
113  immUniformColor3f(1.0f, 1.0f, 1.0f);
114 
116 
117  for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
118  const float env_scene_time = BKE_nla_tweakedit_remap(
119  adt_nla_remap, fed->time, NLATIME_CONVERT_MAP);
120 
121  /* only draw if visible
122  * - min/max here are fixed, not relative
123  */
124  if (IN_RANGE(env_scene_time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
125  immVertex2f(shdr_pos, env_scene_time, fed->min);
126  immVertex2f(shdr_pos, env_scene_time, fed->max);
127  }
128  }
129 
130  immEnd();
131 
133  }
134 }
135 
138 /* -------------------------------------------------------------------- */
142 /* Points ---------------- */
143 
144 /* helper func - set color to draw F-Curve data with */
145 static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
146 {
147  float color[4];
148  float diff;
149 
150  /* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
151  if ((fcu->flag & FCURVE_PROTECTED) == 0) {
152  /* Curve's points ARE BEING edited */
154  }
155  else {
156  /* Curve's points CANNOT BE edited */
158  }
159 
160  /* Fade the 'intensity' of the vertices based on the selection of the curves too
161  * - Only fade by 50% the amount the curves were faded by, so that the points
162  * still stand out for easier selection
163  */
164  diff = 1.0f - fcurve_display_alpha(fcu);
165  color[3] = 1.0f - (diff * 0.5f);
166  CLAMP(color[3], 0.2f, 1.0f);
167 
169 }
170 
172  FCurve *fcu, View2D *v2d, bool edit, bool sel, uint pos)
173 {
174  const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
175 
176  set_fcurve_vertex_color(fcu, sel);
177 
179 
180  BezTriple *bezt = fcu->bezt;
181  for (int i = 0; i < fcu->totvert; i++, bezt++) {
182  /* As an optimization step, only draw those in view
183  * - We apply a correction factor to ensure that points
184  * don't pop in/out due to slight twitches of view size.
185  */
186  if (IN_RANGE(bezt->vec[1][0], (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
187  if (edit) {
188  /* 'Keyframe' vertex only, as handle lines and handles have already been drawn
189  * - only draw those with correct selection state for the current drawing color
190  * -
191  */
192  if ((bezt->f2 & SELECT) == sel) {
193  immVertex2fv(pos, bezt->vec[1]);
194  }
195  }
196  else {
197  /* no check for selection here, as curve is not editable... */
198  /* XXX perhaps we don't want to even draw points? maybe add an option for that later */
199  immVertex2fv(pos, bezt->vec[1]);
200  }
201  }
202  }
203 
204  immEnd();
205 }
206 
210 static void draw_fcurve_active_vertex(const FCurve *fcu, const View2D *v2d, const uint pos)
211 {
212  const int active_keyframe_index = BKE_fcurve_active_keyframe_index(fcu);
213  if (!(fcu->flag & FCURVE_ACTIVE) || active_keyframe_index == FCURVE_ACTIVE_KEYFRAME_NONE) {
214  return;
215  }
216 
217  const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
218  const BezTriple *bezt = &fcu->bezt[active_keyframe_index];
219 
220  if (!IN_RANGE(bezt->vec[1][0], (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
221  return;
222  }
223  if (!(bezt->f2 & SELECT)) {
224  return;
225  }
226 
229  immVertex2fv(pos, bezt->vec[1]);
230  immEnd();
231 }
232 
233 /* helper func - draw keyframe vertices only for an F-Curve */
234 static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, uint pos)
235 {
237 
238  immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.dpi_fac);
239 
240  draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos);
241  draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos);
242  draw_fcurve_active_vertex(fcu, v2d, pos);
243 
245 }
246 
247 /* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
249  FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, uint pos)
250 {
251  (void)v2d; /* TODO: use this to draw only points in view */
252 
253  /* set handle color */
254  float hcolor[3];
256  immUniform4f("outlineColor", hcolor[0], hcolor[1], hcolor[2], 1.0f);
257  immUniformColor3fvAlpha(hcolor, 0.01f); /* almost invisible - only keep for smoothness */
258 
260 
261  BezTriple *bezt = fcu->bezt;
262  BezTriple *prevbezt = NULL;
263  for (int i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
264  /* Draw the editmode handles for a bezier curve (others don't have handles)
265  * if their selection status matches the selection status we're drawing for
266  * - first handle only if previous beztriple was bezier-mode
267  * - second handle only if current beztriple is bezier-mode
268  *
269  * Also, need to take into account whether the keyframe was selected
270  * if a Graph Editor option to only show handles of selected keys is on.
271  */
272  if (!sel_handle_only || BEZT_ISSEL_ANY(bezt)) {
273  if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) ||
274  (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
275  if ((bezt->f1 & SELECT) == sel
276  /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax) */) {
277  immVertex2fv(pos, bezt->vec[0]);
278  }
279  }
280 
281  if (bezt->ipo == BEZT_IPO_BEZ) {
282  if ((bezt->f3 & SELECT) == sel
283  /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax) */) {
284  immVertex2fv(pos, bezt->vec[2]);
285  }
286  }
287  }
288  }
289 
290  immEnd();
291 }
292 
297  const bool sel_handle_only,
298  const uint pos)
299 {
300  const int active_keyframe_index = BKE_fcurve_active_keyframe_index(fcu);
301  if (!(fcu->flag & FCURVE_ACTIVE) || active_keyframe_index == FCURVE_ACTIVE_KEYFRAME_NONE) {
302  return;
303  }
304 
305  const BezTriple *bezt = &fcu->bezt[active_keyframe_index];
306 
307  if (sel_handle_only && !BEZT_ISSEL_ANY(bezt)) {
308  return;
309  }
310 
311  float active_col[4];
313  immUniform4fv("outlineColor", active_col);
314  immUniformColor3fvAlpha(active_col, 0.01f); /* Almost invisible - only keep for smoothness. */
316 
317  const BezTriple *left_bezt = active_keyframe_index > 0 ? &fcu->bezt[active_keyframe_index - 1] :
318  bezt;
319  if (left_bezt->ipo == BEZT_IPO_BEZ && (bezt->f1 & SELECT)) {
320  immVertex2fv(pos, bezt->vec[0]);
321  }
322  if (bezt->ipo == BEZT_IPO_BEZ && (bezt->f3 & SELECT)) {
323  immVertex2fv(pos, bezt->vec[2]);
324  }
325  immEnd();
326 }
327 
328 /* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
329 static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, uint pos)
330 {
331  /* smooth outlines for more consistent appearance */
333 
334  /* set handle size */
335  immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.dpi_fac);
336  immUniform1f("outlineWidth", 1.5f * U.dpi_fac);
337 
338  draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos);
339  draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos);
340  draw_fcurve_active_handle_vertices(fcu, sel_handle_only, pos);
341 
343 }
344 
345 static void draw_fcurve_vertices(ARegion *region,
346  FCurve *fcu,
347  bool do_handles,
348  bool sel_handle_only)
349 {
350  View2D *v2d = &region->v2d;
351 
352  /* only draw points if curve is visible
353  * - Draw unselected points before selected points as separate passes
354  * to make sure in the case of overlapping points that the selected is always visible
355  * - Draw handles before keyframes, so that keyframes will overlap handles
356  * (keyframes are more important for users).
357  */
358 
360 
363 
364  /* draw the two handles first (if they're shown, the curve doesn't
365  * have just a single keyframe, and the curve is being edited) */
366  if (do_handles) {
367  draw_fcurve_handle_vertices(fcu, v2d, sel_handle_only, pos);
368  }
369 
370  /* draw keyframes over the handles */
372 
373  GPU_program_point_size(false);
375 }
376 
377 /* Handles ---------------- */
378 
380 {
381  /* don't draw handle lines if handles are not to be shown */
382  if (
383  /* handles shouldn't be shown anywhere */
384  (sipo->flag & SIPO_NOHANDLES) ||
385  /* keyframes aren't editable */
386  (fcu->flag & FCURVE_PROTECTED) ||
387 #if 0 /* handles can still be selected and handle types set, better draw - campbell */
388  /* editing the handles here will cause weird/incorrect interpolation issues */
389  (fcu->flag & FCURVE_INT_VALUES) ||
390 #endif
391  /* group that curve belongs to is not editable */
392  ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
393  /* Do not show handles if there is only 1 keyframe,
394  * otherwise they all clump together in an ugly ball. */
395  (fcu->totvert <= 1)) {
396  return false;
397  }
398  return true;
399 }
400 
401 /* draw lines for F-Curve handles only (this is only done in EditMode)
402  * NOTE: draw_fcurve_handles_check must be checked before running this. */
403 static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
404 {
405  int sel, b;
406 
412  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
413  GPU_line_smooth(true);
414  }
416 
417  immBeginAtMost(GPU_PRIM_LINES, 4 * 2 * fcu->totvert);
418 
419  /* slightly hacky, but we want to draw unselected points before selected ones
420  * so that selected points are clearly visible
421  */
422  for (sel = 0; sel < 2; sel++) {
423  BezTriple *bezt = fcu->bezt, *prevbezt = NULL;
424  int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
425  uchar col[4];
426 
427  for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
428  /* if only selected keyframes can get their handles shown,
429  * check that keyframe is selected
430  */
431  if (sipo->flag & SIPO_SELVHANDLESONLY) {
432  if (BEZT_ISSEL_ANY(bezt) == 0) {
433  continue;
434  }
435  }
436 
437  /* draw handle with appropriate set of colors if selection is ok */
438  if ((bezt->f2 & SELECT) == sel) {
439  /* only draw first handle if previous segment had handles */
440  if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) ||
441  (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
442  UI_GetThemeColor3ubv(basecol + bezt->h1, col);
443  col[3] = fcurve_display_alpha(fcu) * 255;
445  immVertex2fv(pos, bezt->vec[0]);
447  immVertex2fv(pos, bezt->vec[1]);
448  }
449 
450  /* only draw second handle if this segment is bezier */
451  if (bezt->ipo == BEZT_IPO_BEZ) {
452  UI_GetThemeColor3ubv(basecol + bezt->h2, col);
453  col[3] = fcurve_display_alpha(fcu) * 255;
455  immVertex2fv(pos, bezt->vec[1]);
457  immVertex2fv(pos, bezt->vec[2]);
458  }
459  }
460  else {
461  /* only draw first handle if previous segment was had handles, and selection is ok */
462  if (((bezt->f1 & SELECT) == sel) && ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) ||
463  (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)))) {
464  UI_GetThemeColor3ubv(basecol + bezt->h1, col);
465  col[3] = fcurve_display_alpha(fcu) * 255;
467  immVertex2fv(pos, bezt->vec[0]);
469  immVertex2fv(pos, bezt->vec[1]);
470  }
471 
472  /* only draw second handle if this segment is bezier, and selection is ok */
473  if (((bezt->f3 & SELECT) == sel) && (bezt->ipo == BEZT_IPO_BEZ)) {
474  UI_GetThemeColor3ubv(basecol + bezt->h2, col);
475  col[3] = fcurve_display_alpha(fcu) * 255;
477  immVertex2fv(pos, bezt->vec[1]);
479  immVertex2fv(pos, bezt->vec[2]);
480  }
481  }
482  }
483  }
484 
485  immEnd();
488  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
489  GPU_line_smooth(false);
490  }
491 }
492 
493 /* Samples ---------------- */
494 
495 /* helper func - draw sample-range marker for an F-Curve as a cross
496  * NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
497  * have a consistent appearance (due to off-pixel alignments)...
498  */
500  float x, float y, float xscale, float yscale, float hsize, uint pos)
501 {
502  /* adjust view transform before starting */
503  GPU_matrix_push();
505  GPU_matrix_scale_2f(1.0f / xscale * hsize, 1.0f / yscale * hsize);
506 
507  /* draw X shape */
509  immVertex2f(pos, -0.7f, -0.7f);
510  immVertex2f(pos, +0.7f, +0.7f);
511 
512  immVertex2f(pos, -0.7f, +0.7f);
513  immVertex2f(pos, +0.7f, -0.7f);
514  immEnd();
515 
516  /* restore view transform */
517  GPU_matrix_pop();
518 }
519 
520 /* helper func - draw keyframe vertices only for an F-Curve */
521 static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *region, FCurve *fcu)
522 {
523  FPoint *first, *last;
524  float hsize, xscale, yscale;
525 
526  /* get view settings */
528  UI_view2d_scale_get(&region->v2d, &xscale, &yscale);
529 
530  /* get verts */
531  first = fcu->fpt;
532  last = (first) ? (first + (fcu->totvert - 1)) : (NULL);
533 
534  /* draw */
535  if (first && last) {
536  /* anti-aliased lines for more consistent appearance */
537  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
538  GPU_line_smooth(true);
539  }
541 
544 
546 
547  draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize, pos);
548  draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize, pos);
549 
551 
553  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
554  GPU_line_smooth(false);
555  }
556  }
557 }
558 
559 /* Curve ---------------- */
560 
561 /* Helper func - just draw the F-Curve by sampling the visible region
562  * (for drawing curves with modifiers). */
564  ID *id,
565  FCurve *fcu_,
566  View2D *v2d,
567  uint pos,
568  const bool use_nla_remap,
569  const bool draw_extrapolation)
570 {
571  SpaceGraph *sipo = (SpaceGraph *)ac->sl;
572  short mapping_flag = ANIM_get_normalization_flags(ac);
573 
574  /* when opening a blend file on a different sized screen or while dragging the toolbar this can
575  * happen best just bail out in this case. */
576  if (UI_view2d_scale_get_x(v2d) <= 0.0f) {
577  return;
578  }
579 
580  /* disable any drivers */
581  FCurve fcurve_for_draw = *fcu_;
582  fcurve_for_draw.driver = NULL;
583 
584  /* compute unit correction factor */
585  float offset;
586  float unitFac = ANIM_unit_mapping_get_factor(
587  ac->scene, id, &fcurve_for_draw, mapping_flag, &offset);
588 
589  /* Note about sampling frequency:
590  * Ideally, this is chosen such that we have 1-2 pixels = 1 segment
591  * which means that our curves can be as smooth as possible. However,
592  * this does mean that curves may not be fully accurate (i.e. if they have
593  * sudden spikes which happen at the sampling point, we may have problems).
594  * Also, this may introduce lower performance on less densely detailed curves,
595  * though it is impossible to predict this from the modifiers!
596  *
597  * If the automatically determined sampling frequency is likely to cause an infinite
598  * loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value
599  * chosen here is just the coarsest value which still looks reasonable...
600  */
601 
602  /* TODO: perhaps we should have 1.0 frames
603  * as upper limit so that curves don't get too distorted? */
604  float pixels_per_sample = 1.5f;
605  float samplefreq = pixels_per_sample / UI_view2d_scale_get_x(v2d);
606 
607  if (sipo->flag & SIPO_BEAUTYDRAW_OFF) {
608  /* Low Precision = coarse lower-bound clamping
609  *
610  * Although the "Beauty Draw" flag was originally for AA'd
611  * line drawing, the sampling rate here has a much greater
612  * impact on performance (e.g. for T40372)!
613  *
614  * This one still amounts to 10 sample-frames for each 1-frame interval
615  * which should be quite a decent approximation in many situations.
616  */
617  if (samplefreq < 0.1f) {
618  samplefreq = 0.1f;
619  }
620  }
621  else {
622  /* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */
623  if (samplefreq < 0.00001f) {
624  samplefreq = 0.00001f;
625  }
626  }
627 
628  /* the start/end times are simply the horizontal extents of the 'cur' rect */
629  float stime = v2d->cur.xmin;
630  float etime = v2d->cur.xmax;
631 
632  AnimData *adt = use_nla_remap ? BKE_animdata_from_id(id) : NULL;
633 
634  /* If not drawing extrapolation, then change fcurve drawing bounds to its keyframe bounds clamped
635  * by graph editor bounds. */
636  if (!draw_extrapolation) {
637  float fcu_start = 0;
638  float fcu_end = 0;
639  BKE_fcurve_calc_range(fcu_, &fcu_start, &fcu_end, false, false);
640 
641  fcu_start = BKE_nla_tweakedit_remap(adt, fcu_start, NLATIME_CONVERT_MAP);
642  fcu_end = BKE_nla_tweakedit_remap(adt, fcu_end, NLATIME_CONVERT_MAP);
643 
644  /* Account for reversed NLA strip effect. */
645  if (fcu_end < fcu_start) {
646  SWAP(float, fcu_start, fcu_end);
647  }
648 
649  /* Clamp to graph editor rendering bounds. */
650  stime = max_ff(stime, fcu_start);
651  etime = min_ff(etime, fcu_end);
652  }
653 
654  const int total_samples = roundf((etime - stime) / samplefreq);
655  if (total_samples <= 0) {
656  return;
657  }
658 
659  /* NLA remapping is linear so we don't have to remap per iteration. */
660  const float eval_start = BKE_nla_tweakedit_remap(adt, stime, NLATIME_CONVERT_UNMAP);
661  const float eval_freq = BKE_nla_tweakedit_remap(adt, stime + samplefreq, NLATIME_CONVERT_UNMAP) -
662  eval_start;
663  const float eval_end = BKE_nla_tweakedit_remap(adt, etime, NLATIME_CONVERT_UNMAP);
664 
665  immBegin(GPU_PRIM_LINE_STRIP, (total_samples + 1));
666 
667  /* At each sampling interval, add a new vertex.
668  *
669  * Apply the unit correction factor to the calculated values so that the displayed values appear
670  * correctly in the viewport.
671  */
672  for (int i = 0; i < total_samples; i++) {
673  const float ctime = stime + i * samplefreq;
674  float eval_time = eval_start + i * eval_freq;
675 
676  /* Prevent drawing past bounds, due to floating point problems.
677  * User-wise, prevent visual flickering.
678  *
679  * This is to cover the case where:
680  * eval_start + total_samples * eval_freq > eval_end
681  * due to floating point problems.
682  */
683  if (eval_time > eval_end) {
684  eval_time = eval_end;
685  }
686 
687  immVertex2f(pos, ctime, (evaluate_fcurve(&fcurve_for_draw, eval_time) + offset) * unitFac);
688  }
689 
690  /* Ensure we include end boundary point.
691  * User-wise, prevent visual flickering.
692  *
693  * This is to cover the case where:
694  * eval_start + total_samples * eval_freq < eval_end
695  * due to floating point problems.
696  */
697  immVertex2f(pos, etime, (evaluate_fcurve(&fcurve_for_draw, eval_end) + offset) * unitFac);
698 
699  immEnd();
700 }
701 
702 /* helper func - draw a samples-based F-Curve */
704  ID *id,
705  FCurve *fcu,
706  View2D *v2d,
707  const uint shdr_pos,
708  const bool draw_extrapolation)
709 {
710  if (!draw_extrapolation && fcu->totvert == 1) {
711  return;
712  }
713 
714  FPoint *prevfpt = fcu->fpt;
715  FPoint *fpt = prevfpt + 1;
716  float fac, v[2];
717  int b = fcu->totvert;
718  float unit_scale, offset;
719  short mapping_flag = ANIM_get_normalization_flags(ac);
720  int count = fcu->totvert;
721 
722  const bool extrap_left = draw_extrapolation && prevfpt->vec[0] > v2d->cur.xmin;
723  if (extrap_left) {
724  count++;
725  }
726 
727  const bool extrap_right = draw_extrapolation && (prevfpt + b - 1)->vec[0] < v2d->cur.xmax;
728  if (extrap_right) {
729  count++;
730  }
731 
732  /* apply unit mapping */
733  GPU_matrix_push();
734  unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
735  GPU_matrix_scale_2f(1.0f, unit_scale);
737 
739 
740  /* extrapolate to left? - left-side of view comes before first keyframe? */
741  if (extrap_left) {
742  v[0] = v2d->cur.xmin;
743 
744  /* y-value depends on the interpolation */
745  if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
746  (fcu->totvert == 1)) {
747  /* just extend across the first keyframe's value */
748  v[1] = prevfpt->vec[1];
749  }
750  else {
751  /* extrapolate linear doesn't use the handle, use the next points center instead */
752  fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
753  if (fac) {
754  fac = 1.0f / fac;
755  }
756  v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
757  }
758 
759  immVertex2fv(shdr_pos, v);
760  }
761 
762  /* loop over samples, drawing segments */
763  /* draw curve between first and last keyframe (if there are enough to do so) */
764  while (b--) {
765  /* Linear interpolation: just add one point (which should add a new line segment) */
766  immVertex2fv(shdr_pos, prevfpt->vec);
767 
768  /* get next pointers */
769  if (b > 0) {
770  prevfpt++;
771  }
772  }
773 
774  /* extrapolate to right? (see code for left-extrapolation above too) */
775  if (extrap_right) {
776  v[0] = v2d->cur.xmax;
777 
778  /* y-value depends on the interpolation */
779  if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
780  (fcu->totvert == 1)) {
781  /* based on last keyframe's value */
782  v[1] = prevfpt->vec[1];
783  }
784  else {
785  /* extrapolate linear doesn't use the handle, use the previous points center instead */
786  fpt = prevfpt - 1;
787  fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
788  if (fac) {
789  fac = 1.0f / fac;
790  }
791  v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
792  }
793 
794  immVertex2fv(shdr_pos, v);
795  }
796 
797  immEnd();
798 
799  GPU_matrix_pop();
800 }
801 
802 /* helper func - check if the F-Curve only contains easily drawable segments
803  * (i.e. no easing equation interpolations)
804  */
806 {
807  BezTriple *bezt;
808  int i;
809 
810  for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
811  if (ELEM(bezt->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN, BEZT_IPO_BEZ) == false) {
812  return false;
813  }
814  }
815 
816  return true;
817 }
818 
819 /* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
821  bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos, const bool draw_extrapolation)
822 {
823  if (!draw_extrapolation && fcu->totvert == 1) {
824  return;
825  }
826 
827  BezTriple *prevbezt = fcu->bezt;
828  BezTriple *bezt = prevbezt + 1;
829  float v1[2], v2[2], v3[2], v4[2];
830  float *fp, data[120];
831  float fac = 0.0f;
832  int b = fcu->totvert - 1;
833  int resol;
834  float unit_scale, offset;
835  short mapping_flag = ANIM_get_normalization_flags(ac);
836 
837  /* apply unit mapping */
838  GPU_matrix_push();
839  unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
840  GPU_matrix_scale_2f(1.0f, unit_scale);
842 
843  /* For now, this assumes the worst case scenario, where all the keyframes have
844  * bezier interpolation, and are drawn at full res.
845  * This is tricky to optimize, but maybe can be improved at some point... */
846  immBeginAtMost(GPU_PRIM_LINE_STRIP, (b * 32 + 3));
847 
848  /* extrapolate to left? */
849  if (draw_extrapolation && prevbezt->vec[1][0] > v2d->cur.xmin) {
850  /* left-side of view comes before first keyframe, so need to extend as not cyclic */
851  v1[0] = v2d->cur.xmin;
852 
853  /* y-value depends on the interpolation */
854  if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) ||
855  (fcu->totvert == 1)) {
856  /* just extend across the first keyframe's value */
857  v1[1] = prevbezt->vec[1][1];
858  }
859  else if (prevbezt->ipo == BEZT_IPO_LIN) {
860  /* extrapolate linear doesn't use the handle, use the next points center instead */
861  fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
862  if (fac) {
863  fac = 1.0f / fac;
864  }
865  v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
866  }
867  else {
868  /* based on angle of handle 1 (relative to keyframe) */
869  fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
870  if (fac) {
871  fac = 1.0f / fac;
872  }
873  v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
874  }
875 
876  immVertex2fv(pos, v1);
877  }
878 
879  /* if only one keyframe, add it now */
880  if (fcu->totvert == 1) {
881  v1[0] = prevbezt->vec[1][0];
882  v1[1] = prevbezt->vec[1][1];
883  immVertex2fv(pos, v1);
884  }
885 
886  /* draw curve between first and last keyframe (if there are enough to do so) */
887  /* TODO: optimize this to not have to calc stuff out of view too? */
888  while (b--) {
889  if (prevbezt->ipo == BEZT_IPO_CONST) {
890  /* Constant-Interpolation: draw segment between previous keyframe and next,
891  * but holding same value */
892  v1[0] = prevbezt->vec[1][0];
893  v1[1] = prevbezt->vec[1][1];
894  immVertex2fv(pos, v1);
895 
896  v1[0] = bezt->vec[1][0];
897  v1[1] = prevbezt->vec[1][1];
898  immVertex2fv(pos, v1);
899  }
900  else if (prevbezt->ipo == BEZT_IPO_LIN) {
901  /* Linear interpolation: just add one point (which should add a new line segment) */
902  v1[0] = prevbezt->vec[1][0];
903  v1[1] = prevbezt->vec[1][1];
904  immVertex2fv(pos, v1);
905  }
906  else if (prevbezt->ipo == BEZT_IPO_BEZ) {
907  /* Bezier-Interpolation: draw curve as series of segments between keyframes
908  * - resol determines number of points to sample in between keyframes
909  */
910 
911  /* resol depends on distance between points
912  * (not just horizontal) OR is a fixed high res */
913  /* TODO: view scale should factor into this someday too... */
914  if (fcu->driver) {
915  resol = 32;
916  }
917  else {
918  resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
919  }
920 
921  if (resol < 2) {
922  /* only draw one */
923  v1[0] = prevbezt->vec[1][0];
924  v1[1] = prevbezt->vec[1][1];
925  immVertex2fv(pos, v1);
926  }
927  else {
928  /* clamp resolution to max of 32 */
929  /* NOTE: higher values will crash */
930  if (resol > 32) {
931  resol = 32;
932  }
933 
934  v1[0] = prevbezt->vec[1][0];
935  v1[1] = prevbezt->vec[1][1];
936  v2[0] = prevbezt->vec[2][0];
937  v2[1] = prevbezt->vec[2][1];
938 
939  v3[0] = bezt->vec[0][0];
940  v3[1] = bezt->vec[0][1];
941  v4[0] = bezt->vec[1][0];
942  v4[1] = bezt->vec[1][1];
943 
944  BKE_fcurve_correct_bezpart(v1, v2, v3, v4);
945 
946  BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float[3]));
948  v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float[3]));
949 
950  for (fp = data; resol; resol--, fp += 3) {
951  immVertex2fv(pos, fp);
952  }
953  }
954  }
955 
956  /* get next pointers */
957  prevbezt = bezt;
958  bezt++;
959 
960  /* last point? */
961  if (b == 0) {
962  v1[0] = prevbezt->vec[1][0];
963  v1[1] = prevbezt->vec[1][1];
964  immVertex2fv(pos, v1);
965  }
966  }
967 
968  /* extrapolate to right? (see code for left-extrapolation above too) */
969  if (draw_extrapolation && prevbezt->vec[1][0] < v2d->cur.xmax) {
970  v1[0] = v2d->cur.xmax;
971 
972  /* y-value depends on the interpolation */
973  if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
974  (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
975  /* based on last keyframe's value */
976  v1[1] = prevbezt->vec[1][1];
977  }
978  else if (prevbezt->ipo == BEZT_IPO_LIN) {
979  /* extrapolate linear doesn't use the handle, use the previous points center instead */
980  bezt = prevbezt - 1;
981  fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
982  if (fac) {
983  fac = 1.0f / fac;
984  }
985  v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
986  }
987  else {
988  /* based on angle of handle 1 (relative to keyframe) */
989  fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
990  if (fac) {
991  fac = 1.0f / fac;
992  }
993  v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
994  }
995 
996  immVertex2fv(pos, v1);
997  }
998 
999  immEnd();
1000 
1001  GPU_matrix_pop();
1002 }
1003 
1004 static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAnimListElem *ale)
1005 {
1006  FCurve *fcu = (FCurve *)ale->key_data;
1008  AnimData *adt = ANIM_nla_mapping_get(ac, ale);
1009 
1010  /* map keyframes for drawing if scaled F-Curve */
1011  if (adt) {
1012  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
1013  }
1014 
1015  /* draw curve:
1016  * - curve line may be result of one or more destructive modifiers or just the raw data,
1017  * so we need to check which method should be used
1018  * - controls from active modifier take precedence over keyframes
1019  * (XXX! editing tools need to take this into account!)
1020  */
1021 
1022  /* 1) draw curve line */
1023  if (((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) ||
1024  (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert))) {
1025  /* set color/drawing style for curve itself */
1026  /* draw active F-Curve thicker than the rest to make it stand out */
1027  if (fcu->flag & FCURVE_ACTIVE) {
1028  GPU_line_width(2.5);
1029  }
1030  else {
1031  GPU_line_width(1.0);
1032  }
1033 
1034  /* anti-aliased lines for less jagged appearance */
1035  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
1036  GPU_line_smooth(true);
1037  }
1039 
1040  const uint shdr_pos = GPU_vertformat_attr_add(
1042 
1043  float viewport_size[4];
1044  GPU_viewport_size_get_f(viewport_size);
1045 
1046  if (BKE_fcurve_is_protected(fcu)) {
1047  /* Protected curves (non editable) are drawn with dotted lines. */
1049  immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
1050  immUniform1i("colors_len", 0); /* Simple dashes. */
1051  immUniform1f("dash_width", 4.0f);
1052  immUniform1f("dash_factor", 0.5f);
1053  }
1054  else {
1056  immUniform2fv("viewportSize", &viewport_size[2]);
1057  immUniform1f("lineWidth", GPU_line_width_get());
1058  }
1059 
1060  if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) {
1061  /* muted curves are drawn in a grayish hue */
1062  /* XXX should we have some variations? */
1064  }
1065  else {
1066  /* set whatever color the curve has set
1067  * - unselected curves draw less opaque to help distinguish the selected ones
1068  */
1070  }
1071 
1072  const bool draw_extrapolation = (sipo->flag & SIPO_NO_DRAW_EXTRAPOLATION) == 0;
1073  /* draw F-Curve */
1074  if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) {
1075  /* draw a curve affected by modifiers or only allowed to have integer values
1076  * by sampling it at various small-intervals over the visible region
1077  */
1078  if (adt) {
1085  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, true, false);
1086  draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, true, draw_extrapolation);
1087  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, false, false);
1088  }
1089  else {
1090  draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, false, draw_extrapolation);
1091  }
1092  }
1093  else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
1094  /* just draw curve based on defined data (i.e. no modifiers) */
1095  if (fcu->bezt) {
1097  draw_fcurve_curve_bezts(ac, ale->id, fcu, &region->v2d, shdr_pos, draw_extrapolation);
1098  }
1099  else {
1100  draw_fcurve_curve(ac, ale->id, fcu, &region->v2d, shdr_pos, false, draw_extrapolation);
1101  }
1102  }
1103  else if (fcu->fpt) {
1104  draw_fcurve_curve_samples(ac, ale->id, fcu, &region->v2d, shdr_pos, draw_extrapolation);
1105  }
1106  }
1107 
1108  immUnbindProgram();
1109 
1110  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
1111  GPU_line_smooth(false);
1112  }
1114  }
1115 
1116  /* 2) draw handles and vertices as appropriate based on active
1117  * - If the option to only show controls if the F-Curve is selected is enabled,
1118  * we must obey this.
1119  */
1120  if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) {
1121  if (!BKE_fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) {
1122  /* only draw controls if this is the active modifier */
1123  if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
1124  switch (fcm->type) {
1125  case FMODIFIER_TYPE_ENVELOPE: /* envelope */
1126  draw_fcurve_modifier_controls_envelope(fcm, &region->v2d, adt);
1127  break;
1128  }
1129  }
1130  }
1131  else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
1132  short mapping_flag = ANIM_get_normalization_flags(ac);
1133  float offset;
1134  float unit_scale = ANIM_unit_mapping_get_factor(
1135  ac->scene, ale->id, fcu, mapping_flag, &offset);
1136 
1137  /* apply unit-scaling to all values via OpenGL */
1138  GPU_matrix_push();
1139  GPU_matrix_scale_2f(1.0f, unit_scale);
1141 
1142  /* Set this once and for all -
1143  * all handles and handle-verts should use the same thickness. */
1144  GPU_line_width(1.0);
1145 
1146  if (fcu->bezt) {
1147  bool do_handles = draw_fcurve_handles_check(sipo, fcu);
1148 
1149  if (do_handles) {
1150  /* only draw handles/vertices on keyframes */
1151  draw_fcurve_handles(sipo, fcu);
1152  }
1153 
1154  draw_fcurve_vertices(region, fcu, do_handles, (sipo->flag & SIPO_SELVHANDLESONLY));
1155  }
1156  else {
1157  /* samples: only draw two indicators at either end as indicators */
1158  draw_fcurve_samples(sipo, region, fcu);
1159  }
1160 
1161  GPU_matrix_pop();
1162  }
1163  }
1164 
1165  /* 3) draw driver debugging stuff */
1166  if ((ac->datatype == ANIMCONT_DRIVERS) && (fcu->flag & FCURVE_ACTIVE)) {
1167  graph_draw_driver_debug(ac, ale->id, fcu);
1168  }
1169 
1170  /* undo mapping of keyframes for drawing if scaled F-Curve */
1171  if (adt) {
1172  ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 0);
1173  }
1174 }
1175 
1176 /* Debugging -------------------------------- */
1177 
1178 /* Draw indicators which show the value calculated from the driver,
1179  * and how this is mapped to the value that comes out of it. This
1180  * is handy for helping users better understand how to interpret
1181  * the graphs, and also facilitates debugging.
1182  */
1183 static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
1184 {
1185  ChannelDriver *driver = fcu->driver;
1186  View2D *v2d = &ac->region->v2d;
1187  short mapping_flag = ANIM_get_normalization_flags(ac);
1188  float offset;
1189  float unitfac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
1190 
1191  const uint shdr_pos = GPU_vertformat_attr_add(
1194 
1195  float viewport_size[4];
1196  GPU_viewport_size_get_f(viewport_size);
1197  immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
1198 
1199  immUniform1i("colors_len", 0); /* Simple dashes. */
1200 
1201  /* No curve to modify/visualize the result?
1202  * => We still want to show the 1-1 default...
1203  */
1204  if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) {
1205  float t;
1206 
1207  /* draw with thin dotted lines in style of what curve would have been */
1208  immUniformColor3fv(fcu->color);
1209 
1210  immUniform1f("dash_width", 40.0f);
1211  immUniform1f("dash_factor", 0.5f);
1212  GPU_line_width(2.0f);
1213 
1214  /* draw 1-1 line, stretching just past the screen limits
1215  * NOTE: we need to scale the y-values to be valid for the units
1216  */
1218 
1219  t = v2d->cur.xmin;
1220  immVertex2f(shdr_pos, t, (t + offset) * unitfac);
1221 
1222  t = v2d->cur.xmax;
1223  immVertex2f(shdr_pos, t, (t + offset) * unitfac);
1224 
1225  immEnd();
1226  }
1227 
1228  /* draw driver only if actually functional */
1229  if ((driver->flag & DRIVER_FLAG_INVALID) == 0) {
1230  /* grab "coordinates" for driver outputs */
1231  float x = driver->curval;
1232  float y = fcu->curval * unitfac;
1233 
1234  /* Only draw indicators if the point is in range. */
1235  if (x >= v2d->cur.xmin) {
1236  float co[2];
1237 
1238  /* draw dotted lines leading towards this point from both axes ....... */
1239  immUniformColor3f(0.9f, 0.9f, 0.9f);
1240  immUniform1f("dash_width", 10.0f);
1241  immUniform1f("dash_factor", 0.5f);
1242  GPU_line_width(1.0f);
1243 
1244  immBegin(GPU_PRIM_LINES, (y <= v2d->cur.ymax) ? 4 : 2);
1245 
1246  /* x-axis lookup */
1247  co[0] = x;
1248 
1249  if (y <= v2d->cur.ymax) {
1250  co[1] = v2d->cur.ymax + 1.0f;
1251  immVertex2fv(shdr_pos, co);
1252 
1253  co[1] = y;
1254  immVertex2fv(shdr_pos, co);
1255  }
1256 
1257  /* y-axis lookup */
1258  co[1] = y;
1259 
1260  co[0] = v2d->cur.xmin - 1.0f;
1261  immVertex2fv(shdr_pos, co);
1262 
1263  co[0] = x;
1264  immVertex2fv(shdr_pos, co);
1265 
1266  immEnd();
1267 
1268  immUnbindProgram();
1269 
1270  /* GPU_PRIM_POINTS do not survive dashed line geometry shader... */
1272 
1273  /* x marks the spot .................................................... */
1274  /* -> outer frame */
1275  immUniformColor3f(0.9f, 0.9f, 0.9f);
1276  GPU_point_size(7.0);
1277 
1279  immVertex2f(shdr_pos, x, y);
1280  immEnd();
1281 
1282  /* inner frame */
1283  immUniformColor3f(0.9f, 0.0f, 0.0f);
1284  GPU_point_size(3.0);
1285 
1287  immVertex2f(shdr_pos, x, y);
1288  immEnd();
1289  }
1290  }
1291 
1292  immUnbindProgram();
1293 }
1294 
1295 /* Public Curve-Drawing API ---------------- */
1296 
1298 {
1299  FCurve *fcu;
1300 
1301  /* draw with thick dotted lines */
1302  GPU_line_width(3.0f);
1303 
1304  /* anti-aliased lines for less jagged appearance */
1305  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
1306  GPU_line_smooth(true);
1307  }
1309 
1310  const uint shdr_pos = GPU_vertformat_attr_add(
1312 
1314 
1315  float viewport_size[4];
1316  GPU_viewport_size_get_f(viewport_size);
1317  immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
1318 
1319  immUniform1i("colors_len", 0); /* Simple dashes. */
1320  immUniform1f("dash_width", 20.0f);
1321  immUniform1f("dash_factor", 0.5f);
1322 
1323  const bool draw_extrapolation = (sipo->flag & SIPO_NO_DRAW_EXTRAPOLATION) == 0;
1324  /* the ghost curves are simply sampled F-Curves stored in sipo->runtime.ghost_curves */
1325  for (fcu = sipo->runtime.ghost_curves.first; fcu; fcu = fcu->next) {
1326  /* set whatever color the curve has set
1327  * - this is set by the function which creates these
1328  * - draw with a fixed opacity of 2
1329  */
1330  immUniformColor3fvAlpha(fcu->color, 0.5f);
1331 
1332  /* simply draw the stored samples */
1333  draw_fcurve_curve_samples(ac, NULL, fcu, &region->v2d, shdr_pos, draw_extrapolation);
1334  }
1335 
1336  immUnbindProgram();
1337 
1338  if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) {
1339  GPU_line_smooth(false);
1340  }
1342 }
1343 
1344 void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, short sel)
1345 {
1346  ListBase anim_data = {NULL, NULL};
1347  bAnimListElem *ale;
1348  int filter;
1349 
1350  /* build list of curves to draw */
1352  filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL));
1353  ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1354 
1355  /* for each curve:
1356  * draw curve, then handle-lines, and finally vertices in this order so that
1357  * the data will be layered correctly
1358  */
1359  bAnimListElem *ale_active_fcurve = NULL;
1360  for (ale = anim_data.first; ale; ale = ale->next) {
1361  const FCurve *fcu = (FCurve *)ale->key_data;
1362  if (fcu->flag & FCURVE_ACTIVE) {
1363  ale_active_fcurve = ale;
1364  continue;
1365  }
1366  draw_fcurve(ac, sipo, region, ale);
1367  }
1368 
1369  /* Draw the active FCurve last so that it (especially the active keyframe)
1370  * shows on top of the other curves. */
1371  if (ale_active_fcurve != NULL) {
1372  draw_fcurve(ac, sipo, region, ale_active_fcurve);
1373  }
1374 
1375  /* free list of curves */
1376  ANIM_animdata_freelist(&anim_data);
1377 }
1378 
1381 /* -------------------------------------------------------------------- */
1386 {
1387  ListBase anim_data = {NULL, NULL};
1388  bAnimListElem *ale;
1389  int filter;
1390 
1391  View2D *v2d = &region->v2d;
1392  float height;
1393  size_t items;
1394 
1395  /* build list of channels to draw */
1398  items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1399 
1400  /* Update max-extent of channels here (taking into account scrollers):
1401  * - this is done to allow the channel list to be scrollable, but must be done here
1402  * to avoid regenerating the list again and/or also because channels list is drawn first */
1403  height = ACHANNEL_TOT_HEIGHT(ac, items);
1404  v2d->tot.ymin = -height;
1405 
1406  /* Loop through channels, and set up drawing depending on their type. */
1407  { /* first pass: just the standard GL-drawing for backdrop + text */
1408  size_t channel_index = 0;
1409  float ymax = ACHANNEL_FIRST_TOP(ac);
1410 
1411  for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
1412  float ymin = ymax - ACHANNEL_HEIGHT(ac);
1413 
1414  /* check if visible */
1415  if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
1416  IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
1417  /* draw all channels using standard channel-drawing API */
1418  ANIM_channel_draw(ac, ale, ymin, ymax, channel_index);
1419  }
1420  }
1421  }
1422  { /* second pass: widgets */
1423  uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
1424  size_t channel_index = 0;
1425  float ymax = ACHANNEL_FIRST_TOP(ac);
1426 
1427  /* set blending again, as may not be set in previous step */
1429 
1430  for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
1431  float ymin = ymax - ACHANNEL_HEIGHT(ac);
1432 
1433  /* check if visible */
1434  if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
1435  IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
1436  /* draw all channels using standard channel-drawing API */
1437  rctf channel_rect;
1438  BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax - V2D_SCROLL_WIDTH, ymin, ymax);
1439  ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
1440  }
1441  }
1442 
1443  UI_block_end(C, block);
1444  UI_block_draw(C, block);
1445 
1447  }
1448 
1449  /* free tempolary channels */
1450  ANIM_animdata_freelist(&anim_data);
1451 }
1452 
Blender kernel action and pose functionality.
struct AnimData * BKE_animdata_from_id(const struct ID *id)
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.cc:1717
float evaluate_fcurve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2135
struct FModifier * find_active_fmodifier(ListBase *modifiers)
Definition: fmodifier.c:1246
bool BKE_fcurve_are_keyframes_usable(struct FCurve *fcu)
Definition: fcurve.c:903
bool BKE_fcurve_is_protected(struct FCurve *fcu)
Definition: fcurve.c:963
int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu)
bool BKE_fcurve_calc_range(struct FCurve *fcu, float *min, float *max, bool do_sel_only, bool do_min_length)
Definition: fcurve.c:754
void BKE_fcurve_correct_bezpart(const float v1[2], float v2[2], float v3[2], const float v4[2])
Definition: fcurve.c:1410
@ 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
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition: rct.c:407
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition: BLI_rect.h:194
unsigned char uchar
Definition: BLI_sys_types.h:70
unsigned int uint
Definition: BLI_sys_types.h:67
#define SWAP(type, a, b)
#define IN_RANGE(a, b, c)
#define ELEM(...)
@ AGRP_PROTECTED
@ AGRP_MUTED
@ FMODIFIER_TYPE_ENVELOPE
@ DRIVER_FLAG_INVALID
#define FCURVE_ACTIVE_KEYFRAME_NONE
@ FCURVE_MUTED
@ FCURVE_INT_VALUES
@ FCURVE_ACTIVE
@ FCURVE_SELECTED
@ FCURVE_PROTECTED
@ FCURVE_EXTRAPOLATE_CONSTANT
#define BEZT_ISSEL_ANY(bezt)
@ BEZT_IPO_CONST
@ BEZT_IPO_BEZ
@ BEZT_IPO_LIN
@ SIPO_SELCUVERTSONLY
@ SIPO_SELVHANDLESONLY
@ SIPO_NO_DRAW_EXTRAPOLATION
@ SIPO_NOHANDLES
@ SIPO_BEAUTYDRAW_OFF
#define ACHANNEL_HEIGHT(ac)
Definition: ED_anim_api.h:440
#define ACHANNEL_FIRST_TOP(ac)
Definition: ED_anim_api.h:438
@ ANIMCONT_DRIVERS
Definition: ED_anim_api.h:109
#define ACHANNEL_STEP(ac)
Definition: ED_anim_api.h:442
#define ACHANNEL_TOT_HEIGHT(ac, item_amount)
Definition: ED_anim_api.h:444
@ ANIMFILTER_UNSEL
Definition: ED_anim_api.h:309
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:292
@ ANIMFILTER_CURVE_VISIBLE
Definition: ED_anim_api.h:297
@ ANIMFILTER_LIST_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:300
@ ANIMFILTER_FCURVESONLY
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:308
void immUniform4f(const char *name, float x, float y, float z, float w)
void immUniform2fv(const char *name, const float data[2])
void immUniform2f(const char *name, float x, float y)
void immAttr4ubv(uint attr_id, const unsigned char data[4])
void immUnbindProgram(void)
void immVertex2f(uint attr_id, float x, float y)
void immUniformThemeColor(int color_id)
void immUniformThemeColorShade(int color_id, int offset)
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
void immVertex2fv(uint attr_id, const float data[2])
void immUniform1i(const char *name, int x)
void immBeginAtMost(GPUPrimType, uint max_vertex_len)
void immUniform1f(const char *name, float x)
void immUniformColor4fv(const float rgba[4])
GPUVertFormat * immVertexFormat(void)
void immUniformColor3f(float r, float g, float b)
void immUniform4fv(const char *name, const float data[4])
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fvAlpha(const float rgb[3], float a)
void immEnd(void)
void immUniformColor3fv(const float rgb[3])
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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 y
_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
_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 v1
void GPU_matrix_pop(void)
Definition: gpu_matrix.cc:126
void GPU_matrix_scale_2f(float x, float y)
Definition: gpu_matrix.cc:216
void GPU_matrix_push(void)
Definition: gpu_matrix.cc:119
void GPU_matrix_translate_2f(float x, float y)
Definition: gpu_matrix.cc:174
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:22
@ GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR
Definition: GPU_shader.h:349
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
Definition: GPU_shader.h:253
@ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA
Definition: GPU_shader.h:310
@ GPU_SHADER_2D_UNIFORM_COLOR
Definition: GPU_shader.h:201
@ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA
Definition: GPU_shader.h:321
@ GPU_SHADER_2D_FLAT_COLOR
Definition: GPU_shader.h:208
void GPU_program_point_size(bool enable)
Definition: gpu_state.cc:172
@ GPU_BLEND_NONE
Definition: GPU_state.h:60
@ GPU_BLEND_ALPHA
Definition: GPU_state.h:62
void GPU_blend(eGPUBlend blend)
Definition: gpu_state.cc:39
void GPU_line_width(float width)
Definition: gpu_state.cc:158
float GPU_line_width_get(void)
Definition: gpu_state.cc:248
void GPU_line_smooth(bool enable)
Definition: gpu_state.cc:75
void GPU_point_size(float size)
Definition: gpu_state.cc:164
void GPU_viewport_size_get_f(float coords[4])
Definition: gpu_state.cc:259
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_U8
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
#define C
Definition: RandGen.cpp:25
@ UI_EMBOSS
Definition: UI_interface.h:108
void UI_block_end(const struct bContext *C, uiBlock *block)
void UI_block_draw(const struct bContext *C, struct uiBlock *block)
#define UI_DPI_FAC
Definition: UI_interface.h:305
uiBlock * UI_block_begin(const struct bContext *C, struct ARegion *region, const char *name, eUIEmbossType emboss)
void UI_GetThemeColor3fv(int colorid, float col[3])
Definition: resources.c:1165
@ TH_HEADER
Definition: UI_resources.h:50
@ TH_VERTEX_ACTIVE
Definition: UI_resources.h:79
@ TH_HANDLE_VERTEX_SIZE
Definition: UI_resources.h:206
@ TH_VERTEX
Definition: UI_resources.h:77
@ TH_VERTEX_SIZE
Definition: UI_resources.h:81
@ TH_HANDLE_SEL_FREE
Definition: UI_resources.h:114
@ TH_HANDLE_VERTEX_SELECT
Definition: UI_resources.h:205
@ TH_HANDLE_VERTEX
Definition: UI_resources.h:204
@ TH_VERTEX_SELECT
Definition: UI_resources.h:78
@ TH_HANDLE_FREE
Definition: UI_resources.h:109
@ TH_TEXT
Definition: UI_resources.h:42
@ TH_TEXT_HI
Definition: UI_resources.h:43
void UI_GetThemeColor3ubv(int colorid, unsigned char col[3])
Definition: resources.c:1323
void UI_GetThemeColor4fv(int colorid, float col[4])
Definition: resources.c:1173
float UI_GetThemeValuef(int colorid)
Definition: resources.c:1141
void UI_view2d_scale_get(const struct View2D *v2d, float *r_x, float *r_y)
#define V2D_SCROLL_WIDTH
Definition: UI_view2d.h:55
float UI_view2d_scale_get_x(const struct View2D *v2d)
void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, rctf *rect, size_t channel_index)
void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index)
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:397
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
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3447
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
unsigned int U
Definition: btGjkEpa3.h:78
#define SELECT
SyclQueue void void size_t num_bytes void
uint pos
uint col
static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize, uint pos)
Definition: graph_draw.c:499
void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
Definition: graph_draw.c:1385
static bool draw_fcurve_handles_check(SpaceGraph *sipo, FCurve *fcu)
Definition: graph_draw.c:379
static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos, const bool draw_extrapolation)
Definition: graph_draw.c:820
static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu_, View2D *v2d, uint pos, const bool use_nla_remap, const bool draw_extrapolation)
Definition: graph_draw.c:563
static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
Definition: graph_draw.c:1183
static void draw_fcurve_active_handle_vertices(const FCurve *fcu, const bool sel_handle_only, const uint pos)
Definition: graph_draw.c:296
static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool sel, bool sel_handle_only, uint pos)
Definition: graph_draw.c:248
static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d, AnimData *adt_nla_remap)
Definition: graph_draw.c:69
static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, uint pos)
Definition: graph_draw.c:234
static void set_fcurve_vertex_color(FCurve *fcu, bool sel)
Definition: graph_draw.c:145
void graph_draw_ghost_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region)
Definition: graph_draw.c:1297
static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, uint pos)
Definition: graph_draw.c:329
static void draw_fcurve_vertices(ARegion *region, FCurve *fcu, bool do_handles, bool sel_handle_only)
Definition: graph_draw.c:345
static void draw_fcurve_samples(SpaceGraph *sipo, ARegion *region, FCurve *fcu)
Definition: graph_draw.c:521
static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, const uint shdr_pos, const bool draw_extrapolation)
Definition: graph_draw.c:703
static float fcurve_display_alpha(FCurve *fcu)
Definition: graph_draw.c:52
static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, bool sel, uint pos)
Definition: graph_draw.c:171
static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
Definition: graph_draw.c:805
static void draw_fcurve_active_vertex(const FCurve *fcu, const View2D *v2d, const uint pos)
Definition: graph_draw.c:210
static void draw_fcurve(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, bAnimListElem *ale)
Definition: graph_draw.c:1004
void graph_draw_curves(bAnimContext *ac, SpaceGraph *sipo, ARegion *region, short sel)
Definition: graph_draw.c:1344
static void draw_fcurve_handles(SpaceGraph *sipo, FCurve *fcu)
Definition: graph_draw.c:403
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
format
Definition: logImageCore.h:38
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
uint8_t h1
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
uint8_t h2
struct FCurve * next
bActionGroup * grp
float curval
FPoint * fpt
ChannelDriver * driver
BezTriple * bezt
float color[3]
short extend
short flag
unsigned int totvert
ListBase modifiers
FCM_EnvelopeData * data
void * data
float vec[2]
Definition: DNA_ID.h:368
void * first
Definition: DNA_listBase.h:31
SpaceGraph_Runtime runtime
struct ARegion * region
Definition: ED_anim_api.h:76
struct Scene * scene
Definition: ED_anim_api.h:84
short datatype
Definition: ED_anim_api.h:62
void * data
Definition: ED_anim_api.h:60
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
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70