Animation channels can now be renamed by Ctrl-Clicking on them, as in

the Outliner

Channels which can be renamed include:
- Scenes, Objects, World, Material, Texture, etc. (i.e. "ID-blocks",
or the dark and light blue channels)
- Action Groups (green channels)
- Action expanders (i.e. "CubeAction", "WorldAction", etc.)
- Grease Pencil stuff

Channels which CANNOT be renamed, as they mostly use hardcoded values
or otherwise include:
- Drivers expander
- FCurves (they don't technically have a "name"; what is shown is just
a user-friendly representation of their rna_paths)
This commit is contained in:
Joshua Leung 2011-08-03 01:22:31 +00:00
parent 2f2a95efb8
commit 2b446aa280
7 changed files with 257 additions and 20 deletions

@ -325,6 +325,26 @@ static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
BLI_strncpy(name, id->name+2, ANIM_CHAN_NAME_SIZE);
}
/* name property for ID block entries */
static short acf_generic_idblock_nameprop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
RNA_id_pointer_create(ale->id, ptr);
*prop = RNA_struct_name_property(ptr->type);
return (*prop != NULL);
}
/* name property for ID block entries which are just subheading "fillers" */
static short acf_generic_idfill_nameprop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
/* actual ID we're representing is stored in ale->data not ale->id, as id gives the owner */
RNA_id_pointer_create(ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
return (*prop != NULL);
}
/* Settings ------------------------------------------- */
#if 0
@ -455,6 +475,7 @@ static bAnimChannelType ACF_SUMMARY =
NULL, /* offset */
acf_summary_name, /* name */
NULL, /* name prop */
acf_summary_icon, /* icon */
acf_summary_setting_valid, /* has setting */
@ -556,6 +577,7 @@ static bAnimChannelType ACF_SCENE =
NULL, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_scene_icon, /* icon */
acf_scene_setting_valid, /* has setting */
@ -702,6 +724,7 @@ static bAnimChannelType ACF_OBJECT =
NULL, /* offset */
acf_object_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_object_icon, /* icon */
acf_object_setting_valid, /* has setting */
@ -749,6 +772,15 @@ static void acf_group_name(bAnimListElem *ale, char *name)
BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE);
}
/* name property for group entries */
static short acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
return (*prop != NULL);
}
/* check if some setting exists for this channel */
static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
{
@ -819,6 +851,7 @@ static bAnimChannelType ACF_GROUP =
acf_generic_group_offset, /* offset */
acf_group_name, /* name */
acf_group_name_prop, /* name prop */
NULL, /* icon */
acf_group_setting_valid, /* has setting */
@ -905,6 +938,7 @@ static bAnimChannelType ACF_FCURVE =
acf_generic_group_offset, /* offset */
acf_fcurve_name, /* name */
NULL, /* name prop */
NULL, /* icon */
acf_fcurve_setting_valid, /* has setting */
@ -989,6 +1023,7 @@ static bAnimChannelType ACF_FILLACTD =
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idfill_nameprop, /* name prop */
acf_fillactd_icon, /* icon */
acf_fillactd_setting_valid, /* has setting */
@ -1067,6 +1102,7 @@ static bAnimChannelType ACF_FILLDRIVERS =
acf_generic_basic_offset, /* offset */
acf_filldrivers_name, /* name */
NULL, /* name prop */
acf_filldrivers_icon, /* icon */
acf_filldrivers_setting_valid, /* has setting */
@ -1144,6 +1180,7 @@ static bAnimChannelType ACF_DSMAT=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dsmat_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1220,6 +1257,7 @@ static bAnimChannelType ACF_DSLAM=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dslam_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1303,6 +1341,7 @@ static bAnimChannelType ACF_DSTEX=
acf_dstex_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idfill_nameprop, /* name prop */
acf_dstex_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1379,6 +1418,7 @@ static bAnimChannelType ACF_DSCAM=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idfill_nameprop, /* name prop */
acf_dscam_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1465,6 +1505,7 @@ static bAnimChannelType ACF_DSCUR=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dscur_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1541,6 +1582,7 @@ static bAnimChannelType ACF_DSSKEY=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dsskey_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1617,6 +1659,7 @@ static bAnimChannelType ACF_DSWOR=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idfill_nameprop, /* name prop */
acf_dswor_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1693,6 +1736,7 @@ static bAnimChannelType ACF_DSPART=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dspart_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1769,6 +1813,7 @@ static bAnimChannelType ACF_DSMBALL=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dsmball_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1845,6 +1890,7 @@ static bAnimChannelType ACF_DSARM=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dsarm_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -1932,6 +1978,7 @@ static bAnimChannelType ACF_DSNTREE=
acf_dsntree_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dsntree_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -2008,6 +2055,7 @@ static bAnimChannelType ACF_DSMESH=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dsmesh_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -2084,6 +2132,7 @@ static bAnimChannelType ACF_DSLAT=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dslat_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -2160,6 +2209,7 @@ static bAnimChannelType ACF_DSSPK=
acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idblock_nameprop, /* name prop */
acf_dsspk_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
@ -2184,6 +2234,22 @@ static void acf_shapekey_name(bAnimListElem *ale, char *name)
}
}
/* name property for ShapeKey entries */
static short acf_shapekey_nameprop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
KeyBlock *kb= (KeyBlock *)ale->data;
/* if the KeyBlock had a name, use it, otherwise use the index */
if (kb && kb->name[0]) {
RNA_pointer_create(ale->id, &RNA_ShapeKey, kb, ptr);
*prop = RNA_struct_name_property(ptr->type);
return (*prop != NULL);
}
return 0;
}
/* check if some setting exists for this channel */
static short acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
@ -2250,6 +2316,7 @@ static bAnimChannelType ACF_SHAPEKEY=
acf_generic_basic_offset, /* offset */
acf_shapekey_name, /* name */
acf_shapekey_nameprop, /* name prop */
NULL, /* icon */
acf_shapekey_setting_valid, /* has setting */
@ -2324,6 +2391,7 @@ static bAnimChannelType ACF_GPD =
acf_generic_group_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_generic_idfill_nameprop, /* name prop */
acf_gpd_icon, /* icon */
acf_gpd_setting_valid, /* has setting */
@ -2342,6 +2410,19 @@ static void acf_gpl_name(bAnimListElem *ale, char *name)
BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
}
/* name property for grease pencil layer entries */
static short acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
if (ale->data) {
RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
return (*prop != NULL);
}
return 0;
}
/* check if some setting exists for this channel */
static short acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
{
@ -2399,6 +2480,7 @@ static bAnimChannelType ACF_GPL =
acf_generic_group_offset, /* offset */
acf_gpl_name, /* name */
acf_gpl_name_prop, /* name prop */
NULL, /* icon */
acf_gpl_setting_valid, /* has setting */
@ -2642,6 +2724,8 @@ void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting
#define ICON_WIDTH 17
// XXX hardcoded width of sliders
#define SLIDER_WIDTH 80
// XXX hardcoded width of rename textboxes
#define RENAME_TEXT_WIDTH 100
/* Draw the given channel */
// TODO: make this use UI controls for the buttons
@ -2731,6 +2815,7 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float
}
/* step 5) draw name ............................................... */
// TODO: when renaming, we might not want to draw this, especially if name happens to be longer than channel
if (acf->name) {
char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
@ -2868,6 +2953,19 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void
BLI_freelistN(&anim_data);
}
/* callback for rename widgets - clear rename-in-progress */
static void achannel_setting_rename_done_cb(bContext *C, void *ads_poin, void *UNUSED(arg2))
{
bDopeSheet *ads = (bDopeSheet *)ads_poin;
/* reset rename index so that edit box disappears now that editing is done */
ads->renameIndex = 0;
/* send notifiers */
// XXX: right notifier?
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_RENAME, NULL);
}
/* callback for widget sliders - insert keyframes */
static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
{
@ -3060,12 +3158,11 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan
}
/* Draw UI widgets the given channel */
// TODO: make this use UI controls for the buttons
void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc)
void ANIM_channel_draw_widgets (bContext *C, bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc, size_t channel_index)
{
bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
View2D *v2d= &ac->ar->v2d;
float y, ymid /*, ytext*/;
float y, ymid/*, ytext*/;
short offset;
/* sanity checks - don't draw anything */
@ -3116,11 +3213,31 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
offset += ICON_WIDTH;
}
(void)offset;
}
/* step 4) draw text... */
/* NOTE: this is not done here, since nothing to be clicked on... */
/* step 4) draw text - check if renaming widget is in use... */
if (acf->name_prop && ac->ads) {
float channel_height = ymaxc - yminc;
/* if rename index matches, add widget for this */
if (ac->ads->renameIndex == channel_index+1) {
PointerRNA ptr;
PropertyRNA *prop;
/* draw renaming widget if we can get RNA pointer for it */
if (acf->name_prop(ale, &ptr, &prop)) {
uiBut *but;
uiBlockSetEmboss(block, UI_EMBOSS);
but = uiDefButR(block, TEX, 1, "", offset+3, yminc, RENAME_TEXT_WIDTH, channel_height, &ptr, RNA_property_identifier(prop), -1, 0, 0, -1, -1, NULL);
uiButSetFunc(but, achannel_setting_rename_done_cb, ac->ads, NULL);
uiButActiveOnly(C, block, but);
uiBlockSetEmboss(block, UI_EMBOSSN);
}
}
}
/* step 5) draw mute+protection toggles + (sliders) ....................... */
/* reset offset - now goes from RHS of panel */

