void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; View2D *v2d = &ar->v2d; float y = 0.0f; size_t items; int height; /* build list of channels to draw */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Update max-extent of channels here (taking into account scrollers): * - this is done to allow the channel list to be scrollable, but must be done here * to avoid regenerating the list again and/or also because channels list is drawn first * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2)); /* don't use totrect set, as the width stays the same * (NOTE: this is ok here, the configuration is pretty straightforward) */ v2d->tot.ymin = (float)(-height); /* loop through channels, and set up drawing depending on their type */ y = (float)(-NLACHANNEL_HEIGHT(snla)); for (ale = anim_data.first; ale; ale = ale->next) { const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla)); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* data to draw depends on the type of channel */ switch (ale->type) { case ANIMTYPE_NLATRACK: { AnimData *adt = ale->adt; NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; int index; /* draw each strip in the track (if visible) */ for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) { if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { /* draw the visualization of the strip */ nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc); /* add the text for this strip to the cache */ nla_draw_strip_text(adt, nlt, strip, index, v2d, yminc, ymaxc); /* if transforming strips (only real reason for temp-metas currently), * add to the cache the frame numbers of the strip's extents */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) nla_draw_strip_frames_text(nlt, strip, v2d, yminc, ymaxc); } } break; } case ANIMTYPE_NLAACTION: { AnimData *adt = ale->adt; float color[4]; /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, * and a second darker rect within which we draw keyframe indicator dots if there's data */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); /* get colors for drawing */ nla_action_get_color(adt, ale->data, color); glColor4fv(color); /* draw slightly shifted up for greater separation from standard channels, * but also slightly shorter for some more contrast when viewing the strips */ glRectf(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); /* draw keyframes in the action */ nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP); /* draw 'embossed' lines above and below the strip for effect */ /* white base-lines */ glLineWidth(2.0f); glColor4f(1.0f, 1.0f, 1.0f, 0.3); fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); /* black top-lines */ glLineWidth(1.0f); glColor3f(0.0f, 0.0f, 0.0f); fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP); fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP); glDisable(GL_BLEND); break; } } } /* adjust y-position for next one */ y -= NLACHANNEL_STEP(snla); } /* free tempolary channels */ ANIM_animdata_freelist(&anim_data); }
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar) { View2D *v2d = &ar->v2d; const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); const float text_margin_x = (8 * UI_DPI_FAC) * pixelx; /* build list of channels to draw */ ListBase anim_data = {NULL, NULL}; int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS); size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* Update max-extent of channels here (taking into account scrollers): * - this is done to allow the channel list to be scrollable, but must be done here * to avoid regenerating the list again and/or also because channels list is drawn first * - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for * start of list offset, and the second is as a correction for the scrollers. */ int height = NLACHANNEL_TOT_HEIGHT(ac, items); v2d->tot.ymin = -height; /* loop through channels, and set up drawing depending on their type */ float ymax = NLACHANNEL_FIRST_TOP(ac); for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) { float ymin = ymax - NLACHANNEL_HEIGHT(snla); float ycenter = (ymax + ymin) / 2.0f; /* check if visible */ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) { /* data to draw depends on the type of channel */ switch (ale->type) { case ANIMTYPE_NLATRACK: { AnimData *adt = ale->adt; NlaTrack *nlt = (NlaTrack *)ale->data; NlaStrip *strip; int index; /* draw each strip in the track (if visible) */ for (strip = nlt->strips.first, index = 1; strip; strip = strip->next, index++) { if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) { const float xminc = strip->start + text_margin_x; const float xmaxc = strip->end + text_margin_x; /* draw the visualization of the strip */ nla_draw_strip(snla, adt, nlt, strip, v2d, ymin, ymax); /* add the text for this strip to the cache */ if (xminc < xmaxc) { nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, ymin, ymax); } /* if transforming strips (only real reason for temp-metas currently), * add to the cache the frame numbers of the strip's extents */ if (strip->flag & NLASTRIP_FLAG_TEMP_META) { nla_draw_strip_frames_text(nlt, strip, v2d, ymin, ymax); } } } break; } case ANIMTYPE_NLAACTION: { AnimData *adt = ale->adt; uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); /* just draw a semi-shaded rect spanning the width of the viewable area if there's data, * and a second darker rect within which we draw keyframe indicator dots if there's data */ GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); GPU_blend(true); /* get colors for drawing */ float color[4]; nla_action_get_color(adt, ale->data, color); immUniformColor4fv(color); /* draw slightly shifted up for greater separation from standard channels, * but also slightly shorter for some more contrast when viewing the strips */ immRectf( pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP, v2d->cur.xmax, ymax - NLACHANNEL_SKIP); /* draw 'embossed' lines above and below the strip for effect */ /* white base-lines */ GPU_line_width(2.0f); immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f); immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP); immVertex2f(pos, v2d->cur.xmax, ymin + NLACHANNEL_SKIP); immVertex2f(pos, v2d->cur.xmin, ymax - NLACHANNEL_SKIP); immVertex2f(pos, v2d->cur.xmax, ymax - NLACHANNEL_SKIP); immEnd(); /* black top-lines */ GPU_line_width(1.0f); immUniformColor3f(0.0f, 0.0f, 0.0f); immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP); immVertex2f(pos, v2d->cur.xmax, ymin + NLACHANNEL_SKIP); immVertex2f(pos, v2d->cur.xmin, ymax - NLACHANNEL_SKIP); immVertex2f(pos, v2d->cur.xmax, ymax - NLACHANNEL_SKIP); immEnd(); /* TODO: these lines but better --^ */ immUnbindProgram(); /* draw keyframes in the action */ nla_action_draw_keyframes( v2d, adt, ale->data, ycenter, ymin + NLACHANNEL_SKIP, ymax - NLACHANNEL_SKIP); GPU_blend(false); break; } } } } /* free tempolary channels */ ANIM_animdata_freelist(&anim_data); }