void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop) { /* button to quickly show texture in texture tab */ SpaceButs *sbuts = CTX_wm_space_buts(C); ButsContextTexture *ct = (sbuts) ? sbuts->texuser : NULL; ButsTextureUser *user; /* only show button in other tabs in properties editor */ if (!ct || sbuts->mainb == BCONTEXT_TEXTURE) return; /* find corresponding texture user */ for (user = ct->users.first; user; user = user->next) if (user->ptr.data == ptr->data && user->prop == prop) break; /* draw button */ if (user) { uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_BUTS, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Show texture in texture tab"); UI_but_func_set(but, template_texture_show, user->ptr.data, user->prop); } }
void buttons_context_draw(const bContext *C, uiLayout *layout) { SpaceButs *sbuts = CTX_wm_space_buts(C); ButsContextPath *path = sbuts->path; uiLayout *row; uiBlock *block; uiBut *but; PointerRNA *ptr; char namebuf[128], *name; int a, icon; if (!path) return; row = uiLayoutRow(layout, true); uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); block = uiLayoutGetBlock(row); UI_block_emboss_set(block, UI_EMBOSS_NONE); but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag, 0, 0, 0, 0, TIP_("Follow context or keep fixed datablock displayed")); UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */ UI_but_func_set(but, pin_cb, NULL, NULL); for (a = 0; a < path->len; a++) { ptr = &path->ptr[a]; if (a != 0) uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC); if (ptr->data) { icon = RNA_struct_ui_icon(ptr->type); name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL); if (name) { if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene) uiItemLDrag(row, ptr, "", icon); /* save some space */ else uiItemLDrag(row, ptr, name, icon); if (name != namebuf) MEM_freeN(name); } else uiItemL(row, "", icon); } } }
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_draw_tree_element(bContext *C, uiBlock *block, ARegion *ar, SpaceLDB *slivedb, LiveDbTreeElement *te, int startx, int *starty, int *row_num) { LiveDbTreeElement *ten; float ufac = UI_UNIT_X / 20.0f; int offsx = 0, active = 0; int CUR_UNIT_Y; if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) CUR_UNIT_Y = UI_UNIT_Y; else CUR_UNIT_Y = MAT_LIVEDB_UI_UNIT_Y; *starty -= CUR_UNIT_Y; ++ *row_num; if (*starty + 2 * CUR_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) { int xmax = ar->v2d.cur.xmax; unsigned char alpha = 128; /* icons can be ui buts, we don't want it to overlap with material previews */ if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_MATERIAL) xmax -= MAT_LIVEDB_UI_UNIT_Y; glEnable(GL_BLEND); if(*row_num % 2) { UI_ThemeColorShade(TH_BACK, 6); glRecti(0, *starty + 1, ar->v2d.cur.xmax, *starty + CUR_UNIT_Y - 1); } if (*te->flag & TE_SELECTED) { float col[4]; unsigned char col_circle[4]; UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col); glColor3fv(col); glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + CUR_UNIT_Y - 1); /* active circle */ UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col_circle); col_circle[3] = alpha; glColor4ubv((GLubyte *)col_circle); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox((float)startx + UI_UNIT_X - ufac, (float)*starty + (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY ? 1.0f : UI_UNIT_Y * 3), (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac, (float)*starty + CUR_UNIT_Y - 1.0f * ufac, UI_UNIT_Y / 2.0f - 1.0f * ufac); glEnable(GL_BLEND); /* roundbox disables it */ } /* start by highlighting search matches */ if (SEARCHING_MAT_LIVEDB(slivedb) && (*te->flag & TE_SEARCHMATCH)) { char col[4]; UI_GetThemeColorType4ubv(TH_MATCH, SPACE_MAT_LIVEDB, col); col[3] = alpha; glColor4ubv((GLubyte *)col); glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + CUR_UNIT_Y - 1); } /* open/close icon, only when sublevels */ if (te->subtree.first || (*te->flag & TE_LAZY_CLOSED)) { int icon_x; if (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) icon_x = startx; else icon_x = startx + 5 * ufac; if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_DOWN); else UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_RIGHT); } offsx += UI_UNIT_X; /* Element type icon */ if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) mat_livedb_elem_draw_icon((float)startx + offsx, (float)*starty, te); else mat_livedb_elem_draw_icon((float)startx + offsx, (float)*starty + UI_UNIT_X * 3, te); offsx += UI_UNIT_X; glDisable(GL_BLEND); /* name */ if (active == 1) UI_ThemeColor(TH_TEXT_HI); else UI_ThemeColor(TH_TEXT); if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + 5 * ufac, te->name); else { uiBut *bt; UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + UI_UNIT_X * 3 + 5 * ufac, te->name); UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + UI_UNIT_X * 2 + 5 * ufac, te->nick_name); UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + UI_UNIT_X + 5 * ufac, te->copyright); bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_WORLD, xmax - UI_UNIT_X - 3, *starty + 1 * ufac, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5f, "Get item"); UI_but_func_set(bt, get_material_cb, (void*)slivedb->server_address, (void*)te->item->mat_item.id); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(UI_FSTYLE_WIDGET, te->name)); /* Closed item, we draw the category-info icons */ if (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY && !MAT_LIVEDB_ELEM_OPEN(te, slivedb)) { if (te->subtree.first) { int tempx = startx + offsx; /* divider */ UI_ThemeColorShade(TH_BACK, -40); glRecti(tempx - 10.0f * ufac, *starty + 4.0f * ufac, tempx - 8.0f * ufac, *starty + CUR_UNIT_Y - 4.0f * ufac); glEnable(GL_BLEND); glPixelTransferf(GL_ALPHA_SCALE, 0.5); mat_livedb_draw_content_count_icons(&te->subtree, xmax, &tempx, *starty); glPixelTransferf(GL_ALPHA_SCALE, 1.0); glDisable(GL_BLEND); } } } /* store coord and continue, we need coordinates for elements outside view too */ te->xs = (float)startx; te->ys = (float)*starty; te->xend = startx + offsx; if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) { for (ten = te->subtree.first; ten; ten = ten->next) mat_livedb_draw_tree_element(C, block, ar, slivedb, ten, startx + UI_UNIT_X, starty, row_num); } else { for (ten = te->subtree.first; ten; ten = ten->next) mat_livedb_set_coord_tree_element(slivedb, te, startx, starty); } } /* mat_livedb_draw_tree_element() */
/* driver settings for active F-Curve (only for 'Drivers' mode) */ static void graph_panel_drivers(const bContext *C, Panel *pa) { bAnimListElem *ale; FCurve *fcu; ChannelDriver *driver; DriverVar *dvar; PointerRNA driver_ptr; uiLayout *col; uiBlock *block; uiBut *but; /* Get settings from context */ if (!graph_panel_context(C, &ale, &fcu)) return; driver = fcu->driver; /* set event handler for panel */ block = uiLayoutGetBlock(pa->layout); // xxx? UI_block_func_handle_set(block, do_graph_region_driver_buttons, NULL); /* general actions - management */ col = uiLayoutColumn(pa->layout, false); block = uiLayoutGetBlock(col); but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_FILE_REFRESH, IFACE_("Update Dependencies"), 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, TIP_("Force updates of dependencies")); UI_but_func_set(but, driver_update_flags_cb, fcu, NULL); but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMOUT, IFACE_("Remove Driver"), 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, TIP_("Remove this driver")); UI_but_funcN_set(but, driver_remove_cb, MEM_dupallocN(ale), NULL); /* driver-level settings - type, expressions, and errors */ RNA_pointer_create(ale->id, &RNA_Driver, driver, &driver_ptr); col = uiLayoutColumn(pa->layout, true); block = uiLayoutGetBlock(col); uiItemR(col, &driver_ptr, "type", 0, NULL, ICON_NONE); /* show expression box if doing scripted drivers, and/or error messages when invalid drivers exist */ if (driver->type == DRIVER_TYPE_PYTHON) { bool bpy_data_expr_error = (strstr(driver->expression, "bpy.data.") != NULL); bool bpy_ctx_expr_error = (strstr(driver->expression, "bpy.context.") != NULL); /* expression */ uiItemR(col, &driver_ptr, "expression", 0, IFACE_("Expr"), ICON_NONE); /* errors? */ if ((G.f & G_SCRIPT_AUTOEXEC) == 0) { uiItemL(col, IFACE_("ERROR: Python auto-execution disabled"), ICON_CANCEL); } else if (driver->flag & DRIVER_FLAG_INVALID) { uiItemL(col, IFACE_("ERROR: Invalid Python expression"), ICON_CANCEL); } /* Explicit bpy-references are evil. Warn about these to prevent errors */ /* TODO: put these in a box? */ if (bpy_data_expr_error || bpy_ctx_expr_error) { uiItemL(col, IFACE_("WARNING: Driver expression may not work correctly"), ICON_HELP); if (bpy_data_expr_error) { uiItemL(col, IFACE_("TIP: Use variables instead of bpy.data paths (see below)"), ICON_ERROR); } if (bpy_ctx_expr_error) { uiItemL(col, IFACE_("TIP: bpy.context is not safe for renderfarm usage"), ICON_ERROR); } } } else { /* errors? */ if (driver->flag & DRIVER_FLAG_INVALID) uiItemL(col, IFACE_("ERROR: Invalid target channel(s)"), ICON_ERROR); /* Warnings about a lack of variables * NOTE: The lack of variables is generally a bad thing, since it indicates * that the driver doesn't work at all. This particular scenario arises * primarily when users mistakenly try to use drivers for procedural * property animation */ if (BLI_listbase_is_empty(&driver->variables)) { uiItemL(col, IFACE_("ERROR: Driver is useless without any inputs"), ICON_ERROR); if (!BLI_listbase_is_empty(&fcu->modifiers)) { uiItemL(col, IFACE_("TIP: Use F-Curves for procedural animation instead"), ICON_INFO); uiItemL(col, IFACE_("F-Modifiers can generate curves for those too"), ICON_INFO); } } } col = uiLayoutColumn(pa->layout, true); if (driver->type == DRIVER_TYPE_PYTHON) { uiItemR(col, &driver_ptr, "use_self", 0, NULL, ICON_NONE); } /* debug setting */ uiItemR(col, &driver_ptr, "show_debug_info", 0, NULL, ICON_NONE); /* value of driver */ if (driver->flag & DRIVER_FLAG_SHOWDEBUG) { uiLayout *row = uiLayoutRow(col, true); char valBuf[32]; uiItemL(row, IFACE_("Driver Value:"), ICON_NONE); BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", driver->curval); uiItemL(row, valBuf, ICON_NONE); } /* add/copy/paste driver variables */ { uiLayout *row; /* add driver variable */ row = uiLayoutRow(pa->layout, false); block = uiLayoutGetBlock(row); but = uiDefIconTextBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ZOOMIN, IFACE_("Add Variable"), 0, 0, 10 * UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, TIP_("Driver variables ensure that all dependencies will be accounted for and that drivers will update correctly")); UI_but_func_set(but, driver_add_var_cb, driver, NULL); /* copy/paste (as sub-row) */ row = uiLayoutRow(row, true); block = uiLayoutGetBlock(row); uiItemO(row, "", ICON_COPYDOWN, "GRAPH_OT_driver_variables_copy"); uiItemO(row, "", ICON_PASTEDOWN, "GRAPH_OT_driver_variables_paste"); } /* loop over targets, drawing them */ for (dvar = driver->variables.first; dvar; dvar = dvar->next) { PointerRNA dvar_ptr; uiLayout *box, *row; uiLayout *subrow, *sub; /* sub-layout column for this variable's settings */ col = uiLayoutColumn(pa->layout, true); /* 1) header panel */ box = uiLayoutBox(col); RNA_pointer_create(ale->id, &RNA_DriverVariable, dvar, &dvar_ptr); row = uiLayoutRow(box, false); block = uiLayoutGetBlock(row); /* 1.1) variable type and name */ subrow = uiLayoutRow(row, true); /* 1.1.1) variable type */ sub = uiLayoutRow(subrow, true); /* HACK: special group just for the enum, otherwise we */ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); /* we get ugly layout with text included too... */ uiItemR(sub, &dvar_ptr, "type", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); /* 1.1.2) variable name */ sub = uiLayoutRow(subrow, true); /* HACK: special group to counteract the effects of the previous */ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); /* enum, which now pushes everything too far right */ uiItemR(sub, &dvar_ptr, "name", 0, "", ICON_NONE); /* 1.2) invalid name? */ UI_block_emboss_set(block, UI_EMBOSS_NONE); if (dvar->flag & DVAR_FLAG_INVALID_NAME) { but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_ERROR, 290, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Invalid variable name, click here for details")); UI_but_func_set(but, driver_dvar_invalid_name_query_cb, dvar, NULL); // XXX: reports? } /* 1.3) remove button */ but = uiDefIconBut(block, UI_BTYPE_BUT, B_IPO_DEPCHANGE, ICON_X, 290, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, IFACE_("Delete target variable")); UI_but_func_set(but, driver_delete_var_cb, driver, dvar); UI_block_emboss_set(block, UI_EMBOSS); /* 2) variable type settings */ box = uiLayoutBox(col); /* controls to draw depends on the type of variable */ switch (dvar->type) { case DVAR_TYPE_SINGLE_PROP: /* single property */ graph_panel_driverVar__singleProp(box, ale->id, dvar); break; case DVAR_TYPE_ROT_DIFF: /* rotational difference */ graph_panel_driverVar__rotDiff(box, ale->id, dvar); break; case DVAR_TYPE_LOC_DIFF: /* location difference */ graph_panel_driverVar__locDiff(box, ale->id, dvar); break; case DVAR_TYPE_TRANSFORM_CHAN: /* transform channel */ graph_panel_driverVar__transChan(box, ale->id, dvar); break; } /* 3) value of variable */ if (driver->flag & DRIVER_FLAG_SHOWDEBUG) { char valBuf[32]; box = uiLayoutBox(col); row = uiLayoutRow(box, true); uiItemL(row, IFACE_("Value:"), ICON_NONE); if ((dvar->type == DVAR_TYPE_ROT_DIFF) || (dvar->type == DVAR_TYPE_TRANSFORM_CHAN && dvar->targets[0].transChan >= DTAR_TRANSCHAN_ROTX && dvar->targets[0].transChan < DTAR_TRANSCHAN_SCALEX)) { BLI_snprintf(valBuf, sizeof(valBuf), "%.3f (%4.1f°)", dvar->curval, RAD2DEGF(dvar->curval)); } else { BLI_snprintf(valBuf, sizeof(valBuf), "%.3f", dvar->curval); } uiItemL(row, valBuf, ICON_NONE); } } /* cleanup */ MEM_freeN(ale); }
static void graph_panel_key_properties(const bContext *C, Panel *pa) { bAnimListElem *ale; FCurve *fcu; BezTriple *bezt, *prevbezt; uiLayout *layout = pa->layout; uiLayout *col; uiBlock *block; if (!graph_panel_context(C, &ale, &fcu)) return; block = uiLayoutGetBlock(layout); /* UI_block_func_handle_set(block, do_graph_region_buttons, NULL); */ /* only show this info if there are keyframes to edit */ if (get_active_fcurve_keyframe_edit(fcu, &bezt, &prevbezt)) { PointerRNA bezt_ptr, id_ptr, fcu_prop_ptr; PropertyRNA *fcu_prop = NULL; uiBut *but; int unit = B_UNIT_NONE; /* RNA pointer to keyframe, to allow editing */ RNA_pointer_create(ale->id, &RNA_Keyframe, bezt, &bezt_ptr); /* get property that F-Curve affects, for some unit-conversion magic */ RNA_id_pointer_create(ale->id, &id_ptr); if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &fcu_prop_ptr, &fcu_prop)) { /* determine the unit for this property */ unit = RNA_SUBTYPE_UNIT(RNA_property_subtype(fcu_prop)); } /* interpolation */ col = uiLayoutColumn(layout, false); if (fcu->flag & FCURVE_DISCRETE_VALUES) { uiLayout *split = uiLayoutSplit(col, 0.33f, true); uiItemL(split, IFACE_("Interpolation:"), ICON_NONE); uiItemL(split, IFACE_("None for Enum/Boolean"), ICON_IPO_CONSTANT); } else { uiItemR(col, &bezt_ptr, "interpolation", 0, NULL, ICON_NONE); } /* easing type */ if (bezt->ipo > BEZT_IPO_BEZ) uiItemR(col, &bezt_ptr, "easing", 0, NULL, 0); /* easing extra */ switch (bezt->ipo) { case BEZT_IPO_BACK: col = uiLayoutColumn(layout, 1); uiItemR(col, &bezt_ptr, "back", 0, NULL, 0); break; case BEZT_IPO_ELASTIC: col = uiLayoutColumn(layout, 1); uiItemR(col, &bezt_ptr, "amplitude", 0, NULL, 0); uiItemR(col, &bezt_ptr, "period", 0, NULL, 0); break; default: break; } /* numerical coordinate editing * - we use the button-versions of the calls so that we can attach special update handlers * and unit conversion magic that cannot be achieved using a purely RNA-approach */ col = uiLayoutColumn(layout, true); /* keyframe itself */ { uiItemL(col, IFACE_("Key:"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, IFACE_("Frame:"), 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "co", 0, 0, 0, -1, -1, NULL); UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, IFACE_("Value:"), 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "co", 1, 0, 0, -1, -1, NULL); UI_but_func_set(but, graphedit_activekey_update_cb, fcu, bezt); UI_but_unit_type_set(but, unit); } /* previous handle - only if previous was Bezier interpolation */ if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) { uiItemL(col, IFACE_("Left Handle:"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_left", 0, 0, 0, -1, -1, NULL); UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_left", 1, 0, 0, -1, -1, NULL); UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt); UI_but_unit_type_set(but, unit); /* XXX: with label? */ but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_left_type", 0, 0, 0, -1, -1, "Type of left handle"); UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); } /* next handle - only if current is Bezier interpolation */ if (bezt->ipo == BEZT_IPO_BEZ) { /* NOTE: special update callbacks are needed on the coords here due to T39911 */ uiItemL(col, IFACE_("Right Handle:"), ICON_NONE); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "X:", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_right", 0, 0, 0, -1, -1, NULL); UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); but = uiDefButR(block, UI_BTYPE_NUM, B_REDR, "Y:", 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_right", 1, 0, 0, -1, -1, NULL); UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt); UI_but_unit_type_set(but, unit); /* XXX: with label? */ but = uiDefButR(block, UI_BTYPE_MENU, B_REDR, NULL, 0, 0, UI_UNIT_X, UI_UNIT_Y, &bezt_ptr, "handle_right_type", 0, 0, 0, -1, -1, "Type of right handle"); UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt); } } else { if ((fcu->bezt == NULL) && (fcu->modifiers.first)) { /* modifiers only - so no keyframes to be active */ uiItemL(layout, IFACE_("F-Curve only has F-Modifiers"), ICON_NONE); uiItemL(layout, IFACE_("See Modifiers panel below"), ICON_INFO); } else if (fcu->fpt) { /* samples only */ uiItemL(layout, IFACE_("F-Curve doesn't have any keyframes as it only contains sampled points"), ICON_NONE); } else uiItemL(layout, IFACE_("No active keyframe on F-Curve"), ICON_NONE); } MEM_freeN(ale); }