84
84
/* Envelope -------------- */
86
// TODO: draw a shaded poly showing the region of influence too!!!
87
static void draw_fcurve_modifier_controls_envelope (FModifier *fcm, View2D *v2d)
86
/* TODO: draw a shaded poly showing the region of influence too!!! */
87
static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
89
FMod_Envelope *env= (FMod_Envelope *)fcm->data;
89
FMod_Envelope *env = (FMod_Envelope *)fcm->data;
90
90
FCM_EnvelopeData *fed;
91
const float fac= 0.05f * (v2d->cur.xmax - v2d->cur.xmin);
91
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
94
94
/* draw two black lines showing the standard reference levels */
99
glVertex2f(v2d->cur.xmin, env->midval+env->min);
100
glVertex2f(v2d->cur.xmax, env->midval+env->min);
99
glVertex2f(v2d->cur.xmin, env->midval + env->min);
100
glVertex2f(v2d->cur.xmax, env->midval + env->min);
102
glVertex2f(v2d->cur.xmin, env->midval+env->max);
103
glVertex2f(v2d->cur.xmax, env->midval+env->max);
102
glVertex2f(v2d->cur.xmin, env->midval + env->max);
103
glVertex2f(v2d->cur.xmax, env->midval + env->max);
104
glEnd(); /* GL_LINES */
107
107
/* set size of vertices (non-adjustable for now) */
108
108
glPointSize(2.0f);
110
// for now, point color is fixed, and is white
110
/* for now, point color is fixed, and is white */
111
111
glColor3f(1.0f, 1.0f, 1.0f);
113
113
/* we use bgl points not standard gl points, to workaround vertex
114
114
* drawing bugs that some drivers have (probably legacy ones only though)
116
116
bglBegin(GL_POINTS);
117
for (i=0, fed=env->data; i < env->totvert; i++, fed++) {
117
for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
118
118
/* only draw if visible
119
119
* - min/max here are fixed, not relative
134
134
/* Points ---------------- */
136
136
/* helper func - draw keyframe vertices only for an F-Curve */
137
static void draw_fcurve_vertices_keyframes (FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel)
137
static void draw_fcurve_vertices_keyframes(FCurve *fcu, SpaceIpo *UNUSED(sipo), View2D *v2d, short edit, short sel)
139
BezTriple *bezt= fcu->bezt;
140
const float fac= 0.05f * (v2d->cur.xmax - v2d->cur.xmin);
139
BezTriple *bezt = fcu->bezt;
140
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
143
143
/* we use bgl points not standard gl points, to workaround vertex
174
174
* NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
175
175
* have a consistent appearance (due to off-pixel alignments)...
177
static void draw_fcurve_handle_control (float x, float y, float xscale, float yscale, float hsize)
177
static void draw_fcurve_handle_control(float x, float y, float xscale, float yscale, float hsize)
179
static GLuint displist=0;
179
static GLuint displist = 0;
181
181
/* initialize round circle shape */
182
182
if (displist == 0) {
183
183
GLUquadricObj *qobj;
185
displist= glGenLists(1);
185
displist = glGenLists(1);
186
186
glNewList(displist, GL_COMPILE);
188
qobj = gluNewQuadric();
188
qobj = gluNewQuadric();
189
189
gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
190
190
gluDisk(qobj, 0, 0.7, 8, 1);
191
191
gluDeleteQuadric(qobj);
196
196
/* adjust view transform before starting */
197
197
glTranslatef(x, y, 0.0f);
198
glScalef(1.0f/xscale*hsize, 1.0f/yscale*hsize, 1.0f);
198
glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
201
201
glCallList(displist);
203
203
/* restore view transform */
204
glScalef(xscale/hsize, yscale/hsize, 1.0);
204
glScalef(xscale / hsize, yscale / hsize, 1.0);
205
205
glTranslatef(-x, -y, 0.0f);
208
208
/* helper func - draw handle vertices only for an F-Curve (if it is not protected) */
209
static void draw_fcurve_vertices_handles (FCurve *fcu, SpaceIpo *sipo, View2D *v2d, short sel, short sel_handle_only)
209
static void draw_fcurve_vertices_handles(FCurve *fcu, SpaceIpo *sipo, View2D *v2d, short sel, short sel_handle_only)
211
BezTriple *bezt= fcu->bezt;
211
BezTriple *bezt = fcu->bezt;
212
212
BezTriple *prevbezt = NULL;
213
213
float hsize, xscale, yscale;
216
216
/* get view settings */
217
hsize= UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
217
hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE);
218
218
UI_view2d_getscale(v2d, &xscale, &yscale);
220
220
/* set handle color */
222
222
else UI_ThemeColor(TH_HANDLE_VERTEX);
224
224
/* anti-aliased lines for more consistent appearance */
225
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF)==0) glEnable(GL_LINE_SMOOTH);
225
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
226
226
glEnable(GL_BLEND);
228
for (i=0; i < fcu->totvert; i++, prevbezt=bezt, bezt++) {
228
for (i = 0; i < fcu->totvert; i++, prevbezt = bezt, bezt++) {
229
229
/* Draw the editmode handles for a bezier curve (others don't have handles)
230
230
* if their selection status matches the selection status we're drawing for
231
231
* - first handle only if previous beztriple was bezier-mode
234
234
* Also, need to take into account whether the keyframe was selected
235
235
* if a Graph Editor option to only show handles of selected keys is on.
237
if ( !sel_handle_only || BEZSELECTED(bezt) ) {
238
if ( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) {
239
if ((bezt->f1 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
237
if (!sel_handle_only || BEZSELECTED(bezt) ) {
238
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
239
if ((bezt->f1 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[0][0] < v2d->cur.xmax)*/
240
240
draw_fcurve_handle_control(bezt->vec[0][0], bezt->vec[0][1], xscale, yscale, hsize);
243
if (bezt->ipo==BEZT_IPO_BEZ) {
244
if ((bezt->f3 & SELECT) == sel)/* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
243
if (bezt->ipo == BEZT_IPO_BEZ) {
244
if ((bezt->f3 & SELECT) == sel) /* && v2d->cur.xmin < bezt->vec[2][0] < v2d->cur.xmax)*/
245
245
draw_fcurve_handle_control(bezt->vec[2][0], bezt->vec[2][1], xscale, yscale, hsize);
250
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF)==0) glDisable(GL_LINE_SMOOTH);
250
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
251
251
glDisable(GL_BLEND);
254
254
/* helper func - set color to draw F-Curve data with */
255
static void set_fcurve_vertex_color (FCurve *fcu, short sel)
255
static void set_fcurve_vertex_color(FCurve *fcu, short sel)
257
257
/* Fade the 'intensity' of the vertices based on the selection of the curves too */
258
int alphaOffset= (int)((fcurve_display_alpha(fcu) - 1.0f) * 255);
258
int alphaOffset = (int)((fcurve_display_alpha(fcu) - 1.0f) * 255);
260
260
/* Set color of curve vertex based on state of curve (i.e. 'Edit' Mode) */
261
if ((fcu->flag & FCURVE_PROTECTED)==0) {
261
if ((fcu->flag & FCURVE_PROTECTED) == 0) {
262
262
/* Curve's points ARE BEING edited */
263
263
if (sel) UI_ThemeColorShadeAlpha(TH_VERTEX_SELECT, 0, alphaOffset);
264
264
else UI_ThemeColorShadeAlpha(TH_VERTEX, 0, alphaOffset);
267
267
/* Curve's points CANNOT BE edited */
268
268
if (sel) UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, alphaOffset);
274
static void draw_fcurve_vertices (SpaceIpo *sipo, ARegion *ar, FCurve *fcu, short do_handles, short sel_handle_only)
274
static void draw_fcurve_vertices(SpaceIpo *sipo, ARegion *ar, FCurve *fcu, short do_handles, short sel_handle_only)
276
View2D *v2d= &ar->v2d;
276
View2D *v2d = &ar->v2d;
278
278
/* only draw points if curve is visible
279
* - draw unselected points before selected points as separate passes to minimise color-changing overhead
279
* - draw unselected points before selected points as separate passes to minimize color-changing overhead
280
280
* (XXX dunno if this is faster than drawing all in one pass though)
281
* and also to make sure in the case of overlapping points that the selected is always visible
281
* and also to make sure in the case of overlapping points that the selected is always visible
282
282
* - draw handles before keyframes, so that keyframes will overlap handles (keyframes are more important for users)
308
308
static int draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu)
310
310
/* don't draw handle lines if handles are not to be shown */
311
if ( (sipo->flag & SIPO_NOHANDLES) || /* handles shouldn't be shown anywhere */
312
(fcu->flag & FCURVE_PROTECTED) || /* keyframes aren't editable */
313
#if 0 /* handles can still be selected and handle types set, better draw - campbell */
314
(fcu->flag & FCURVE_INT_VALUES) || /* editing the handles here will cause weird/incorrect interpolation issues */
311
if ( (sipo->flag & SIPO_NOHANDLES) || /* handles shouldn't be shown anywhere */
312
(fcu->flag & FCURVE_PROTECTED) || /* keyframes aren't editable */
313
#if 0 /* handles can still be selected and handle types set, better draw - campbell */
314
(fcu->flag & FCURVE_INT_VALUES) || /* editing the handles here will cause weird/incorrect interpolation issues */
316
((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || /* group that curve belongs to is not editable */
317
(fcu->totvert <= 1) /* do not show handles if there is only 1 keyframe, otherwise they all clump together in an ugly ball */
316
((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || /* group that curve belongs to is not editable */
317
(fcu->totvert <= 1) /* do not show handles if there is only 1 keyframe, otherwise they all clump together in an ugly ball */
339
339
/* slightly hacky, but we want to draw unselected points before selected ones
340
340
* so that selected points are clearly visible
342
for (sel= 0; sel < 2; sel++) {
343
BezTriple *bezt=fcu->bezt, *prevbezt=NULL;
344
int basecol= (sel)? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
342
for (sel = 0; sel < 2; sel++) {
343
BezTriple *bezt = fcu->bezt, *prevbezt = NULL;
344
int basecol = (sel) ? TH_HANDLE_SEL_FREE : TH_HANDLE_FREE;
346
346
unsigned char col[4];
348
for (b= 0; b < fcu->totvert; b++, prevbezt=bezt, bezt++) {
348
for (b = 0; b < fcu->totvert; b++, prevbezt = bezt, bezt++) {
349
349
/* if only selected keyframes can get their handles shown,
350
350
* check that keyframe is selected
357
357
/* draw handle with appropriate set of colors if selection is ok */
358
if ((bezt->f2 & SELECT)==sel) {
358
if ((bezt->f2 & SELECT) == sel) {
361
361
/* only draw first handle if previous segment had handles */
362
if ((!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ))) {
362
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
363
363
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
364
col[3]= fcurve_display_alpha(fcu) * 255;
364
col[3] = fcurve_display_alpha(fcu) * 255;
365
365
glColor4ubv((GLubyte *)col);
367
glVertex2fv(fp); glVertex2fv(fp+3);
367
glVertex2fv(fp); glVertex2fv(fp + 3);
370
370
/* only draw second handle if this segment is bezier */
371
371
if (bezt->ipo == BEZT_IPO_BEZ) {
372
372
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
373
col[3]= fcurve_display_alpha(fcu) * 255;
373
col[3] = fcurve_display_alpha(fcu) * 255;
374
374
glColor4ubv((GLubyte *)col);
376
glVertex2fv(fp+3); glVertex2fv(fp+6);
376
glVertex2fv(fp + 3); glVertex2fv(fp + 6);
380
380
/* only draw first handle if previous segment was had handles, and selection is ok */
381
if ( ((bezt->f1 & SELECT)==sel) &&
382
( (!prevbezt && (bezt->ipo==BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo==BEZT_IPO_BEZ)) ) )
381
if (((bezt->f1 & SELECT) == sel) &&
382
((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))))
385
385
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
386
col[3]= fcurve_display_alpha(fcu) * 255;
386
col[3] = fcurve_display_alpha(fcu) * 255;
387
387
glColor4ubv((GLubyte *)col);
389
glVertex2fv(fp); glVertex2fv(fp+3);
389
glVertex2fv(fp); glVertex2fv(fp + 3);
392
392
/* only draw second handle if this segment is bezier, and selection is ok */
393
if ( ((bezt->f3 & SELECT)==sel) &&
394
(bezt->ipo == BEZT_IPO_BEZ) )
393
if (((bezt->f3 & SELECT) == sel) &&
394
(bezt->ipo == BEZT_IPO_BEZ))
397
397
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
398
col[3]= fcurve_display_alpha(fcu) * 255;
398
col[3] = fcurve_display_alpha(fcu) * 255;
399
399
glColor4ubv((GLubyte *)col);
401
glVertex2fv(fp); glVertex2fv(fp+3);
401
glVertex2fv(fp); glVertex2fv(fp + 3);
407
glEnd(); /* GL_LINES */
410
410
/* Samples ---------------- */
413
413
* NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
414
414
* have a consistent appearance (due to off-pixel alignments)...
416
static void draw_fcurve_sample_control (float x, float y, float xscale, float yscale, float hsize)
416
static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize)
418
static GLuint displist=0;
418
static GLuint displist = 0;
420
420
/* initialize X shape */
421
421
if (displist == 0) {
422
displist= glGenLists(1);
422
displist = glGenLists(1);
423
423
glNewList(displist, GL_COMPILE);
425
425
glBegin(GL_LINES);
426
glVertex2f(-0.7f, -0.7f);
427
glVertex2f(+0.7f, +0.7f);
426
glVertex2f(-0.7f, -0.7f);
427
glVertex2f(+0.7f, +0.7f);
429
glVertex2f(-0.7f, +0.7f);
430
glVertex2f(+0.7f, -0.7f);
429
glVertex2f(-0.7f, +0.7f);
430
glVertex2f(+0.7f, -0.7f);
431
glEnd(); /* GL_LINES */
436
436
/* adjust view transform before starting */
437
437
glTranslatef(x, y, 0.0f);
438
glScalef(1.0f/xscale*hsize, 1.0f/yscale*hsize, 1.0f);
438
glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
441
441
glCallList(displist);
443
443
/* restore view transform */
444
glScalef(xscale/hsize, yscale/hsize, 1.0);
444
glScalef(xscale / hsize, yscale / hsize, 1.0);
445
445
glTranslatef(-x, -y, 0.0f);
448
448
/* helper func - draw keyframe vertices only for an F-Curve */
449
static void draw_fcurve_samples (SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
449
static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
451
451
FPoint *first, *last;
452
452
float hsize, xscale, yscale;
454
454
/* get view settings */
455
hsize= UI_GetThemeValuef(TH_VERTEX_SIZE);
455
hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
456
456
UI_view2d_getscale(&ar->v2d, &xscale, &yscale);
458
458
/* set vertex color */
459
if (fcu->flag & (FCURVE_ACTIVE|FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI);
459
if (fcu->flag & (FCURVE_ACTIVE | FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI);
460
460
else UI_ThemeColor(TH_TEXT);
464
last= (first) ? (first + (fcu->totvert-1)) : (NULL);
464
last = (first) ? (first + (fcu->totvert - 1)) : (NULL);
467
467
if (first && last) {
468
468
/* anti-aliased lines for more consistent appearance */
469
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF)==0) glEnable(GL_LINE_SMOOTH);
469
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
470
470
glEnable(GL_BLEND);
472
472
draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize);
473
473
draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize);
475
475
glDisable(GL_BLEND);
476
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF)==0) glDisable(GL_LINE_SMOOTH);
476
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
480
480
/* Curve ---------------- */
482
482
/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
483
static void draw_fcurve_curve (bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid)
483
static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid)
485
485
ChannelDriver *driver;
486
486
float samplefreq, ctime;
498
498
/* disable any drivers temporarily */
499
driver = fcu->driver;
502
502
/* compute unit correction factor */
503
unitFac= ANIM_unit_mapping_get_factor(ac->scene, id, fcu, 0);
503
unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, 0);
505
505
/* Note about sampling frequency:
506
* Ideally, this is chosen such that we have 1-2 pixels = 1 segment
506
* Ideally, this is chosen such that we have 1-2 pixels = 1 segment
507
507
* which means that our curves can be as smooth as possible. However,
508
* this does mean that curves may not be fully accurate (i.e. if they have
509
* sudden spikes which happen at the sampling point, we may have problems).
510
* Also, this may introduce lower performance on less densely detailed curves,'
508
* this does mean that curves may not be fully accurate (i.e. if they have
509
* sudden spikes which happen at the sampling point, we may have problems).
510
* Also, this may introduce lower performance on less densely detailed curves,'
511
511
* though it is impossible to predict this from the modifiers!
513
513
* If the automatically determined sampling frequency is likely to cause an infinite
514
514
* loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value
515
* chosen here is just the coarsest value which still looks reasonable...
515
* chosen here is just the coarsest value which still looks reasonable...
517
/* grid->dx represents the number of 'frames' between gridlines, but we divide by U.v2d_min_gridsize to get pixels-steps */
518
// TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted?
519
samplefreq= dx / U.v2d_min_gridsize;
520
if (samplefreq < 0.00001f) samplefreq= 0.00001f;
517
/* grid->dx represents the number of 'frames' between gridlines, but we divide by U.v2d_min_gridsize to get pixels-steps */
518
/* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */
519
samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize);
520
if (samplefreq < 0.00001f) samplefreq = 0.00001f;
523
523
/* the start/end times are simply the horizontal extents of the 'cur' rect */
524
stime= v2d->cur.xmin;
525
etime= v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */
524
stime = v2d->cur.xmin;
525
etime = v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */
528
528
/* at each sampling interval, add a new vertex
532
532
glBegin(GL_LINE_STRIP);
534
for (ctime= stime; ctime <= etime; ctime += samplefreq)
535
glVertex2f( ctime, evaluate_fcurve(fcu, ctime)*unitFac );
534
for (ctime = stime; ctime <= etime; ctime += samplefreq)
535
glVertex2f(ctime, evaluate_fcurve(fcu, ctime) * unitFac);
539
539
/* restore driver */
540
fcu->driver = driver;
543
543
/* helper func - draw a samples-based F-Curve */
544
static void draw_fcurve_curve_samples (bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
544
static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
546
FPoint *prevfpt= fcu->fpt;
547
FPoint *fpt= prevfpt + 1;
546
FPoint *prevfpt = fcu->fpt;
547
FPoint *fpt = prevfpt + 1;
549
int b= fcu->totvert-1;
549
int b = fcu->totvert - 1;
551
551
glBegin(GL_LINE_STRIP);
556
556
/* extrapolate to left? - left-side of view comes before first keyframe? */
557
557
if (prevfpt->vec[0] > v2d->cur.xmin) {
558
v[0] = v2d->cur.xmin;
560
560
/* y-value depends on the interpolation */
561
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
561
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) {
562
562
/* just extend across the first keyframe's value */
563
v[1]= prevfpt->vec[1];
563
v[1] = prevfpt->vec[1];
566
566
/* extrapolate linear dosnt use the handle, use the next points center instead */
567
fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
568
if (fac) fac= 1.0f/fac;
569
v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
567
fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
568
if (fac) fac = 1.0f / fac;
569
v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
594
594
/* extrapolate to right? (see code for left-extrapolation above too) */
595
595
if (prevfpt->vec[0] < v2d->cur.xmax) {
596
v[0] = v2d->cur.xmax;
598
598
/* y-value depends on the interpolation */
599
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert==1)) {
599
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (fcu->totvert == 1)) {
600
600
/* based on last keyframe's value */
601
v[1]= prevfpt->vec[1];
601
v[1] = prevfpt->vec[1];
604
604
/* extrapolate linear dosnt use the handle, use the previous points center instead */
606
fac= (prevfpt->vec[0]-fpt->vec[0])/(prevfpt->vec[0]-v[0]);
607
if (fac) fac= 1.0f/fac;
608
v[1]= prevfpt->vec[1]-fac*(prevfpt->vec[1]-fpt->vec[1]);
606
fac = (prevfpt->vec[0] - fpt->vec[0]) / (prevfpt->vec[0] - v[0]);
607
if (fac) fac = 1.0f / fac;
608
v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
620
620
/* helper func - draw one repeat of an F-Curve */
621
static void draw_fcurve_curve_bezts (bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
621
static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
623
BezTriple *prevbezt= fcu->bezt;
624
BezTriple *bezt= prevbezt+1;
623
BezTriple *prevbezt = fcu->bezt;
624
BezTriple *bezt = prevbezt + 1;
625
625
float v1[2], v2[2], v3[2], v4[2];
626
626
float *fp, data[120];
628
int b= fcu->totvert-1;
628
int b = fcu->totvert - 1;
631
631
glBegin(GL_LINE_STRIP);
636
636
/* extrapolate to left? */
637
637
if (prevbezt->vec[1][0] > v2d->cur.xmin) {
638
638
/* left-side of view comes before first keyframe, so need to extend as not cyclic */
639
v1[0]= v2d->cur.xmin;
639
v1[0] = v2d->cur.xmin;
641
641
/* y-value depends on the interpolation */
642
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
642
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
643
643
/* just extend across the first keyframe's value */
644
v1[1]= prevbezt->vec[1][1];
646
else if (prevbezt->ipo==BEZT_IPO_LIN) {
644
v1[1] = prevbezt->vec[1][1];
646
else if (prevbezt->ipo == BEZT_IPO_LIN) {
647
647
/* extrapolate linear dosnt use the handle, use the next points center instead */
648
fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
649
if (fac) fac= 1.0f/fac;
650
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
648
fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
649
if (fac) fac = 1.0f / fac;
650
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
653
653
/* based on angle of handle 1 (relative to keyframe) */
654
fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
655
if (fac) fac= 1.0f/fac;
656
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
654
fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
655
if (fac) fac = 1.0f / fac;
656
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
662
662
/* if only one keyframe, add it now */
663
663
if (fcu->totvert == 1) {
664
v1[0]= prevbezt->vec[1][0];
665
v1[1]= prevbezt->vec[1][1];
664
v1[0] = prevbezt->vec[1][0];
665
v1[1] = prevbezt->vec[1][1];
669
669
/* draw curve between first and last keyframe (if there are enough to do so) */
670
// TODO: optimize this to not have to calc stuff out of view too?
670
/* TODO: optimize this to not have to calc stuff out of view too? */
672
if (prevbezt->ipo==BEZT_IPO_CONST) {
672
if (prevbezt->ipo == BEZT_IPO_CONST) {
673
673
/* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
674
v1[0]= prevbezt->vec[1][0];
675
v1[1]= prevbezt->vec[1][1];
674
v1[0] = prevbezt->vec[1][0];
675
v1[1] = prevbezt->vec[1][1];
678
v1[0]= bezt->vec[1][0];
679
v1[1]= prevbezt->vec[1][1];
678
v1[0] = bezt->vec[1][0];
679
v1[1] = prevbezt->vec[1][1];
682
else if (prevbezt->ipo==BEZT_IPO_LIN) {
682
else if (prevbezt->ipo == BEZT_IPO_LIN) {
683
683
/* Linear interpolation: just add one point (which should add a new line segment) */
684
v1[0]= prevbezt->vec[1][0];
685
v1[1]= prevbezt->vec[1][1];
684
v1[0] = prevbezt->vec[1][0];
685
v1[1] = prevbezt->vec[1][1];
693
693
/* resol depends on distance between points (not just horizontal) OR is a fixed high res */
694
// TODO: view scale should factor into this someday too...
694
/* TODO: view scale should factor into this someday too... */
698
resol= (int)(5.0f*len_v2v2(bezt->vec[1], prevbezt->vec[1]));
698
resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
701
701
/* only draw one */
702
v1[0]= prevbezt->vec[1][0];
703
v1[1]= prevbezt->vec[1][1];
702
v1[0] = prevbezt->vec[1][0];
703
v1[1] = prevbezt->vec[1][1];
707
707
/* clamp resolution to max of 32 */
708
// NOTE: higher values will crash
709
if (resol > 32) resol= 32;
711
v1[0]= prevbezt->vec[1][0];
712
v1[1]= prevbezt->vec[1][1];
713
v2[0]= prevbezt->vec[2][0];
714
v2[1]= prevbezt->vec[2][1];
716
v3[0]= bezt->vec[0][0];
717
v3[1]= bezt->vec[0][1];
718
v4[0]= bezt->vec[1][0];
719
v4[1]= bezt->vec[1][1];
708
/* NOTE: higher values will crash */
709
if (resol > 32) resol = 32;
711
v1[0] = prevbezt->vec[1][0];
712
v1[1] = prevbezt->vec[1][1];
713
v2[0] = prevbezt->vec[2][0];
714
v2[1] = prevbezt->vec[2][1];
716
v3[0] = bezt->vec[0][0];
717
v3[1] = bezt->vec[0][1];
718
v4[0] = bezt->vec[1][0];
719
v4[1] = bezt->vec[1][1];
721
721
correct_bezpart(v1, v2, v3, v4);
723
forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float)*3);
724
forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, sizeof(float)*3);
723
BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
724
BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);
726
for (fp= data; resol; resol--, fp+= 3)
726
for (fp = data; resol; resol--, fp += 3)
731
731
/* get next pointers */
735
735
/* last point? */
737
v1[0]= prevbezt->vec[1][0];
738
v1[1]= prevbezt->vec[1][1];
737
v1[0] = prevbezt->vec[1][0];
738
v1[1] = prevbezt->vec[1][1];
743
743
/* extrapolate to right? (see code for left-extrapolation above too) */
744
744
if (prevbezt->vec[1][0] < v2d->cur.xmax) {
745
v1[0]= v2d->cur.xmax;
745
v1[0] = v2d->cur.xmax;
747
747
/* y-value depends on the interpolation */
748
if ((fcu->extend==FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo==BEZT_IPO_CONST) || (fcu->totvert==1)) {
748
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) || (prevbezt->ipo == BEZT_IPO_CONST) || (fcu->totvert == 1)) {
749
749
/* based on last keyframe's value */
750
v1[1]= prevbezt->vec[1][1];
752
else if (prevbezt->ipo==BEZT_IPO_LIN) {
750
v1[1] = prevbezt->vec[1][1];
752
else if (prevbezt->ipo == BEZT_IPO_LIN) {
753
753
/* extrapolate linear dosnt use the handle, use the previous points center instead */
755
fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
756
if (fac) fac= 1.0f/fac;
757
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
755
fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
756
if (fac) fac = 1.0f / fac;
757
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
760
760
/* based on angle of handle 1 (relative to keyframe) */
761
fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
762
if (fac) fac= 1.0f/fac;
763
v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
761
fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
762
if (fac) fac = 1.0f / fac;
763
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
786
786
glLineWidth(3.0f);
788
788
/* anti-aliased lines for less jagged appearance */
789
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF)==0) glEnable(GL_LINE_SMOOTH);
789
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
790
790
glEnable(GL_BLEND);
792
792
/* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */
793
for (fcu= sipo->ghostCurves.first; fcu; fcu= fcu->next) {
793
for (fcu = sipo->ghostCurves.first; fcu; fcu = fcu->next) {
794
794
/* set whatever color the curve has set
795
* - this is set by the function which creates these
795
* - this is set by the function which creates these
796
796
* - draw with a fixed opacity of 2
798
798
glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], 0.5f);
806
806
glLineWidth(1.0f);
808
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF)==0) glDisable(GL_LINE_SMOOTH);
808
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
809
809
glDisable(GL_BLEND);
812
812
/* This is called twice from space_graph.c -> graph_main_area_draw()
813
813
* Unselected then selected F-Curves are drawn so that they do not occlude each other.
815
void graph_draw_curves (bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid *grid, short sel)
815
void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid *grid, short sel)
817
817
ListBase anim_data = {NULL, NULL};
818
818
bAnimListElem *ale;
821
821
/* build list of curves to draw */
822
filter= (ANIMFILTER_DATA_VISIBLE|ANIMFILTER_CURVE_VISIBLE);
822
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE);
823
823
filter |= ((sel) ? (ANIMFILTER_SEL) : (ANIMFILTER_UNSEL));
824
824
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
826
826
/* for each curve:
827
827
* draw curve, then handle-lines, and finally vertices in this order so that
828
* the data will be layered correctly
828
* the data will be layered correctly
830
for (ale=anim_data.first; ale; ale=ale->next) {
831
FCurve *fcu= (FCurve *)ale->key_data;
832
FModifier *fcm= find_active_fmodifier(&fcu->modifiers);
833
AnimData *adt= ANIM_nla_mapping_get(ac, ale);
830
for (ale = anim_data.first; ale; ale = ale->next) {
831
FCurve *fcu = (FCurve *)ale->key_data;
832
FModifier *fcm = find_active_fmodifier(&fcu->modifiers);
833
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
835
835
/* map keyframes for drawing if scaled F-Curve */
846
846
/* 1) draw curve line */
848
848
/* set color/drawing style for curve itself */
849
if ( ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED) ) {
849
if (((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) || (fcu->flag & FCURVE_PROTECTED)) {
850
850
/* protected curves (non editable) are drawn with dotted lines */
853
if ( ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED) ) {
854
/* muted curves are drawn in a greyish hue */
855
// XXX should we have some variations?
853
if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) {
854
/* muted curves are drawn in a grayish hue */
855
/* XXX should we have some variations? */
856
856
UI_ThemeColorShade(TH_HEADER, 50);
953
953
bAnimListElem *ale;
956
View2D *v2d= &ar->v2d;
957
float y= 0.0f, height;
956
View2D *v2d = &ar->v2d;
957
float y = 0.0f, height;
961
961
/* build list of channels to draw */
962
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
963
items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
962
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
963
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
965
965
/* Update max-extent of channels here (taking into account scrollers):
966
* - this is done to allow the channel list to be scrollable, but must be done here
967
* to avoid regenerating the list again and/or also because channels list is drawn first
966
* - this is done to allow the channel list to be scrollable, but must be done here
967
* to avoid regenerating the list again and/or also because channels list is drawn first
968
968
* - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
969
969
* start of list offset, and the second is as a correction for the scrollers.
971
height= (float)((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
971
height = (float)((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2));
972
972
UI_view2d_totRect_set(v2d, ar->winx, height);
974
/* loop through channels, and set up drawing depending on their type */
975
{ /* first pass: just the standard GL-drawing for backdrop + text */
976
y= (float)ACHANNEL_FIRST;
974
/* loop through channels, and set up drawing depending on their type */
975
{ /* first pass: just the standard GL-drawing for backdrop + text */
976
y = (float)ACHANNEL_FIRST;
978
for (ale= anim_data.first, i=0; ale; ale= ale->next, i++) {
979
const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
980
const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
978
for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
979
const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF);
980
const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF);
982
982
/* check if visible */
983
if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
984
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
983
if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
984
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
986
986
/* draw all channels using standard channel-drawing API */
987
987
ANIM_channel_draw(ac, ale, yminc, ymaxc);
991
991
y -= ACHANNEL_STEP;
994
{ /* second pass: widgets */
995
uiBlock *block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
994
{ /* second pass: widgets */
995
uiBlock *block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
996
996
size_t channel_index = 0;
998
y= (float)ACHANNEL_FIRST;
998
y = (float)ACHANNEL_FIRST;
1000
1000
/* set blending again, as may not be set in previous step */
1001
1001
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1002
1002
glEnable(GL_BLEND);
1004
for (ale= anim_data.first, i=0; ale; ale= ale->next, i++) {
1005
const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1006
const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1004
for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
1005
const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF);
1006
const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF);
1008
1008
/* check if visible */
1009
if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1010
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
1009
if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1010
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
1012
1012
/* draw all channels using standard channel-drawing API */
1013
1013
ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index);