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