@ -1965,6 +1965,107 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot)
WM_operator_properties_gesture_border(ot, FALSE);
}
/* ******************* Rename Operator ***************************** */
/* Allow renaming some channels by clicking on them */
static void rename_anim_channels (bAnimContext *ac, int channel_index)
{
ListBase anim_data = {NULL, NULL};
bAnimChannelType *acf;
bAnimListElem *ale;
int filter;
/* get the channel that was clicked on */
/* filter channels */
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get channel from index */
ale= BLI_findlink(&anim_data, channel_index);
if (ale == NULL) {
/* channel not found */
if (G.f & G_DEBUG)
printf("Error: animation channel (index = %d) not found in rename_anim_channels() \n", channel_index);
BLI_freelistN(&anim_data);
return;
}
/* check that channel can be renamed */
acf = ANIM_channel_get_typeinfo(ale);
if (acf && acf->name_prop) {
PointerRNA ptr;
PropertyRNA *prop;
/* ok if we can get name property to edit from this channel */
if (acf->name_prop(ale, &ptr, &prop)) {
/* actually showing the rename textfield is done on redraw,
* so here we just store the index of this channel in the
* dopesheet data, which will get utilised when drawing the
* channel...
*
* +1 factor is for backwards compat issues
*/
if (ac->ads) {
ac->ads->renameIndex = channel_index + 1;
}
}
}
/* free temp data and tag for refresh */
BLI_freelistN(&anim_data);
ED_region_tag_redraw(ac->ar);
}
static int animchannels_rename_invoke (bContext *C, wmOperator *op, wmEvent *evt)
{
bAnimContext ac;
ARegion *ar;
View2D *v2d;
int channel_index;
float x, y;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
/* get useful pointers from animation context data */
ar= ac.ar;
v2d= &ar->v2d;
/* figure out which channel user clicked in
* Note: although channels technically start at y= ACHANNEL_FIRST, we need to adjust by half a channel's height
* so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
* ACHANNEL_HEIGHT_HALF.
*/
UI_view2d_region_to_view(v2d, evt->mval[0], evt->mval[1], &x, &y);
if (ac.datatype == ANIMCONT_NLA) {
SpaceNla *snla = (SpaceNla *)ac.sl;
UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
}
else {
UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
}
/* handle click */
rename_anim_channels(&ac, channel_index);
return OPERATOR_FINISHED;
}
static void ANIM_OT_channels_rename (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Rename Channels";
ot->idname= "ANIM_OT_channels_rename";
ot->description= "Rename animation channel under mouse";
/* api callbacks */
ot->invoke= animchannels_rename_invoke;
ot->poll= animedit_poll_channels_active;
}
/* ******************** Mouse-Click Operator *********************** */
/* Handle selection changes due to clicking on channels. Settings will get caught by UI code... */
@ -2288,7 +2389,9 @@ void ED_operatortypes_animchannels(void)
{
WM_operatortype_append(ANIM_OT_channels_select_all_toggle);
WM_operatortype_append(ANIM_OT_channels_select_border);
WM_operatortype_append(ANIM_OT_channels_click);
WM_operatortype_append(ANIM_OT_channels_rename);
WM_operatortype_append(ANIM_OT_channels_setting_enable);
WM_operatortype_append(ANIM_OT_channels_setting_disable);
@ -2323,6 +2426,9 @@ void ED_keymap_animchannels(wmKeyConfig *keyconf)
RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend", 1);
RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_CTRL|KM_SHIFT, 0)->ptr, "children_only", 1);
/* rename */
WM_keymap_add_item(keymap, "ANIM_OT_channels_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
/* deselect all */
WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", AKEY, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "ANIM_OT_channels_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0)->ptr, "invert", 1);

