static int actkeys_viewall(bContext *C, const short onlySel) { bAnimContext ac; View2D *v2d; float extra; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; v2d= &ac.ar->v2d; /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel); extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; /* set vertical range */ v2d->cur.ymax= 0.0f; v2d->cur.ymin= (float)-(v2d->mask.ymax - v2d->mask.ymin); /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); /* just redraw this view */ ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; }
static int actkeys_viewall(bContext *C, const bool only_sel) { bAnimContext ac; View2D *v2d; float extra, min, max; bool found; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; v2d = &ac.ar->v2d; /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ found = get_keyframe_extents(&ac, &min, &max, only_sel); if (only_sel && (found == false)) return OPERATOR_CANCELLED; v2d->cur.xmin = min; v2d->cur.xmax = max; extra = 0.1f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; /* set vertical range */ if (only_sel == false) { /* view all -> the summary channel is usually the shows everything, and resides right at the top... */ v2d->cur.ymax = 0.0f; v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask); } else { /* locate first selected channel (or the active one), and frame those */ float ymin = v2d->cur.ymin; float ymax = v2d->cur.ymax; if (actkeys_channels_get_selected_extents(&ac, &ymin, &ymax)) { /* recenter the view so that this range is in the middle */ float ymid = (ymax - ymin) / 2.0f + ymin; float x_center; UI_view2d_center_get(v2d, &x_center, NULL); UI_view2d_center_set(v2d, x_center, ymid); } } /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); /* just redraw this view */ ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; }
static int actkeys_viewall(bContext *C, const bool only_sel, const bool only_xaxis) { bAnimContext ac; View2D *v2d; float extra; bool found; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; v2d = &ac.ar->v2d; /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ found = get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, only_sel); if (only_sel && (found == false)) return OPERATOR_CANCELLED; extra = 0.1f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; /* set vertical range */ if (only_xaxis == false) { v2d->cur.ymax = 0.0f; v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask); } /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); /* just redraw this view */ ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; }
void draw_nla_channel_list(bContext *C, bAnimContext *ac, ARegion *ar) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; SpaceNla *snla = (SpaceNla *)ac->sl; 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); /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); /* draw channels */ { /* first pass: just the standard GL-drawing for backdrop + text */ y = (float)(-NLACHANNEL_HEIGHT(snla)); for (ale = anim_data.first; ale; ale = ale->next) { float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla)); 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) ) { /* draw all channels using standard channel-drawing API */ ANIM_channel_draw(ac, ale, yminc, ymaxc); } /* adjust y-position for next one */ y -= NLACHANNEL_STEP(snla); } } { /* second pass: UI widgets */ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); size_t channel_index = 0; y = (float)(-NLACHANNEL_HEIGHT(snla)); /* set blending again, as may not be set in previous step */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); /* loop through channels, and set up drawing depending on their type */ 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) ) { /* draw all channels using standard channel-drawing API */ ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index); } /* adjust y-position for next one */ y -= NLACHANNEL_STEP(snla); channel_index++; } UI_block_end(C, block); UI_block_draw(C, block); glDisable(GL_BLEND); } /* free temporary channels */ ANIM_animdata_freelist(&anim_data); }
void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) { ScrArea *sa = CTX_wm_area(C); SpaceClip *sc = CTX_wm_space_clip(C); View2D *v2d = &ar->v2d; MovieClip *clip = ED_space_clip_get_clip(sc); uiStyle *style = UI_style_get(); int fontid = style->widget.uifont_id; if (!clip) { return; } MovieTracking *tracking = &clip->tracking; MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); if (height > BLI_rcti_size_y(&v2d->mask)) { /* 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); } /* need to do a view-sync here, so that the keys area doesn't jump around * (it must copy this) */ UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY); /* loop through channels, and set up drawing depending on their type * first pass: just the standard GL-drawing for backdrop + text */ float y = (float)CHANNEL_FIRST; GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); MovieTrackingDopesheetChannel *channel; for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float)(y - CHANNEL_HEIGHT_HALF); float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; float color[3]; track_channel_color(track, NULL, color); immUniformColor3fv(color); immRectf(pos, v2d->cur.xmin, (float)y - CHANNEL_HEIGHT_HALF, v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + CHANNEL_HEIGHT_HALF); } /* adjust y-position for next one */ y -= CHANNEL_STEP; } immUnbindProgram(); /* second pass: text */ y = (float)CHANNEL_FIRST; BLF_size(fontid, 11.0f * U.pixelsize, U.dpi); for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float)(y - CHANNEL_HEIGHT_HALF); float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; bool sel = (track->flag & TRACK_DOPE_SEL) != 0; UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT); float font_height = BLF_height(fontid, channel->name, sizeof(channel->name)); BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD, y - font_height / 2.0f, 0.0f); BLF_draw(fontid, channel->name, strlen(channel->name)); } /* adjust y-position for next one */ y -= CHANNEL_STEP; } /* third pass: widgets */ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); y = (float)CHANNEL_FIRST; /* get RNA properties (once) */ PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock"); BLI_assert(chan_prop_lock); GPU_blend(true); for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float)(y - CHANNEL_HEIGHT_HALF); float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED; PointerRNA ptr; RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr); UI_block_emboss_set(block, UI_EMBOSS_NONE); uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 1, icon, v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f, UI_UNIT_X, UI_UNIT_Y, &ptr, chan_prop_lock, 0, 0, 0, 0, 0, NULL); UI_block_emboss_set(block, UI_EMBOSS); } /* adjust y-position for next one */ y -= CHANNEL_STEP; } GPU_blend(false); UI_block_end(C, block); UI_block_draw(C, block); }
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; int items, height; /* build list of channels to draw */ filter= (ANIMFILTER_VISIBLE|ANIMFILTER_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) + (NLACHANNEL_HEIGHT*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); /* need to do a view-sync here, so that the strips area doesn't jump around */ UI_view2d_sync(NULL, ac->sa, v2d, V2D_VIEWSYNC_AREA_VERTICAL); /* loop through channels, and set up drawing depending on their type */ y= (float)(-NLACHANNEL_HEIGHT); for (ale= anim_data.first; ale; ale= ale->next) { const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF); const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF); /* 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 visualisation 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(nlt, strip, index, 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; } /* free tempolary channels */ BLI_freelistN(&anim_data); }
void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar) { ScrArea *sa = CTX_wm_area(C); SpaceClip *sc = CTX_wm_space_clip(C); View2D *v2d = &ar->v2d; MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking; MovieTrackingDopesheet *dopesheet; MovieTrackingDopesheetChannel *channel; uiStyle *style = UI_GetStyle(); uiBlock *block; int fontid = style->widget.uifont_id; int height; float y; PropertyRNA *chan_prop_lock; if (!clip) return; tracking = &clip->tracking; dopesheet = &tracking->dopesheet; height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT); if (height > BLI_rcti_size_y(&v2d->mask)) { /* 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); } /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY); /* loop through channels, and set up drawing depending on their type * first pass: just the standard GL-drawing for backdrop + text */ y = (float) CHANNEL_FIRST; BLF_size(fontid, 11.0f * U.pixelsize, U.dpi); for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float) (y - CHANNEL_HEIGHT_HALF); float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; float font_height, color[3]; int sel = track->flag & TRACK_DOPE_SEL; track_channel_color(track, NULL, color); glColor3fv(color); glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF, v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF); if (sel) UI_ThemeColor(TH_TEXT_HI); else UI_ThemeColor(TH_TEXT); font_height = BLF_height(fontid, channel->name, sizeof(channel->name)); BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD, y - font_height / 2.0f, 0.0f); BLF_draw(fontid, channel->name, strlen(channel->name)); } /* adjust y-position for next one */ y -= CHANNEL_STEP; } /* second pass: widgets */ block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); y = (float) CHANNEL_FIRST; /* get RNA properties (once) */ chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock"); BLI_assert(chan_prop_lock); glEnable(GL_BLEND); for (channel = dopesheet->channels.first; channel; channel = channel->next) { float yminc = (float)(y - CHANNEL_HEIGHT_HALF); float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) { MovieTrackingTrack *track = channel->track; const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED; PointerRNA ptr; RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr); uiBlockSetEmboss(block, UI_EMBOSSN); uiDefIconButR_prop(block, ICONTOG, 1, icon, v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f, UI_UNIT_X, UI_UNIT_Y, &ptr, chan_prop_lock, 0, 0, 0, 0, 0, NULL); uiBlockSetEmboss(block, UI_EMBOSS); } /* adjust y-position for next one */ y -= CHANNEL_STEP; } glDisable(GL_BLEND); uiEndBlock(C, block); uiDrawBlock(C, block); }
/* left hand part */ void draw_channel_names(bContext *C, bAnimContext *ac, 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 ACHANNEL_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 * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2)); if (height > (v2d->mask.ymax - v2d->mask.ymin)) { /* 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); } /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); /* loop through channels, and set up drawing depending on their type */ { /* first pass: just the standard GL-drawing for backdrop + text */ y = (float)ACHANNEL_FIRST; for (ale = anim_data.first; ale; ale = ale->next) { float yminc = (float)(y - ACHANNEL_HEIGHT_HALF); float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* draw all channels using standard channel-drawing API */ ANIM_channel_draw(ac, ale, yminc, ymaxc); } /* adjust y-position for next one */ y -= ACHANNEL_STEP; } } { /* second pass: widgets */ uiBlock *block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); size_t channel_index = 0; y = (float)ACHANNEL_FIRST; for (ale = anim_data.first; ale; ale = ale->next) { float yminc = (float)(y - ACHANNEL_HEIGHT_HALF); float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* draw all channels using standard channel-drawing API */ ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index); } /* adjust y-position for next one */ y -= ACHANNEL_STEP; channel_index++; } uiEndBlock(C, block); uiDrawBlock(C, block); } /* free tempolary channels */ BLI_freelistN(&anim_data); }
/* left hand part */ void draw_channel_names(bContext *C, bAnimContext *ac, 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); height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac))); if (height > BLI_rcti_size_y(&v2d->mask)) { /* 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); } /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */ UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); /* loop through channels, and set up drawing depending on their type */ { /* first pass: just the standard GL-drawing for backdrop + text */ size_t channel_index = 0; y = (float)ACHANNEL_FIRST(ac); for (ale = anim_data.first; ale; ale = ale->next) { float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* draw all channels using standard channel-drawing API */ ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index); } /* adjust y-position for next one */ y -= ACHANNEL_STEP(ac); channel_index++; } } { /* second pass: widgets */ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); size_t channel_index = 0; y = (float)ACHANNEL_FIRST(ac); for (ale = anim_data.first; ale; ale = ale->next) { float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac)); float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac)); /* check if visible */ if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) { /* draw all channels using standard channel-drawing API */ ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index); } /* adjust y-position for next one */ y -= ACHANNEL_STEP(ac); channel_index++; } UI_block_end(C, block); UI_block_draw(C, block); } /* free tempolary channels */ ANIM_animdata_freelist(&anim_data); }
void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; SpaceNla *snla = (SpaceNla *)ac->sl; View2D *v2d = &ar->v2d; size_t items; /* 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. */ int height = NLACHANNEL_TOT_HEIGHT(ac, items); v2d->tot.ymin = -height; /* need to do a view-sync here, so that the keys area doesn't jump around * (it must copy this) */ UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY); /* draw channels */ { /* first pass: just the standard GL-drawing for backdrop + text */ size_t channel_index = 0; float ymax = NLACHANNEL_FIRST_TOP(ac); for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla), channel_index++) { float ymin = ymax - NLACHANNEL_HEIGHT(snla); /* check if visible */ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) { /* draw all channels using standard channel-drawing API */ ANIM_channel_draw(ac, ale, ymin, ymax, channel_index); } } } { /* second pass: UI widgets */ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); size_t channel_index = 0; float ymax = NLACHANNEL_FIRST_TOP(ac); /* set blending again, as may not be set in previous step */ GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); GPU_blend(true); /* loop through channels, and set up drawing depending on their type */ for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla), channel_index++) { float ymin = ymax - NLACHANNEL_HEIGHT(snla); /* check if visible */ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) || IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) { /* draw all channels using standard channel-drawing API */ rctf channel_rect; BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, ymin, ymax); ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index); } } UI_block_end(C, block); UI_block_draw(C, block); GPU_blend(false); } /* free temporary channels */ ANIM_animdata_freelist(&anim_data); }