/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d. * The controls are laid out as follows: * * ------------------------------------------- * | Directory input | execute | * ------------------------------------------- * | Filename input | + | - | cancel | * ------------------------------------------- * * The input widgets will stretch to fill any excess space. * When there isn't enough space for all controls to be shown, they are * hidden in this order: x/-, execute/cancel, input widgets. */ void file_draw_buttons(const bContext *C, ARegion *ar) { /* Button layout. */ const int max_x = ar->winx - 10; const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); const int input_minw = 20; const int btn_h = UI_UNIT_Y; const int btn_fn_w = UI_UNIT_X; const int btn_minw = 80; const int btn_margin = 20; const int separator = 4; /* Additional locals. */ char uiblockstr[32]; int loadbutton; int fnumbuttons; int min_x = 10; int chan_offs = 0; int available_w = max_x - min_x; int line1_w = available_w; int line2_w = available_w; uiBut *but; uiBlock *block; SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); ARegion *artmp; /* Initialize UI block. */ BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar); block = uiBeginBlock(C, ar, uiblockstr, UI_EMBOSS); /* exception to make space for collapsed region icon */ for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) { if (artmp->regiontype == RGN_TYPE_CHANNELS && artmp->flag & RGN_FLAG_HIDDEN) { chan_offs = 16; min_x += chan_offs; available_w -= chan_offs; } } /* Is there enough space for the execute / cancel buttons? */ loadbutton = UI_GetStringWidth(sfile->params->title) + btn_margin; if (loadbutton < btn_minw) { loadbutton = MAX2(btn_minw, btn_margin + UI_GetStringWidth(params->title)); } if (available_w <= loadbutton + separator + input_minw || params->title[0] == 0) { loadbutton = 0; } else { line1_w -= (loadbutton + separator); line2_w = line1_w; } /* Is there enough space for file number increment/decrement buttons? */ fnumbuttons = 2 * btn_fn_w; if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) { fnumbuttons = 0; } else { line2_w -= (fnumbuttons + separator); } /* Text input fields for directory and file. */ if (available_w > 0) { int overwrite_alert = file_draw_check_exists(sfile); /* callbacks for operator check functions */ uiBlockSetFunc(block, file_draw_check_cb, NULL, NULL); but = uiDefBut(block, TEX, -1, "", min_x, line1_y, line1_w - chan_offs, btn_h, params->dir, 0.0, (float)FILE_MAX, 0, 0, TIP_("File path")); uiButSetCompleteFunc(but, autocomplete_directory, NULL); uiButSetFlag(but, UI_BUT_NO_UTF8); uiButClearFlag(but, UI_BUT_UNDO); uiButSetNFunc(but, file_directory_enter_handle, NULL, but); /* TODO, directory editing is non-functional while a library is loaded * until this is properly supported just disable it. */ if (sfile->files && filelist_lib(sfile->files)) uiButSetFlag(but, UI_BUT_DISABLED); if ((params->flag & FILE_DIRSEL_ONLY) == 0) { but = uiDefBut(block, TEX, -1, "", min_x, line2_y, line2_w - chan_offs, btn_h, params->file, 0.0, (float)FILE_MAXFILE, 0, 0, TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name"))); uiButSetCompleteFunc(but, autocomplete_file, NULL); uiButSetFlag(but, UI_BUT_NO_UTF8); uiButClearFlag(but, UI_BUT_UNDO); /* silly workaround calling NFunc to ensure this does not get called * immediate ui_apply_but_func but only after button deactivates */ uiButSetNFunc(but, file_filename_enter_handle, NULL, but); /* check if this overrides a file and if the operator option is used */ if (overwrite_alert) { uiButSetFlag(but, UI_BUT_REDALERT); } } /* clear func */ uiBlockSetFunc(block, NULL, NULL, NULL); } /* Filename number increment / decrement buttons. */ if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) { uiBlockBeginAlign(block); but = uiDefIconButO(block, BUT, "FILE_OT_filenum", 0, ICON_ZOOMOUT, min_x + line2_w + separator - chan_offs, line2_y, btn_fn_w, btn_h, TIP_("Decrement the filename number")); RNA_int_set(uiButGetOperatorPtrRNA(but), "increment", -1); but = uiDefIconButO(block, BUT, "FILE_OT_filenum", 0, ICON_ZOOMIN, min_x + line2_w + separator + btn_fn_w - chan_offs, line2_y, btn_fn_w, btn_h, TIP_("Increment the filename number")); RNA_int_set(uiButGetOperatorPtrRNA(but), "increment", 1); uiBlockEndAlign(block); } /* Execute / cancel buttons. */ if (loadbutton) { /* params->title is already translated! */ uiDefButO(block, BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, params->title, max_x - loadbutton, line1_y, loadbutton, btn_h, ""); uiDefButO(block, BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"), max_x - loadbutton, line2_y, loadbutton, btn_h, ""); } uiEndBlock(C, block); uiDrawBlock(C, block); }
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: backdrops + oldstyle drawing */ y = (float)(-NLACHANNEL_HEIGHT(snla)); draw_nla_channel_list_gl(ac, &anim_data, v2d, y); } { /* second pass: UI widgets */ uiBlock *block = uiBeginBlock(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++; } uiEndBlock(C, block); uiDrawBlock(C, block); glDisable(GL_BLEND); } /* free tempolary channels */ BLI_freelistN(&anim_data); }
void file_draw_list(const bContext *C, ARegion *ar) { SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); FileLayout *layout = ED_fileselect_get_layout(sfile, ar); View2D *v2d = &ar->v2d; struct FileList *files = sfile->files; struct direntry *file; ImBuf *imb; uiBlock *block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); int numfiles; int numfiles_layout; int sx, sy; int offset; int textwidth, textheight; int i; short is_icon; short align; bool do_drag; int column_space = 0.6f * UI_UNIT_X; numfiles = filelist_numfiles(files); if (params->display != FILE_IMGDISPLAY) { draw_background(layout, v2d); draw_dividers(layout, v2d); } offset = ED_fileselect_layout_offset(layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax); if (offset < 0) offset = 0; numfiles_layout = ED_fileselect_layout_numfiles(layout, ar); /* adjust, so the next row is already drawn when scrolling */ if (layout->flag & FILE_LAYOUT_HOR) { numfiles_layout += layout->rows; } else { numfiles_layout += layout->columns; } textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : (int)layout->column_widths[COLUMN_NAME]; textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5); align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT; for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) { ED_fileselect_layout_tilepos(layout, i, &sx, &sy); sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X); sy = (int)(v2d->tot.ymax - sy); file = filelist_file(files, i); UI_ThemeColor4(TH_TEXT); if (!(file->selflag & EDITING_FILE)) { if ((params->active_file == i) || (file->selflag & HILITED_FILE) || (file->selflag & SELECTED_FILE)) { int colorid = (file->selflag & SELECTED_FILE) ? TH_HILITE : TH_BACK; int shade = (params->active_file == i) || (file->selflag & HILITED_FILE) ? 20 : 0; draw_tile(sx, sy - 1, layout->tile_w + 4, sfile->layout->tile_h + layout->tile_border_y, colorid, shade); } } uiSetRoundBox(UI_CNR_NONE); /* don't drag parent or refresh items */ do_drag = !(STREQ(file->relname, "..") || STREQ(file->relname, ".")); if (FILE_IMGDISPLAY == params->display) { is_icon = 0; imb = filelist_getimage(files, i); if (!imb) { imb = filelist_geticon(files, i); is_icon = 1; } file_draw_preview(block, file, sx, sy, imb, layout, !is_icon && (file->flags & IMAGEFILE), do_drag); } else { file_draw_icon(block, file->path, sx, sy - (UI_UNIT_Y / 6), get_file_icon(file), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag); sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; } UI_ThemeColor4(TH_TEXT); if (file->selflag & EDITING_FILE) { uiBut *but = uiDefBut(block, TEX, 1, "", sx, sy - layout->tile_h - 0.15f * UI_UNIT_X, textwidth, textheight, sfile->params->renameedit, 1.0f, (float)sizeof(sfile->params->renameedit), 0, 0, ""); uiButSetRenameFunc(but, renamebutton_cb, file); uiButSetFlag(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ uiButClearFlag(but, UI_BUT_UNDO); if (false == uiButActiveOnly(C, ar, block, but)) { file->selflag &= ~EDITING_FILE; } } if (!(file->selflag & EDITING_FILE)) { int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy; file_draw_string(sx + 1, tpos, file->relname, (float)textwidth, textheight, align); } if (params->display == FILE_SHORTDISPLAY) { sx += (int)layout->column_widths[COLUMN_NAME] + column_space; if (!(file->type & S_IFDIR)) { file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } } else if (params->display == FILE_LONGDISPLAY) { sx += (int)layout->column_widths[COLUMN_NAME] + column_space; #ifndef WIN32 /* rwx rwx rwx */ file_draw_string(sx, sy, file->mode1, layout->column_widths[COLUMN_MODE1], layout->tile_h, align); sx += layout->column_widths[COLUMN_MODE1] + column_space; file_draw_string(sx, sy, file->mode2, layout->column_widths[COLUMN_MODE2], layout->tile_h, align); sx += layout->column_widths[COLUMN_MODE2] + column_space; file_draw_string(sx, sy, file->mode3, layout->column_widths[COLUMN_MODE3], layout->tile_h, align); sx += layout->column_widths[COLUMN_MODE3] + column_space; file_draw_string(sx, sy, file->owner, layout->column_widths[COLUMN_OWNER], layout->tile_h, align); sx += layout->column_widths[COLUMN_OWNER] + column_space; #endif file_draw_string(sx, sy, file->date, layout->column_widths[COLUMN_DATE], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_DATE] + column_space; file_draw_string(sx, sy, file->time, layout->column_widths[COLUMN_TIME], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_TIME] + column_space; if (!(file->type & S_IFDIR)) { file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } } } 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, "dopesheet channel buttons", 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); }
void action_header_buttons(const bContext *C, ARegion *ar) { ScrArea *sa= CTX_wm_area(C); SpaceAction *saction= CTX_wm_space_action(C); bAnimContext ac; uiBlock *block; int xco, yco= 3, xmax; block= uiBeginBlock(C, ar, "header buttons", UI_EMBOSS); uiBlockSetHandleFunc(block, do_action_buttons, NULL); xco= ED_area_header_standardbuttons(C, block, yco); uiBlockSetEmboss(block, UI_EMBOSS); /* get context... (also syncs data) */ ANIM_animdata_get_context(C, &ac); if ((sa->flag & HEADER_NO_PULLDOWN)==0) { xmax= GetButStringLength("View"); uiDefMenuBut(block, act_viewmenu, NULL, "View", xco, yco, xmax-3, 20, ""); xco+= xmax; xmax= GetButStringLength("Select"); uiDefMenuBut(block, act_selectmenu, NULL, "Select", xco, yco, xmax-3, 20, ""); xco+= xmax; if ( (saction->mode == SACTCONT_DOPESHEET) || ((saction->action) && (saction->mode==SACTCONT_ACTION)) ) { xmax= GetButStringLength("Channel"); uiDefMenuBut(block, act_channelmenu, NULL, "Channel", xco, yco, xmax-3, 20, ""); xco+= xmax; } else if (saction->mode==SACTCONT_GPENCIL) { xmax= GetButStringLength("Channel"); uiDefMenuBut(block, act_gplayermenu, NULL, "Channel", xco, yco, xmax-3, 20, ""); xco+= xmax; } //xmax= GetButStringLength("Marker"); //uiDefMenuBut(block, act_markermenu, NULL, "Marker", xco, yco, xmax-3, 20, ""); //xco+= xmax; if (saction->mode == SACTCONT_GPENCIL) { //xmax= GetButStringLength("Frame"); //uiDefMenuBut(block, act_selectmenu, NULL, "Frame", xco, yco, xmax-3, 20, ""); //xco+= xmax; } else { xmax= GetButStringLength("Key"); uiDefMenuBut(block, act_editmenu, NULL, "Key", xco, yco, xmax-3, 20, ""); xco+= xmax; } } uiBlockSetEmboss(block, UI_EMBOSS); /* MODE SELECTOR */ uiDefButC(block, MENU, B_MODECHANGE, "Editor Mode %t|DopeSheet %x3|Action Editor %x0|ShapeKey Editor %x1|Grease Pencil %x2", xco,yco,90,YIC, &saction->mode, 0, 1, 0, 0, "Editing modes for this editor"); xco += (90 + 8); /* SUMMARY CHANNEL */ uiDefIconTextButBitI(block, TOG, ADS_FILTER_SUMMARY, B_REDR, ICON_BORDERMOVE, "Summary", xco,yco,XIC*4,YIC, &(saction->ads.filterflag), 0, 0, 0, 0, "Include DopeSheet summary row"); // TODO: needs a better icon xco += (XIC*4.5); /*if (ac.data)*/ { /* MODE-DEPENDENT DRAWING */ if (saction->mode == SACTCONT_DOPESHEET) { /* FILTERING OPTIONS */ xco -= XIC; // XXX first button incurs this offset... xco= ANIM_headerUI_standard_buttons(C, &saction->ads, block, xco, yco); } else if (saction->mode == SACTCONT_ACTION) { uiLayout *layout; bScreen *sc= CTX_wm_screen(C); PointerRNA ptr; RNA_pointer_create(&sc->id, &RNA_SpaceDopeSheetEditor, saction, &ptr); layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, 20+3, 20, 1, U.uistyles.first); uiTemplateID(layout, (bContext*)C, &ptr, "action", "ACT_OT_new", NULL, NULL); uiBlockLayoutResolve(block, &xco, NULL); xco += 8; } /* draw AUTOSNAP */ if (saction->mode != SACTCONT_GPENCIL) { if (saction->flag & SACTION_DRAWTIME) { uiDefButC(block, MENU, B_REDR, "Auto-Snap Keyframes %t|No Snap %x0|Second Step %x1|Nearest Second %x2|Nearest Marker %x3", xco,yco,90,YIC, &(saction->autosnap), 0, 1, 0, 0, "Auto-snapping mode for keyframes when transforming"); } else { uiDefButC(block, MENU, B_REDR, "Auto-Snap Keyframes %t|No Snap %x0|Frame Step %x1|Nearest Frame %x2|Nearest Marker %x3", xco,yco,90,YIC, &(saction->autosnap), 0, 1, 0, 0, "Auto-snapping mode for keyframes when transforming"); } xco += (90 + 8); } /* COPY PASTE */ uiBlockBeginAlign(block); uiDefIconButO(block, BUT, "ACT_OT_copy", WM_OP_INVOKE_REGION_WIN, ICON_COPYDOWN, xco,yco,XIC,YIC, "Copies the selected keyframes to the buffer."); xco += XIC; uiDefIconButO(block, BUT, "ACT_OT_paste", WM_OP_INVOKE_REGION_WIN, ICON_PASTEDOWN, xco,yco,XIC,YIC, "Pastes the keyframes from the buffer into the selected channels."); uiBlockEndAlign(block); xco += (XIC + 8); } /* always as last */ UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, (int)(ar->v2d.tot.ymax-ar->v2d.tot.ymin)); 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); height = ((items * ACHANNEL_STEP) + (ACHANNEL_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, 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 */ ANIM_animdata_freelist(&anim_data); }
/* left hand part */ void graph_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, height; size_t items; int i = 0; /* 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 = (float)((items * ACHANNEL_STEP) + (ACHANNEL_HEIGHT * 2)); UI_view2d_totRect_set(v2d, ar->winx, height); /* 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, i = 0; ale; ale = ale->next, i++) { const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF); const 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; /* set blending again, as may not be set in previous step */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) { const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF); const 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); glDisable(GL_BLEND); } /* free tempolary channels */ BLI_freelistN(&anim_data); }