@ -57,6 +57,9 @@ struct FModifier;
struct uiBlock;
struct uiLayout;
struct PointerRNA;
struct PropertyRNA;
/* ************************************************ */
/* ANIMATION CHANNEL FILTERING */
/* anim_filter.c */
@ -375,6 +378,8 @@ typedef struct bAnimChannelType {
/* get name (for channel lists) */
void (*name)(bAnimListElem *ale, char *name);
/* get RNA property+pointer for editing the name */
short (*name_prop)(bAnimListElem *ale, struct PointerRNA *ptr, struct PropertyRNA **prop);
/* get icon (for channel lists) */
int (*icon)(bAnimListElem *ale);
@ -401,7 +406,7 @@ void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level);
/* Draw the given channel */
void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc);
/* Draw the widgets for the given channel */
void ANIM_channel_draw_widgets(bAnimContext *ac, bAnimListElem *ale, struct uiBlock *block, float yminc, float ymaxc);
void ANIM_channel_draw_widgets(struct bContext *C, bAnimContext *ac, bAnimListElem *ale, struct uiBlock *block, float yminc, float ymaxc, size_t channel_index);
/* ------------------------ Editing API -------------------------- */

@ -122,6 +122,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
}
{ /* second pass: widgets */
uiBlock *block= uiBeginBlock(C, ar, "dopesheet channel buttons", UI_EMBOSS);
size_t channel_index = 0;
y= (float)ACHANNEL_FIRST;
@ -134,11 +135,12 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
{
/* draw all channels using standard channel-drawing API */
ANIM_channel_draw_widgets(ac, ale, block, yminc, ymaxc);
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);

@ -1006,6 +1006,7 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
}
{ /* second pass: widgets */
uiBlock *block= uiBeginBlock(C, ar, "graph channel buttons", UI_EMBOSS);
size_t channel_index = 0;
y= (float)ACHANNEL_FIRST;
@ -1022,11 +1023,12 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
{
/* draw all channels using standard channel-drawing API */
ANIM_channel_draw_widgets(ac, ale, block, yminc, ymaxc);
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);

@ -947,6 +947,7 @@ void draw_nla_channel_list (bContext *C, bAnimContext *ac, ARegion *ar)
}
{ /* second pass: UI widgets */
uiBlock *block= uiBeginBlock(C, ar, "NLA channel buttons", UI_EMBOSS);
size_t channel_index = 0;
y= (float)(-NLACHANNEL_HEIGHT(snla));
@ -964,11 +965,12 @@ void draw_nla_channel_list (bContext *C, bAnimContext *ac, ARegion *ar)
IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
{
/* draw all channels using standard channel-drawing API */
ANIM_channel_draw_widgets(ac, ale, block, yminc, ymaxc);
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);

@ -519,6 +519,9 @@ typedef struct bDopeSheet {
int filterflag; /* flags to use for filtering data */
int flag; /* standard flags */
int renameIndex; /* index+1 of channel to rename - only gets set by renaming operator */
int pad;
} bDopeSheet;