/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung * All rights reserved. * * Contributor(s): Joshua Leung * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/editors/animation/anim_channels_defines.c * \ingroup edanimation */ #include #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" #include "DNA_key_types.h" #include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_meta_types.h" #include "DNA_node_types.h" #include "DNA_world_types.h" #include "DNA_gpencil_types.h" #include "RNA_access.h" #include "BKE_curve.h" #include "BKE_key.h" #include "BKE_context.h" #include "BKE_utildefines.h" /* FILE_MAX */ #include "UI_interface.h" #include "UI_interface_icons.h" #include "UI_resources.h" #include "ED_anim_api.h" #include "ED_keyframing.h" #include "BIF_gl.h" #include "BIF_glutil.h" #include "WM_api.h" #include "WM_types.h" /* *********************************************** */ // XXX constant defines to be moved elsewhere? /* extra padding for lengths (to go under scrollers) */ #define EXTRA_SCROLL_PAD 100.0f /* size of indent steps */ #define INDENT_STEP_SIZE 7 #define ANIM_CHAN_NAME_SIZE 256 /* macros used for type defines */ /* get the pointer used for some flag */ #define GET_ACF_FLAG_PTR(ptr) \ { \ *type= sizeof((ptr)); \ return &(ptr); \ } /* *********************************************** */ /* Generic Functions (Type independent) */ /* Draw Backdrop ---------------------------------- */ /* get backdrop color for top-level widgets (Scene and Object only) */ static void acf_generic_root_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { /* darker blue for top-level widgets */ UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, color); } /* backdrop for top-level widgets (Scene and Object only) */ static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); glColor3fv(color); /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ uiSetRoundBox((expanded)? (1):(1|8)); uiDrawBox(GL_POLYGON, offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); } /* get backdrop color for data expanders under top-level Scene/Object */ static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { /* lighter color than top-level widget */ UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, color); } /* backdrop for data expanders under top-level Scene/Object */ static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); glColor3fv(color); /* no rounded corner - just rectangular box */ glRectf(offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc); } /* get backdrop color for generic channels */ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float *color) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); SpaceAction *saction = NULL; bActionGroup *grp = NULL; short indent= (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0; /* get context info needed... */ if ((ac->sa) && (ac->sa->spacetype == SPACE_ACTION)) saction= (SpaceAction *)ac->sa->spacedata.first; if (ale->type == ANIMTYPE_FCURVE) { FCurve *fcu= (FCurve *)ale->data; grp= fcu->grp; } /* set color for normal channels * - use 3 shades of color group/standard color for 3 indention level * - only use group colors if allowed to, and if actually feasible */ if ( (saction && !(saction->flag & SACTION_NODRAWGCOLORS)) && ((grp) && (grp->customCol)) ) { unsigned char cp[3]; if (indent == 2) { VECCOPY(cp, grp->cs.solid); } else if (indent == 1) { VECCOPY(cp, grp->cs.select); } else { VECCOPY(cp, grp->cs.active); } /* copy the colors over, transforming from bytes to floats */ rgb_byte_to_float(cp, color); } else { // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)? int colOfs= 20 - 20*indent; UI_GetThemeColorShade3fv(TH_HEADER, colOfs, color); } } /* backdrop for generic channels */ static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); glColor3fv(color); /* no rounded corners - just rectangular box */ glRectf(offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc); } /* Indention + Offset ------------------------------------------- */ /* indention level is always the value in the name */ static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 0; } static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 1; } #if 0 // XXX not used static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale) { return 2; } #endif /* indention which varies with the grouping status */ static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale) { short indent= 0; if (ale->id) { /* special exception for materials, textures, and particles */ // xxx should tex use indention 2? if (ELEM3(GS(ale->id->name),ID_MA,ID_PA,ID_TE)) indent++; } /* grouped F-Curves need extra level of indention */ if (ale->type == ANIMTYPE_FCURVE) { FCurve *fcu= (FCurve *)ale->data; // TODO: we need some way of specifying that the indention color should be one less... if (fcu->grp) indent++; } /* no indention */ return indent; } /* basic offset for channels derived from indention */ static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); if (acf && acf->get_indent_level) return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE; else return 0; } /* offset for groups + grouped entities */ static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale) { short offset= acf_generic_basic_offset(ac, ale); if (ale->id) { /* special exception for textures */ if (GS(ale->id->name) == ID_TE) { /* minimum offset */ offset += 21; /* special offset from owner type */ switch (ale->ownertype) { case ANIMTYPE_DSMAT: offset += 21; break; case ANIMTYPE_DSLAM: case ANIMTYPE_DSWOR: offset += 14; break; } } /* special exception for materials and particles */ else if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) offset += 21; /* if not in Action Editor mode, groupings must carry some offset too... */ else if (ac->datatype != ANIMCONT_ACTION) offset += 14; } /* offset is just the normal type - i.e. based on indention */ return offset; } /* Name ------------------------------------------- */ /* name for ID block entries */ static void acf_generic_idblock_name(bAnimListElem *ale, char *name) { ID *id= (ID *)ale->data; /* data pointed to should be an ID block */ /* just copy the name... */ if (id && name) BLI_strncpy(name, id->name+2, ANIM_CHAN_NAME_SIZE); } /* Settings ------------------------------------------- */ #if 0 /* channel type has no settings */ static short acf_generic_none_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) { return 0; } #endif /* check if some setting exists for this object-based data-expander (category only) */ static short acf_generic_dsexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) { switch (setting) { /* only expand supported everywhere */ case ACHANNEL_SETTING_EXPAND: return 1; /* visible * - only available in Graph Editor * - NOT available for 'filler' channels */ case ACHANNEL_SETTING_VISIBLE: if (ELEM3(ale->type, ANIMTYPE_FILLMATD, ANIMTYPE_FILLPARTD, ANIMTYPE_FILLTEXD)) return 0; else return ((ac) && (ac->spacetype == SPACE_IPO)); default: return 0; } } /* get pointer to the setting (category only) */ static void *acf_generic_dsexpand_setting_ptr(bAnimListElem *ale, int setting, short *type) { Object *ob= (Object *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(ob->nlaflag); // XXX default: /* unsupported */ return NULL; } } /* check if some setting exists for this object-based data-expander (datablock only) */ static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* expand is always supported */ case ACHANNEL_SETTING_EXPAND: return 1; /* mute is only supported for NLA */ case ACHANNEL_SETTING_MUTE: return ((ac) && (ac->spacetype == SPACE_NLA)); /* other flags are never supported */ default: return 0; } } /* *********************************************** */ /* Type Specific Functions + Defines */ /* Animation Summary ----------------------------------- */ /* get backdrop color for summary widget */ static void acf_summary_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { // FIXME: hardcoded color - same as the 'action' line in NLA // reddish color color[0] = 0.8f; color[1] = 0.2f; color[2] = 0.0f; } /* backdrop for summary widget */ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; float color[3]; /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); glColor3fv(color); /* rounded corners on LHS only * - top and bottom * - special hack: make the top a bit higher, since we are first... */ uiSetRoundBox((1|8)); uiDrawBox(GL_POLYGON, 0, yminc-2, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); } /* name for summary entries */ static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name) { if (name) BLI_strncpy(name, "DopeSheet Summary", ANIM_CHAN_NAME_SIZE); } // TODO: this is really a temp icon I think static int acf_summary_icon(bAnimListElem *UNUSED(ale)) { return ICON_BORDERMOVE; } /* check if some setting exists for this channel */ static short acf_summary_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { /* only expanded is supported, as it is used for hiding all stuff which the summary covers */ return (setting == ACHANNEL_SETTING_EXPAND); } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { if (setting == ACHANNEL_SETTING_EXPAND) { /* expanded */ *neg= 1; return ADS_FLAG_SUMMARY_COLLAPSED; } else { /* unsupported */ *neg= 0; return 0; } } /* get pointer to the setting */ static void *acf_summary_setting_ptr(bAnimListElem *ale, int setting, short *type) { bAnimContext *ac= (bAnimContext *)ale->data; /* if data is valid, return pointer to active dopesheet's relevant flag * - this is restricted to DopeSheet/Action Editor only */ if ((ac->sa) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) { SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first; bDopeSheet *ads= &saction->ads; /* return pointer to DopeSheet's flag */ GET_ACF_FLAG_PTR(ads->flag); } else { /* can't return anything useful - unsupported */ *type= 0; return NULL; } } /* all animation summary (DopeSheet only) type define */ static bAnimChannelType ACF_SUMMARY = { "Summary", /* type name */ acf_summary_color, /* backdrop color */ acf_summary_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ NULL, /* offset */ acf_summary_name, /* name */ acf_summary_icon, /* icon */ acf_summary_setting_valid, /* has setting */ acf_summary_setting_flag, /* flag for setting */ acf_summary_setting_ptr /* pointer for setting */ }; /* Scene ------------------------------------------- */ // TODO: just get this from RNA? static int acf_scene_icon(bAnimListElem *UNUSED(ale)) { return ICON_SCENE_DATA; } /* check if some setting exists for this channel */ static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* muted only in NLA */ case ACHANNEL_SETTING_MUTE: return ((ac) && (ac->spacetype == SPACE_NLA)); /* visible only in Graph Editor */ case ACHANNEL_SETTING_VISIBLE: return ((ac) && (ac->spacetype == SPACE_IPO)); /* only select and expand supported otherwise */ case ACHANNEL_SETTING_SELECT: case ACHANNEL_SETTING_EXPAND: return 1; default: return 0; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ return SCE_DS_SELECTED; case ACHANNEL_SETTING_EXPAND: /* expanded */ *neg= 1; return SCE_DS_COLLAPSED; 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; default: /* unsupported */ return 0; } } /* get pointer to the setting */ static void *acf_scene_setting_ptr(bAnimListElem *ale, int setting, short *type) { Scene *scene= (Scene *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ GET_ACF_FLAG_PTR(scene->flag); case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(scene->flag); case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (scene->adt) GET_ACF_FLAG_PTR(scene->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* scene type define */ static bAnimChannelType ACF_SCENE = { "Scene", /* type name */ acf_generic_root_color, /* backdrop color */ acf_generic_root_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ NULL, /* offset */ acf_generic_idblock_name, /* name */ acf_scene_icon, /* icon */ acf_scene_setting_valid, /* has setting */ acf_scene_setting_flag, /* flag for setting */ acf_scene_setting_ptr /* pointer for setting */ }; /* Object ------------------------------------------- */ static int acf_object_icon(bAnimListElem *ale) { Base *base= (Base *)ale->data; Object *ob= base->object; /* icon depends on object-type */ switch (ob->type) { case OB_LAMP: return ICON_OUTLINER_OB_LAMP; case OB_MESH: return ICON_OUTLINER_OB_MESH; case OB_CAMERA: return ICON_OUTLINER_OB_CAMERA; case OB_CURVE: return ICON_OUTLINER_OB_CURVE; case OB_MBALL: return ICON_OUTLINER_OB_META; case OB_LATTICE: return ICON_OUTLINER_OB_LATTICE; case OB_ARMATURE: return ICON_OUTLINER_OB_ARMATURE; case OB_FONT: return ICON_OUTLINER_OB_FONT; case OB_SURF: return ICON_OUTLINER_OB_SURFACE; case OB_EMPTY: return ICON_OUTLINER_OB_EMPTY; default: return ICON_OBJECT_DATA; } } /* name for object */ static void acf_object_name(bAnimListElem *ale, char *name) { Base *base= (Base *)ale->data; Object *ob= base->object; /* just copy the name... */ if (ob && name) BLI_strncpy(name, ob->id.name+2, ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) { Base *base= (Base *)ale->data; Object *ob= base->object; switch (setting) { /* muted only in NLA */ case ACHANNEL_SETTING_MUTE: return ((ac) && (ac->spacetype == SPACE_NLA)); /* visible only in Graph Editor */ case ACHANNEL_SETTING_VISIBLE: return ((ac) && (ac->spacetype == SPACE_IPO) && (ob->adt)); /* only select and expand supported otherwise */ case ACHANNEL_SETTING_SELECT: case ACHANNEL_SETTING_EXPAND: return 1; default: return 0; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_object_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ return SELECT; case ACHANNEL_SETTING_EXPAND: /* expanded */ *neg= 1; return OB_ADS_COLLAPSED; 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; default: /* unsupported */ return 0; } } /* get pointer to the setting */ static void *acf_object_setting_ptr(bAnimListElem *ale, int setting, short *type) { Base *base= (Base *)ale->data; Object *ob= base->object; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ GET_ACF_FLAG_PTR(ob->flag); case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(ob->nlaflag); // xxx case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (ob->adt) GET_ACF_FLAG_PTR(ob->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* object type define */ static bAnimChannelType ACF_OBJECT = { "Object", /* type name */ acf_generic_root_color, /* backdrop color */ acf_generic_root_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ NULL, /* offset */ acf_object_name, /* name */ acf_object_icon, /* icon */ acf_object_setting_valid, /* has setting */ acf_object_setting_flag, /* flag for setting */ acf_object_setting_ptr /* pointer for setting */ }; /* Group ------------------------------------------- */ /* get backdrop color for group widget */ static void acf_group_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float *color) { /* highlight only for action group channels */ if (ale->flag & AGRP_ACTIVE) UI_GetThemeColorShade3fv(TH_GROUP_ACTIVE, 10, color); else UI_GetThemeColorShade3fv(TH_GROUP, 20, color); } /* backdrop for group widget */ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0; short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0; float color[3]; /* set backdrop drawing color */ acf->get_backdrop_color(ac, ale, color); glColor3fv(color); /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ uiSetRoundBox((expanded)? (1):(1|8)); uiDrawBox(GL_POLYGON, offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8); } /* name for group entries */ static void acf_group_name(bAnimListElem *ale, char *name) { bActionGroup *agrp= (bActionGroup *)ale->data; /* just copy the name... */ if (agrp && name) BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting) { /* for now, all settings are supported, though some are only conditionally */ switch (setting) { case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */ return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO)); default: /* always supported */ return 1; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_group_setting_flag(bAnimContext *ac, int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ return AGRP_SELECTED; case ACHANNEL_SETTING_EXPAND: /* expanded */ { /* NOTE: Graph Editor uses a different flag to everywhere else for this, * allowing different collapsing of groups there, since sharing the flag * proved to be a hazard for workflows... */ return (ac->spacetype == SPACE_IPO) ? AGRP_EXPANDED_G : /* Graph Editor case */ AGRP_EXPANDED; /* DopeSheet and elsewhere */ } case ACHANNEL_SETTING_MUTE: /* muted */ return AGRP_MUTED; case ACHANNEL_SETTING_PROTECT: /* protected */ //*neg= 1; - if we change this to edtiability return AGRP_PROTECTED; case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */ *neg= 1; return AGRP_NOTVISIBLE; } /* this shouldn't happen */ return 0; } /* get pointer to the setting */ static void *acf_group_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) { bActionGroup *agrp= (bActionGroup *)ale->data; /* all flags are just in agrp->flag for now... */ GET_ACF_FLAG_PTR(agrp->flag); } /* group type define */ static bAnimChannelType ACF_GROUP = { "Group", /* type name */ acf_group_color, /* backdrop color */ acf_group_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_generic_group_offset, /* offset */ acf_group_name, /* name */ NULL, /* icon */ acf_group_setting_valid, /* has setting */ acf_group_setting_flag, /* flag for setting */ acf_group_setting_ptr /* pointer for setting */ }; /* F-Curve ------------------------------------------- */ /* name for fcurve entries */ static void acf_fcurve_name(bAnimListElem *ale, char *name) { getname_anim_fcurve(name, ale->id, ale->data); } /* check if some setting exists for this channel */ static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) { FCurve *fcu= (FCurve *)ale->data; switch (setting) { /* unsupported */ case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */ return 0; /* conditionally available */ case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */ if (fcu->bezt) return 1; else return 0; // NOTE: in this special case, we need to draw ICON_ZOOMOUT case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */ return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO)); /* always available */ default: return 1; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ return FCURVE_SELECTED; case ACHANNEL_SETTING_MUTE: /* muted */ return FCURVE_MUTED; case ACHANNEL_SETTING_PROTECT: /* protected */ //*neg= 1; - if we change this to edtiability return FCURVE_PROTECTED; case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */ return FCURVE_VISIBLE; default: /* unsupported */ return 0; } } /* get pointer to the setting */ static void *acf_fcurve_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) { FCurve *fcu= (FCurve *)ale->data; /* all flags are just in agrp->flag for now... */ GET_ACF_FLAG_PTR(fcu->flag); } /* fcurve type define */ static bAnimChannelType ACF_FCURVE = { "F-Curve", /* type name */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_flexible, /* indent level */ // xxx rename this to f-curves only? acf_generic_group_offset, /* offset */ acf_fcurve_name, /* name */ NULL, /* icon */ acf_fcurve_setting_valid, /* has setting */ acf_fcurve_setting_flag, /* flag for setting */ acf_fcurve_setting_ptr /* pointer for setting */ }; /* Object Action Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_fillactd_icon(bAnimListElem *UNUSED(ale)) { return ICON_ACTION; } /* check if some setting exists for this channel */ static short acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* only select and expand supported */ case ACHANNEL_SETTING_SELECT: case ACHANNEL_SETTING_EXPAND: return 1; default: return 0; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ return ADT_UI_SELECTED; case ACHANNEL_SETTING_EXPAND: /* expanded */ *neg= 1; return ACT_COLLAPSED; default: /* unsupported */ return 0; } } /* get pointer to the setting */ static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *type) { bAction *act= (bAction *)ale->data; AnimData *adt= ale->adt; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ if (adt) { GET_ACF_FLAG_PTR(adt->flag); } else return NULL; case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(act->flag); default: /* unsupported */ return NULL; } } /* object action expander type define */ static bAnimChannelType ACF_FILLACTD = { "Ob-Action Filler", /* 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_fillactd_icon, /* icon */ acf_fillactd_setting_valid, /* has setting */ acf_fillactd_setting_flag, /* flag for setting */ acf_fillactd_setting_ptr /* pointer for setting */ }; /* Drivers Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale)) { return ICON_ANIM_DATA; } static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name) { BLI_strncpy(name, "Drivers", ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ // TODO: this could be made more generic static short acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* only expand supported */ case ACHANNEL_SETTING_EXPAND: return 1; default: return 0; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ *neg= 1; return ADT_DRIVERS_COLLAPSED; default: /* unsupported */ return 0; } } /* get pointer to the setting */ static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, int setting, short *type) { AnimData *adt= (AnimData *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(adt->flag); default: /* unsupported */ return NULL; } } /* drivers expander type define */ static bAnimChannelType ACF_FILLDRIVERS = { "Drivers Filler", /* 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_filldrivers_name, /* name */ acf_filldrivers_icon, /* icon */ acf_filldrivers_setting_valid, /* has setting */ acf_filldrivers_setting_flag, /* flag for setting */ acf_filldrivers_setting_ptr /* pointer for setting */ }; /* Materials Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_fillmatd_icon(bAnimListElem *UNUSED(ale)) { return ICON_MATERIAL_DATA; } static void acf_fillmatd_name(bAnimListElem *UNUSED(ale), char *name) { BLI_strncpy(name, "Materials", ANIM_CHAN_NAME_SIZE); } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_fillmatd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return OB_ADS_SHOWMATS; default: /* unsupported */ return 0; } } /* materials expander type define */ static bAnimChannelType ACF_FILLMATD= { "Materials Filler", /* 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_fillmatd_name, /* name */ acf_fillmatd_icon, /* icon */ acf_generic_dsexpand_setting_valid, /* has setting */ acf_fillmatd_setting_flag, /* flag for setting */ acf_generic_dsexpand_setting_ptr /* pointer for setting */ }; /* Particles Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_fillpartd_icon(bAnimListElem *UNUSED(ale)) { return ICON_PARTICLE_DATA; } static void acf_fillpartd_name(bAnimListElem *UNUSED(ale), char *name) { BLI_strncpy(name, "Particles", ANIM_CHAN_NAME_SIZE); } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_fillpartd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return OB_ADS_SHOWPARTS; default: /* unsupported */ return 0; } } /* particles expander type define */ static bAnimChannelType ACF_FILLPARTD= { "Particles Filler", /* 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_fillpartd_name, /* name */ acf_fillpartd_icon, /* icon */ acf_generic_dsexpand_setting_valid, /* has setting */ acf_fillpartd_setting_flag, /* flag for setting */ acf_generic_dsexpand_setting_ptr /* pointer for setting */ }; /* Textures Expander ------------------------------------------- */ /* offset for groups + grouped entities */ static short acf_filltexd_offset(bAnimContext *ac, bAnimListElem *ale) { short offset= acf_generic_basic_offset(ac, ale); if (ale->id) { /* materials */ switch (GS(ale->id->name)) { case ID_MA: offset += 21; break; case ID_LA: case ID_WO: offset += 14; break; } } return offset; } // TODO: just get this from RNA? static int acf_filltexd_icon(bAnimListElem *UNUSED(ale)) { return ICON_TEXTURE_DATA; } static void acf_filltexd_name(bAnimListElem *UNUSED(ale), char *name) { BLI_strncpy(name, "Textures", ANIM_CHAN_NAME_SIZE); } /* get pointer to the setting (category only) */ static void *acf_filltexd_setting_ptr(bAnimListElem *ale, int setting, short *type) { ID *id= (ID *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ { switch (GS(id->name)) { case ID_MA: { Material *ma= (Material *)id; GET_ACF_FLAG_PTR(ma->flag); } case ID_LA: { Lamp *la= (Lamp *)id; GET_ACF_FLAG_PTR(la->flag); } case ID_WO: { World *wo= (World *)id; GET_ACF_FLAG_PTR(wo->flag); } } } default: /* unsupported */ return NULL; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_filltexd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ /* NOTE: the exact same flag must be used for other texture stack types too! */ return MA_DS_SHOW_TEXS; default: /* unsupported */ return 0; } } /* particles expander type define */ static bAnimChannelType ACF_FILLTEXD= { "Textures Filler", /* type name */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_flexible, /* indent level */ acf_filltexd_offset, /* offset */ acf_filltexd_name, /* name */ acf_filltexd_icon, /* icon */ acf_generic_dsexpand_setting_valid, /* has setting */ acf_filltexd_setting_flag, /* flag for setting */ acf_filltexd_setting_ptr /* pointer for setting */ }; /* Material Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dsmat_icon(bAnimListElem *UNUSED(ale)) { return ICON_MATERIAL_DATA; } /* offset for material expanders */ static short acf_dsmat_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale)) { return 21; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return MA_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; } } /* get pointer to the setting */ static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type) { Material *ma= (Material *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(ma->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (ma->adt) GET_ACF_FLAG_PTR(ma->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* material expander type define */ static bAnimChannelType ACF_DSMAT= { "Material Data Expander", /* type name */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_dsmat_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_dsmat_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dsmat_setting_flag, /* flag for setting */ acf_dsmat_setting_ptr /* pointer for setting */ }; /* Lamp Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dslam_icon(bAnimListElem *UNUSED(ale)) { return ICON_LAMP_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return LA_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; } } /* get pointer to the setting */ static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type) { Lamp *la= (Lamp *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(la->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (la->adt) GET_ACF_FLAG_PTR(la->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* lamp expander type define */ static bAnimChannelType ACF_DSLAM= { "Lamp 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_dslam_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dslam_setting_flag, /* flag for setting */ acf_dslam_setting_ptr /* pointer for setting */ }; /* Texture Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dstex_icon(bAnimListElem *UNUSED(ale)) { return ICON_TEXTURE_DATA; } /* offset for texture expanders */ static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *ale) { short offset = 21; /* special offset from owner type */ // FIXME: too much now! switch (ale->ownertype) { case ANIMTYPE_DSMAT: offset += 14; case ANIMTYPE_DSLAM: case ANIMTYPE_DSWOR: offset += 7; } return offset; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return TEX_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; } } /* get pointer to the setting */ static void *acf_dstex_setting_ptr(bAnimListElem *ale, int setting, short *type) { Tex *tex= (Tex *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(tex->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (tex->adt) GET_ACF_FLAG_PTR(tex->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* material expander type define */ static bAnimChannelType ACF_DSTEX= { "Texture Data Expander", /* type name */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_dstex_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_dstex_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dstex_setting_flag, /* flag for setting */ acf_dstex_setting_ptr /* pointer for setting */ }; /* Camera Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dscam_icon(bAnimListElem *UNUSED(ale)) { return ICON_CAMERA_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return CAM_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; } } /* get pointer to the setting */ static void *acf_dscam_setting_ptr(bAnimListElem *ale, int setting, short *type) { Camera *ca= (Camera *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(ca->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (ca->adt) GET_ACF_FLAG_PTR(ca->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* camera expander type define */ static bAnimChannelType ACF_DSCAM= { "Camera 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_dscam_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dscam_setting_flag, /* flag for setting */ acf_dscam_setting_ptr /* pointer for setting */ }; /* Curve Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dscur_icon(bAnimListElem *ale) { Curve *cu= (Curve *)ale->data; short obtype= curve_type(cu); switch (obtype) { case OB_FONT: return ICON_FONT_DATA; case OB_SURF: return ICON_SURFACE_DATA; default: return ICON_CURVE_DATA; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return CU_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; } } /* get pointer to the setting */ static void *acf_dscur_setting_ptr(bAnimListElem *ale, int setting, short *type) { Curve *cu= (Curve *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(cu->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (cu->adt) GET_ACF_FLAG_PTR(cu->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* curve expander type define */ static bAnimChannelType ACF_DSCUR= { "Curve 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_dscur_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dscur_setting_flag, /* flag for setting */ acf_dscur_setting_ptr /* pointer for setting */ }; /* Shape Key Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dsskey_icon(bAnimListElem *UNUSED(ale)) { return ICON_SHAPEKEY_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return KEY_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; } } /* get pointer to the setting */ static void *acf_dsskey_setting_ptr(bAnimListElem *ale, int setting, short *type) { Key *key= (Key *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(key->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (key->adt) GET_ACF_FLAG_PTR(key->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* shapekey expander type define */ static bAnimChannelType ACF_DSSKEY= { "Shape Key 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_dsskey_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dsskey_setting_flag, /* flag for setting */ acf_dsskey_setting_ptr /* pointer for setting */ }; /* World Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dswor_icon(bAnimListElem *UNUSED(ale)) { return ICON_WORLD_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return WO_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; } } /* get pointer to the setting */ static void *acf_dswor_setting_ptr(bAnimListElem *ale, int setting, short *type) { World *wo= (World *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(wo->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (wo->adt) GET_ACF_FLAG_PTR(wo->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* world expander type define */ static bAnimChannelType ACF_DSWOR= { "World 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_dswor_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dswor_setting_flag, /* flag for setting */ acf_dswor_setting_ptr /* pointer for setting */ }; /* Particle Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dspart_icon(bAnimListElem *UNUSED(ale)) { return ICON_PARTICLE_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return PART_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; } } /* get pointer to the setting */ static void *acf_dspart_setting_ptr(bAnimListElem *ale, int setting, short *type) { ParticleSettings *part= (ParticleSettings *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(part->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (part->adt) GET_ACF_FLAG_PTR(part->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* particle expander type define */ static bAnimChannelType ACF_DSPART= { "Particle Data 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_dspart_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dspart_setting_flag, /* flag for setting */ acf_dspart_setting_ptr /* pointer for setting */ }; /* MetaBall Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dsmball_icon(bAnimListElem *UNUSED(ale)) { return ICON_META_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return MB_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; } } /* get pointer to the setting */ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *type) { MetaBall *mb= (MetaBall *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(mb->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (mb->adt) GET_ACF_FLAG_PTR(mb->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* metaball expander type define */ static bAnimChannelType ACF_DSMBALL= { "Metaball 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_dsmball_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dsmball_setting_flag, /* flag for setting */ acf_dsmball_setting_ptr /* pointer for setting */ }; /* Armature Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dsarm_icon(bAnimListElem *UNUSED(ale)) { return ICON_ARMATURE_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return ARM_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; } } /* get pointer to the setting */ static void *acf_dsarm_setting_ptr(bAnimListElem *ale, int setting, short *type) { bArmature *arm= (bArmature *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(arm->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (arm->adt) GET_ACF_FLAG_PTR(arm->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* metaball expander type define */ static bAnimChannelType ACF_DSARM= { "Armature 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_dsarm_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dsarm_setting_flag, /* flag for setting */ acf_dsarm_setting_ptr /* pointer for setting */ }; /* NodeTree Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dsntree_icon(bAnimListElem *UNUSED(ale)) { return ICON_NODETREE; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return NTREE_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; } } /* get pointer to the setting */ static void *acf_dsntree_setting_ptr(bAnimListElem *ale, int setting, short *type) { bNodeTree *ntree= (bNodeTree *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(ntree->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (ntree->adt) GET_ACF_FLAG_PTR(ntree->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* node tree expander type define */ static bAnimChannelType ACF_DSNTREE= { "Node Tree Expander", /* type name */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ // XXX this only works for compositing acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_dsntree_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dsntree_setting_flag, /* flag for setting */ acf_dsntree_setting_ptr /* pointer for setting */ }; /* Mesh Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale)) { return ICON_MESH_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return ME_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; } } /* get pointer to the setting */ static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, int setting, short *type) { Mesh *me= (Mesh *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(me->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (me->adt) GET_ACF_FLAG_PTR(me->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* node tree expander type define */ static bAnimChannelType ACF_DSMESH= { "Mesh Expander", /* type name */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ // XXX this only works for compositing acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_dsmesh_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dsmesh_setting_flag, /* flag for setting */ acf_dsmesh_setting_ptr /* pointer for setting */ }; /* Lattice Expander ------------------------------------------- */ // TODO: just get this from RNA? static int acf_dslat_icon(bAnimListElem *UNUSED(ale)) { return ICON_LATTICE_DATA; } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ return LT_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; } } /* get pointer to the setting */ static void *acf_dslat_setting_ptr(bAnimListElem *ale, int setting, short *type) { Lattice *lt= (Lattice *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ GET_ACF_FLAG_PTR(lt->flag); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ if (lt->adt) GET_ACF_FLAG_PTR(lt->adt->flag) else return NULL; default: /* unsupported */ return NULL; } } /* node tree expander type define */ static bAnimChannelType ACF_DSLAT= { "Lattice Expander", /* type name */ acf_generic_dataexpand_color, /* backdrop color */ acf_generic_dataexpand_backdrop,/* backdrop */ acf_generic_indention_1, /* indent level */ // XXX this only works for compositing acf_generic_basic_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_dslat_icon, /* icon */ acf_generic_dataexpand_setting_valid, /* has setting */ acf_dslat_setting_flag, /* flag for setting */ acf_dslat_setting_ptr /* pointer for setting */ }; /* ShapeKey Entry ------------------------------------------- */ /* name for ShapeKey */ static void acf_shapekey_name(bAnimListElem *ale, char *name) { KeyBlock *kb= (KeyBlock *)ale->data; /* just copy the name... */ if (kb && name) { /* if the KeyBlock had a name, use it, otherwise use the index */ if (kb->name[0]) BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE); else BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, "Key %d", ale->index); } } /* check if some setting exists for this channel */ static short acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted */ case ACHANNEL_SETTING_PROTECT: /* protected */ return 1; /* nothing else is supported */ default: return 0; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_MUTE: /* mute */ return KEYBLOCK_MUTE; case ACHANNEL_SETTING_SELECT: /* selected */ return KEYBLOCK_SEL; case ACHANNEL_SETTING_PROTECT: /* locked */ return KEYBLOCK_LOCKED; default: /* unsupported */ return 0; } } /* get pointer to the setting */ static void *acf_shapekey_setting_ptr(bAnimListElem *ale, int setting, short *type) { KeyBlock *kb= (KeyBlock *)ale->data; /* clear extra return data first */ *type= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted */ case ACHANNEL_SETTING_PROTECT: /* protected */ GET_ACF_FLAG_PTR(kb->flag) default: /* unsupported */ return NULL; } } /* shapekey expander type define */ static bAnimChannelType ACF_SHAPEKEY= { "Shape Key", /* type name */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_generic_basic_offset, /* offset */ acf_shapekey_name, /* name */ NULL, /* icon */ acf_shapekey_setting_valid, /* has setting */ acf_shapekey_setting_flag, /* flag for setting */ acf_shapekey_setting_ptr /* pointer for setting */ }; /* GPencil Datablock ------------------------------------------- */ /* get backdrop color for gpencil datablock widget */ static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float *color) { /* these are ID-blocks, but not exactly standalone... */ UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, color); } // TODO: just get this from RNA? static int acf_gpd_icon(bAnimListElem *UNUSED(ale)) { return ICON_GREASEPENCIL; } /* check if some setting exists for this channel */ static short acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* only select and expand supported */ case ACHANNEL_SETTING_SELECT: case ACHANNEL_SETTING_EXPAND: return 1; default: return 0; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ return AGRP_SELECTED; case ACHANNEL_SETTING_EXPAND: /* expanded */ return GP_DATA_EXPAND; } /* this shouldn't happen */ return 0; } /* get pointer to the setting */ static void *acf_gpd_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) { bGPdata *gpd= (bGPdata *)ale->data; /* all flags are just in gpd->flag for now... */ GET_ACF_FLAG_PTR(gpd->flag); } /* gpencil datablock type define */ static bAnimChannelType ACF_GPD = { "GPencil Datablock", /* type name */ acf_gpd_color, /* backdrop color */ acf_group_backdrop, /* backdrop */ acf_generic_indention_0, /* indent level */ acf_generic_group_offset, /* offset */ acf_generic_idblock_name, /* name */ acf_gpd_icon, /* icon */ acf_gpd_setting_valid, /* has setting */ acf_gpd_setting_flag, /* flag for setting */ acf_gpd_setting_ptr /* pointer for setting */ }; /* GPencil Layer ------------------------------------------- */ /* name for grase pencil layer entries */ static void acf_gpl_name(bAnimListElem *ale, char *name) { bGPDlayer *gpl = (bGPDlayer *)ale->data; if (gpl && name) BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ static short acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting) { switch (setting) { /* unsupported */ case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */ case ACHANNEL_SETTING_VISIBLE: /* graph editor only */ return 0; /* always available */ default: return 1; } } /* get the appropriate flag(s) for the setting when it is valid */ static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) { /* clear extra return data first */ *neg= 0; switch (setting) { case ACHANNEL_SETTING_SELECT: /* selected */ return GP_LAYER_SELECT; case ACHANNEL_SETTING_MUTE: /* muted */ return GP_LAYER_HIDE; case ACHANNEL_SETTING_PROTECT: /* protected */ //*neg= 1; - if we change this to edtiability return GP_LAYER_LOCKED; default: /* unsupported */ return 0; } } /* get pointer to the setting */ static void *acf_gpl_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) { bGPDlayer *gpl= (bGPDlayer *)ale->data; /* all flags are just in agrp->flag for now... */ GET_ACF_FLAG_PTR(gpl->flag); } /* grease pencil layer type define */ static bAnimChannelType ACF_GPL = { "GPencil Layer", /* type name */ acf_generic_channel_color, /* backdrop color */ acf_generic_channel_backdrop, /* backdrop */ acf_generic_indention_flexible, /* indent level */ acf_generic_group_offset, /* offset */ acf_gpl_name, /* name */ NULL, /* icon */ acf_gpl_setting_valid, /* has setting */ acf_gpl_setting_flag, /* flag for setting */ acf_gpl_setting_ptr /* pointer for setting */ }; /* *********************************************** */ /* Type Registration and General Access */ /* These globals only ever get directly accessed in this file */ static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES]; static short ACF_INIT= 1; /* when non-zero, the list needs to be updated */ /* Initialise type info definitions */ static void ANIM_init_channel_typeinfo_data (void) { int type= 0; /* start initialising if necessary... */ if (ACF_INIT) { ACF_INIT= 0; animchannelTypeInfo[type++]= NULL; /* None */ animchannelTypeInfo[type++]= NULL; /* AnimData */ animchannelTypeInfo[type++]= NULL; /* Special */ animchannelTypeInfo[type++]= &ACF_SUMMARY; /* Motion Summary */ animchannelTypeInfo[type++]= &ACF_SCENE; /* Scene */ animchannelTypeInfo[type++]= &ACF_OBJECT; /* Object */ animchannelTypeInfo[type++]= &ACF_GROUP; /* Group */ animchannelTypeInfo[type++]= &ACF_FCURVE; /* F-Curve */ animchannelTypeInfo[type++]= &ACF_FILLACTD; /* Object Action Expander */ animchannelTypeInfo[type++]= &ACF_FILLDRIVERS; /* Drivers Expander */ animchannelTypeInfo[type++]= &ACF_FILLMATD; /* Materials Expander */ animchannelTypeInfo[type++]= &ACF_FILLPARTD; /* Particles Expander */ animchannelTypeInfo[type++]= &ACF_FILLTEXD; /* Textures Expander */ animchannelTypeInfo[type++]= &ACF_DSMAT; /* Material Channel */ animchannelTypeInfo[type++]= &ACF_DSLAM; /* Lamp Channel */ animchannelTypeInfo[type++]= &ACF_DSCAM; /* Camera Channel */ animchannelTypeInfo[type++]= &ACF_DSCUR; /* Curve Channel */ animchannelTypeInfo[type++]= &ACF_DSSKEY; /* ShapeKey Channel */ animchannelTypeInfo[type++]= &ACF_DSWOR; /* World Channel */ animchannelTypeInfo[type++]= &ACF_DSNTREE; /* NodeTree Channel */ animchannelTypeInfo[type++]= &ACF_DSPART; /* Particle Channel */ animchannelTypeInfo[type++]= &ACF_DSMBALL; /* MetaBall Channel */ animchannelTypeInfo[type++]= &ACF_DSARM; /* Armature Channel */ animchannelTypeInfo[type++]= &ACF_DSMESH; /* Mesh Channel */ animchannelTypeInfo[type++]= &ACF_DSTEX; /* Texture Channel */ animchannelTypeInfo[type++]= &ACF_DSLAT; /* Lattice Channel */ animchannelTypeInfo[type++]= &ACF_SHAPEKEY; /* ShapeKey */ animchannelTypeInfo[type++]= &ACF_GPD; /* Grease Pencil Datablock */ animchannelTypeInfo[type++]= &ACF_GPL; /* Grease Pencil Layer */ // TODO: these types still need to be implemented!!! // probably need a few extra flags for these special cases... animchannelTypeInfo[type++]= NULL; /* NLA Track */ animchannelTypeInfo[type++]= NULL; /* NLA Action */ } } /* Get type info from given channel type */ bAnimChannelType *ANIM_channel_get_typeinfo (bAnimListElem *ale) { /* santiy checks */ if (ale == NULL) return NULL; /* init the typeinfo if not available yet... */ ANIM_init_channel_typeinfo_data(); /* check if type is in bounds... */ if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES)) return animchannelTypeInfo[ale->type]; else return NULL; } /* --------------------------- */ /* Print debug info string for the given channel */ void ANIM_channel_debug_print_info (bAnimListElem *ale, short indent_level) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); /* print indents */ for (; indent_level > 0; indent_level--) printf(" "); /* print info */ if (acf) { char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ /* get UI name */ if (acf->name) acf->name(ale, name); else BLI_strncpy(name, "", sizeof(name)); /* print type name + ui name */ printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name); } else if (ale) printf("ChanType: \n", ale->type); else printf("\n"); } /* --------------------------- */ /* Check if some setting for a channel is enabled * Returns: 1 = On, 0 = Off, -1 = Invalid */ short ANIM_channel_setting_get (bAnimContext *ac, bAnimListElem *ale, int setting) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); /* 1) check that the setting exists for the current context */ if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) { /* 2) get pointer to check for flag in, and the flag to check for */ short negflag, ptrsize; int flag; void *ptr; flag= acf->setting_flag(ac, setting, &negflag); ptr= acf->setting_ptr(ale, setting, &ptrsize); /* check if flag is enabled */ if (ptr && flag) { switch (ptrsize) { case sizeof(int): /* integer pointer for setting */ { int *val= (int *)ptr; if (negflag) return ((*val) & flag) == 0; else return ((*val) & flag) != 0; } break; case sizeof(short): /* short pointer for setting */ { short *val= (short *)ptr; if (negflag) return ((*val) & flag) == 0; else return ((*val) & flag) != 0; } break; case sizeof(char): /* char pointer for setting */ { char *val= (char *)ptr; if (negflag) return ((*val) & flag) == 0; else return ((*val) & flag) != 0; } break; } } } /* not found... */ return -1; } /* quick macro for use in ANIM_channel_setting_set - set flag for setting according the mode given */ #define ACF_SETTING_SET(sval, sflag, smode) \ {\ if (negflag) {\ if (smode == ACHANNEL_SETFLAG_INVERT) (sval) ^= (sflag); \ else if (smode == ACHANNEL_SETFLAG_ADD) (sval) &= ~(sflag); \ else (sval) |= (sflag); \ } \ else {\ if (smode == ACHANNEL_SETFLAG_INVERT) (sval) ^= (sflag); \ else if (smode == ACHANNEL_SETFLAG_ADD) (sval) |= (sflag); \ else (sval) &= ~(sflag); \ }\ } /* Change value of some setting for a channel * - setting: eAnimChannel_Settings * - mode: eAnimChannels_SetFlag */ void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting, short mode) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); /* 1) check that the setting exists for the current context */ if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) { /* 2) get pointer to check for flag in, and the flag to check for */ short negflag, ptrsize; int flag; void *ptr; flag= acf->setting_flag(ac, setting, &negflag); ptr= acf->setting_ptr(ale, setting, &ptrsize); /* check if flag is enabled */ if (ptr && flag) { switch (ptrsize) { case sizeof(int): /* integer pointer for setting */ { int *val= (int *)ptr; ACF_SETTING_SET(*val, flag, mode); } break; case sizeof(short): /* short pointer for setting */ { short *val= (short *)ptr; ACF_SETTING_SET(*val, flag, mode); } break; case sizeof(char): /* char pointer for setting */ { char *val= (char *)ptr; ACF_SETTING_SET(*val, flag, mode); } break; } } } } /* --------------------------- */ // XXX hardcoded size of icons #define ICON_WIDTH 17 // XXX hardcoded width of sliders #define SLIDER_WIDTH 80 /* Draw the given channel */ // TODO: make this use UI controls for the buttons void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; short selected, offset; float y, ymid, ytext; /* sanity checks - don't draw anything */ if ELEM(NULL, acf, ale) return; /* get initial offset */ if (acf->get_offset) offset= acf->get_offset(ac, ale); else offset= 0; /* calculate appropriate y-coordinates for icon buttons * 7 is hardcoded factor for half-height of icons */ y= (ymaxc - yminc)/2 + yminc; ymid= y - 7; /* y-coordinates for text is only 4 down from middle */ ytext= y - 4; /* check if channel is selected */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) selected= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT); else selected= 0; /* set blending again, as may not be set in previous step */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); /* step 1) draw backdrop ........................................... */ if (acf->draw_backdrop) acf->draw_backdrop(ac, ale, yminc, ymaxc); /* step 2) draw expand widget ....................................... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) { /* just skip - drawn as widget now */ offset += ICON_WIDTH; } /* step 3) draw icon ............................................... */ if (acf->icon) { UI_icon_draw(offset, ymid, acf->icon(ale)); offset += ICON_WIDTH; } /* turn off blending, since not needed anymore... */ glDisable(GL_BLEND); /* step 4) draw special toggles ................................. * - in Graph Editor, checkboxes for visibility in curves area * - in NLA Editor, glowing dots for solo/not solo... */ if (ac->sa) { if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) { /* for F-Curves, draw color-preview of curve behind checkbox */ if (ale->type == ANIMTYPE_FCURVE) { FCurve *fcu= (FCurve *)ale->data; /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever * color the curve has stored */ glColor3fv(fcu->color); /* just a solid color rect * hardcoded 17 pixels width is slightly wider than icon width, so that * there's a slight border around it */ glRectf(offset, yminc, offset+17, ymaxc); } /* icon is drawn as widget now... */ offset += ICON_WIDTH; } else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) { /* just skip - drawn as widget now */ offset += ICON_WIDTH; } } /* step 5) draw name ............................................... */ if (acf->name) { char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */ /* set text color */ if (selected) UI_ThemeColor(TH_TEXT_HI); else UI_ThemeColor(TH_TEXT); /* get name */ acf->name(ale, name); offset += 3; UI_DrawString(offset, ytext, name); /* draw red underline if channel is disabled */ if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_DISABLED)) { // FIXME: replace hardcoded color here, and check on extents! glColor3f(1.0f, 0.0f, 0.0f); glLineWidth(2.0); fdrawline((float)(offset), yminc, (float)(v2d->cur.xmax), yminc); glLineWidth(1.0); } } /* step 6) draw backdrops behidn mute+protection toggles + (sliders) ....................... */ /* reset offset - now goes from RHS of panel */ offset = 0; // TODO: when drawing sliders, make those draw instead of these toggles if not enough space if (v2d) { short draw_sliders = 0; float color[3]; /* get and set backdrop color */ acf->get_backdrop_color(ac, ale, color); glColor3fv(color); /* check if we need to show the sliders */ if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) { switch (ac->spacetype) { case SPACE_ACTION: { SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first; draw_sliders= (saction->flag & SACTION_SLIDERS); } break; case SPACE_IPO: { SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first; draw_sliders= (sipo->flag & SIPO_SLIDERS); } break; } } /* check if there's enough space for the toggles if the sliders are drawn too */ if ( !(draw_sliders) || ((v2d->mask.xmax-v2d->mask.xmin) > ACHANNEL_BUTTON_WIDTH/2) ) { /* protect... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) offset += ICON_WIDTH; /* mute... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) offset += ICON_WIDTH; } /* draw slider * - even if we can draw sliders for this view, we must also check that the channel-type supports them * (only only F-Curves really can support them for now) * - slider should start before the toggles (if they're visible) to keep a clean line down the side */ if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { /* adjust offset */ offset += SLIDER_WIDTH; } /* finally draw a backdrop rect behind these * - starts from the point where the first toggle/slider starts, * - ends past the space that might be reserved for a scroller */ glRectf(v2d->cur.xmax-(float)offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc); } } /* ------------------ */ /* callback for (normal) widget settings - send notifiers */ static void achannel_setting_widget_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) { WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); } /* callback for widget settings that need flushing */ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void *setting_wrap) { bAnimListElem *ale_setting= (bAnimListElem *)ale_npoin; bAnimContext ac; ListBase anim_data = {NULL, NULL}; int filter; int setting = GET_INT_FROM_POINTER(setting_wrap); short on = 0; /* send notifiers before doing anything else... */ WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); /* verify animation context */ if (ANIM_animdata_get_context(C, &ac) == 0) return; /* verify that we have a channel to operate on, and that it has all we need */ if (ale_setting) { /* check if the setting is on... */ on= ANIM_channel_setting_get(&ac, ale_setting, setting); /* on == -1 means setting not found... */ if (on == -1) return; } else return; /* get all channels that can possibly be chosen * - therefore, the filter is simply ANIMFILTER_CHANNELS, since if we took VISIBLE too, * then the channels under closed expanders get ignored... */ filter= ANIMFILTER_CHANNELS; ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* call API method to flush the setting */ ANIM_flush_setting_anim_channels(&ac, &anim_data, ale_setting, setting, on); /* free temp data */ BLI_freelistN(&anim_data); } /* callback for widget sliders - insert keyframes */ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin) { ID *id= (ID *)id_poin; FCurve *fcu= (FCurve *)fcu_poin; ReportList *reports = CTX_wm_reports(C); Scene *scene= CTX_data_scene(C); PointerRNA id_ptr, ptr; PropertyRNA *prop; short flag=0, done=0; float cfra; /* get current frame */ // NOTE: this will do for now... cfra= (float)CFRA; /* get flags for keyframing */ flag = ANIM_get_keyframing_flags(scene, 1); /* get RNA pointer, and resolve the path */ RNA_id_pointer_create(id, &id_ptr); /* try to resolve the path stored in the F-Curve */ if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) { /* set the special 'replace' flag if on a keyframe */ if (fcurve_frame_has_keyframe(fcu, cfra, 0)) flag |= INSERTKEY_REPLACE; /* insert a keyframe for this F-Curve */ done= insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); if (done) WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); } } /* callback for shapekey widget sliders - insert keyframes */ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin) { Key *key= (Key *)key_poin; KeyBlock *kb= (KeyBlock *)kb_poin; char *rna_path= key_get_curValue_rnaPath(key, kb); ReportList *reports = CTX_wm_reports(C); Scene *scene= CTX_data_scene(C); PointerRNA id_ptr, ptr; PropertyRNA *prop; short flag=0, done=0; float cfra; /* get current frame */ // NOTE: this will do for now... cfra= (float)CFRA; /* get flags for keyframing */ flag = ANIM_get_keyframing_flags(scene, 1); /* get RNA pointer, and resolve the path */ RNA_id_pointer_create((ID *)key, &id_ptr); /* try to resolve the path stored in the F-Curve */ if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) { /* find or create new F-Curve */ // XXX is the group name for this ok? bAction *act= verify_adt_action((ID *)key, 1); FCurve *fcu= verify_fcurve(act, NULL, rna_path, 0, 1); /* set the special 'replace' flag if on a keyframe */ if (fcurve_frame_has_keyframe(fcu, cfra, 0)) flag |= INSERTKEY_REPLACE; /* insert a keyframe for this F-Curve */ done= insert_keyframe_direct(reports, ptr, prop, fcu, cfra, flag); if (done) WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL); } /* free the path */ if (rna_path) MEM_freeN(rna_path); } /* Draw a widget for some setting */ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting) { short negflag, ptrsize, enabled, butType; int flag, icon; void *ptr; const char *tooltip; uiBut *but = NULL; /* get the flag and the pointer to that flag */ flag= acf->setting_flag(ac, setting, &negflag); ptr= acf->setting_ptr(ale, setting, &ptrsize); enabled= ANIM_channel_setting_get(ac, ale, setting); /* get the base icon for the setting */ switch (setting) { case ACHANNEL_SETTING_VISIBLE: /* visibility checkboxes */ //icon= ((enabled)? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT); icon= ICON_CHECKBOX_DEHLT; if (ale->type == ANIMTYPE_FCURVE) tooltip= "Channel is visible in Graph Editor for editing."; else tooltip= "Channel(s) are visible in Graph Editor for editing."; break; case ACHANNEL_SETTING_EXPAND: /* expanded triangle */ //icon= ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT); icon= ICON_TRIA_RIGHT; tooltip= "Make channels grouped under this channel visible."; break; case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */ //icon= ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED); icon= ICON_LAYER_USED; tooltip= "NLA Track is the only one evaluated for the AnimData block it belongs to."; break; /* --- */ case ACHANNEL_SETTING_PROTECT: /* protected lock */ // TODO: what about when there's no protect needed? //icon= ((enabled)? ICON_LOCKED : ICON_UNLOCKED); icon= ICON_UNLOCKED; tooltip= "Editability of keyframes for this channel."; break; case ACHANNEL_SETTING_MUTE: /* muted eye */ //icon= ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF); icon= ICON_MUTE_IPO_OFF; if (ale->type == ALE_FCURVE) tooltip= "Does F-Curve contribute to result."; else tooltip= "Do channels contribute to result."; break; default: tooltip= NULL; icon= 0; break; } /* type of button */ if (negflag) butType= ICONTOGN; else butType= ICONTOG; /* draw button for setting */ if (ptr && flag) { switch (ptrsize) { case sizeof(int): /* integer pointer for setting */ but= uiDefIconButBitI(block, butType, flag, 0, icon, xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip); break; case sizeof(short): /* short pointer for setting */ but= uiDefIconButBitS(block, butType, flag, 0, icon, xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip); break; case sizeof(char): /* char pointer for setting */ but= uiDefIconButBitC(block, butType, flag, 0, icon, xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip); break; } /* set call to send relevant notifiers and/or perform type-specific updates */ if (but) { switch (setting) { /* settings needing flushing up/down hierarchy */ case ACHANNEL_SETTING_VISIBLE: /* Graph Editor - 'visibility' toggles */ case ACHANNEL_SETTING_PROTECT: /* General - protection flags */ case ACHANNEL_SETTING_MUTE: /* General - muting flags */ uiButSetNFunc(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting)); break; /* no flushing */ case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush, otherwise all would open/close at once */ default: uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL); } } } } /* 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) { bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale); View2D *v2d= &ac->ar->v2d; float y, ymid, ytext; short offset; /* sanity checks - don't draw anything */ if ELEM3(NULL, acf, ale, block) return; /* get initial offset */ if (acf->get_offset) offset= acf->get_offset(ac, ale); else offset= 0; /* calculate appropriate y-coordinates for icon buttons * 7 is hardcoded factor for half-height of icons */ y= (ymaxc - yminc)/2 + yminc; ymid= y - 7; /* y-coordinates for text is only 4 down from middle */ ytext= y - 4; /* no button backdrop behind icons */ uiBlockSetEmboss(block, UI_EMBOSSN); /* step 1) draw expand widget ....................................... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) { draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_EXPAND); offset += ICON_WIDTH; } /* step 2) draw icon ............................................... */ if (acf->icon) { /* icon is not drawn here (not a widget) */ offset += ICON_WIDTH; } /* step 3) draw special toggles ................................. * - in Graph Editor, checkboxes for visibility in curves area * - in NLA Editor, glowing dots for solo/not solo... */ if (ac->sa) { if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) { /* visibility toggle */ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE); offset += ICON_WIDTH; } else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) { /* 'solo' setting for NLA Tracks */ draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO); offset += ICON_WIDTH; } } /* step 4) draw text... */ /* NOTE: this is not done here, since nothing to be clicked on... */ /* step 5) draw mute+protection toggles + (sliders) ....................... */ /* reset offset - now goes from RHS of panel */ offset = 0; // TODO: when drawing sliders, make those draw instead of these toggles if not enough space if (v2d) { short draw_sliders = 0; /* check if we need to show the sliders */ if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) { switch (ac->spacetype) { case SPACE_ACTION: { SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first; draw_sliders= (saction->flag & SACTION_SLIDERS); } break; case SPACE_IPO: { SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first; draw_sliders= (sipo->flag & SIPO_SLIDERS); } break; } } /* check if there's enough space for the toggles if the sliders are drawn too */ if ( !(draw_sliders) || ((v2d->mask.xmax-v2d->mask.xmin) > ACHANNEL_BUTTON_WIDTH/2) ) { /* protect... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) { offset += ICON_WIDTH; draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_PROTECT); } /* mute... */ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) { offset += ICON_WIDTH; draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_MUTE); } } /* draw slider * - even if we can draw sliders for this view, we must also check that the channel-type supports them * (only only F-Curves really can support them for now) * - to make things easier, we use RNA-autobuts for this so that changes are reflected immediately, * whereever they occurred. BUT, we don't use the layout engine, otherwise we'd get wrong alignment, * and wouldn't be able to auto-keyframe... * - slider should start before the toggles (if they're visible) to keep a clean line down the side */ if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) { /* adjust offset */ // TODO: make slider width dynamic, so that they can be easier to use when the view is wide enough offset += SLIDER_WIDTH; /* need backdrop behind sliders... */ uiBlockSetEmboss(block, UI_EMBOSS); if (ale->id) { /* Slider using RNA Access -------------------- */ PointerRNA id_ptr, ptr; PropertyRNA *prop; char *rna_path = NULL; int array_index = 0; short free_path = 0; /* get destination info */ if (ale->type == ANIMTYPE_FCURVE) { FCurve *fcu= (FCurve *)ale->data; rna_path= fcu->rna_path; array_index= fcu->array_index; } else if (ale->type == ANIMTYPE_SHAPEKEY) { KeyBlock *kb= (KeyBlock *)ale->data; Key *key= (Key *)ale->id; rna_path= key_get_curValue_rnaPath(key, kb); free_path= 1; } /* only if RNA-Path found */ if (rna_path) { /* get RNA pointer, and resolve the path */ RNA_id_pointer_create(ale->id, &id_ptr); /* try to resolve the path */ if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) { uiBut *but; /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */ but= uiDefAutoButR(block, &ptr, prop, array_index, "", ICON_NONE, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc); /* assign keyframing function according to slider type */ if (ale->type == ANIMTYPE_SHAPEKEY) uiButSetFunc(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data); else uiButSetFunc(but, achannel_setting_slider_cb, ale->id, ale->data); } /* free the path if necessary */ if (free_path) MEM_freeN(rna_path); } } else { /* Special Slider for stuff without RNA Access ---------- */ // TODO: only implement this case when we really need it... } } } } /* *********************************************** */