From 2b446aa280af60aefd304aae904bc16b1b15f373 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 3 Aug 2011 01:22:31 +0000 Subject: 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) --- .../editors/animation/anim_channels_defines.c | 149 ++++++++++++++++++--- .../blender/editors/animation/anim_channels_edit.c | 106 +++++++++++++++ 2 files changed, 239 insertions(+), 16 deletions(-) (limited to 'source/blender/editors/animation') diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 4296d404cd3..f08b6e8b9a2 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -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 */ @@ -2108,17 +2157,17 @@ static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), int setting, short * switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return SPK_DS_EXPAND; - + case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ return ADT_NLA_EVAL_OFF; - + case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ *neg= 1; return ADT_CURVES_NOT_VISIBLE; - + case ACHANNEL_SETTING_SELECT: /* selected */ return ADT_UI_SELECTED; - + default: /* unsupported */ return 0; } @@ -2135,7 +2184,7 @@ static void *acf_dsspk_setting_ptr(bAnimListElem *ale, int setting, short *type) switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(spk->flag); - + case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ @@ -2143,7 +2192,7 @@ static void *acf_dsspk_setting_ptr(bAnimListElem *ale, int setting, short *type) GET_ACF_FLAG_PTR(spk->adt->flag) else return NULL; - + default: /* unsupported */ return NULL; } @@ -2153,15 +2202,16 @@ static void *acf_dsspk_setting_ptr(bAnimListElem *ale, int setting, short *type) static bAnimChannelType ACF_DSSPK= { "Speaker Expander", /* type name */ - + acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ 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 */ acf_dsspk_setting_flag, /* flag for setting */ acf_dsspk_setting_ptr /* pointer for 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 */ @@ -2450,7 +2532,7 @@ static void ANIM_init_channel_typeinfo_data (void) animchannelTypeInfo[type++]= &ACF_DSTEX; /* Texture Channel */ animchannelTypeInfo[type++]= &ACF_DSLAT; /* Lattice Channel */ animchannelTypeInfo[type++]= &ACF_DSSPK; /* Speaker Channel */ - + animchannelTypeInfo[type++]= &ACF_SHAPEKEY; /* ShapeKey */ animchannelTypeInfo[type++]= &ACF_GPD; /* Grease Pencil Datablock */ @@ -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 */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 8331001d98e..551bc7e263e 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -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); -- cgit v1.2.3