ebd05d8b16b9191559c60d862f12ae7ead8cb3f0
[blender-staging.git] / source / blender / editors / animation / anim_channels_defines.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
19  * All rights reserved.
20  *
21  * Contributor(s): Joshua Leung
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/animation/anim_channels_defines.c
27  *  \ingroup edanimation
28  */
29
30
31 #include <stdio.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38
39 #include "BLF_translation.h"
40
41 #include "DNA_anim_types.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_camera_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_particle_types.h"
46 #include "DNA_screen_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_space_types.h"
49 #include "DNA_key_types.h"
50 #include "DNA_lamp_types.h"
51 #include "DNA_lattice_types.h"
52 #include "DNA_linestyle_types.h"
53 #include "DNA_mesh_types.h"
54 #include "DNA_material_types.h"
55 #include "DNA_meta_types.h"
56 #include "DNA_node_types.h"
57 #include "DNA_world_types.h"
58 #include "DNA_gpencil_types.h"
59 #include "DNA_speaker_types.h"
60 #include "DNA_mask_types.h"
61
62 #include "RNA_access.h"
63
64 #include "BKE_animsys.h"
65 #include "BKE_curve.h"
66 #include "BKE_key.h"
67 #include "BKE_nla.h"
68 #include "BKE_context.h"
69
70 #include "UI_interface.h"
71 #include "UI_interface_icons.h"
72 #include "UI_resources.h"
73
74 #include "ED_anim_api.h"
75 #include "ED_keyframing.h"
76
77 #include "BIF_gl.h"
78 #include "BIF_glutil.h"
79
80 #include "WM_api.h"
81 #include "WM_types.h"
82
83 /* *********************************************** */
84 // XXX constant defines to be moved elsewhere?
85
86 /* extra padding for lengths (to go under scrollers) */
87 #define EXTRA_SCROLL_PAD    100.0f
88
89 /* size of indent steps */
90 #define INDENT_STEP_SIZE    (0.35f * U.widget_unit)
91
92 /* size of string buffers used for animation channel displayed names */
93 #define ANIM_CHAN_NAME_SIZE 256
94
95 /* get the pointer used for some flag */
96 #define GET_ACF_FLAG_PTR(ptr, type) ((*(type) = sizeof((ptr))), &(ptr))
97
98 /* *********************************************** */
99 /* Generic Functions (Type independent) */
100
101 /* Draw Backdrop ---------------------------------- */
102
103 /* get backdrop color for top-level widgets (Scene and Object only) */
104 static void acf_generic_root_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
105 {
106         /* darker blue for top-level widgets */
107         UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, r_color);
108 }
109
110 /* backdrop for top-level widgets (Scene and Object only) */
111 static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
112 {
113         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
114         View2D *v2d = &ac->ar->v2d;
115         short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
116         short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
117         float color[3];
118         
119         /* set backdrop drawing color */
120         acf->get_backdrop_color(ac, ale, color);
121         glColor3fv(color);
122         
123         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
124         UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
125         UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
126 }
127
128
129 /* get backdrop color for data expanders under top-level Scene/Object */
130 static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
131 {
132         /* lighter color than top-level widget */
133         UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, r_color);
134 }
135
136 /* backdrop for data expanders under top-level Scene/Object */
137 static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
138 {
139         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
140         View2D *v2d = &ac->ar->v2d;
141         short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
142         float color[3];
143         
144         /* set backdrop drawing color */
145         acf->get_backdrop_color(ac, ale, color);
146         glColor3fv(color);
147         
148         /* no rounded corner - just rectangular box */
149         glRectf(offset, yminc,  v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
150 }
151
152 /* helper method to test if group colors should be drawn */
153 static bool acf_show_channel_colors(bAnimContext *ac)
154 {
155         bool showGroupColors = false;
156         
157         if (ac->sl) {
158                 switch (ac->spacetype) {
159                         case SPACE_ACTION:
160                         {
161                                 SpaceAction *saction = (SpaceAction *)ac->sl;
162                                 showGroupColors = !(saction->flag & SACTION_NODRAWGCOLORS);
163                         }
164                                 break;
165                         case SPACE_IPO:
166                         {
167                                 SpaceIpo *sipo = (SpaceIpo *)ac->sl;
168                                 showGroupColors = !(sipo->flag & SIPO_NODRAWGCOLORS);
169                         }
170                                 break;
171                 }
172         }
173         
174         return showGroupColors;
175 }
176
177 /* get backdrop color for generic channels */
178 static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
179 {
180         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
181         bActionGroup *grp = NULL;
182         short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
183         bool showGroupColors = acf_show_channel_colors(ac);
184         
185         if (ale->type == ANIMTYPE_FCURVE) {
186                 FCurve *fcu = (FCurve *)ale->data;
187                 grp = fcu->grp;
188         }
189         
190         /* set color for normal channels 
191          *      - use 3 shades of color group/standard color for 3 indention level
192          *      - only use group colors if allowed to, and if actually feasible
193          */
194         if (showGroupColors && (grp) && (grp->customCol)) {
195                 unsigned char cp[3];
196                 
197                 if (indent == 2) {
198                         copy_v3_v3_char((char *)cp, grp->cs.solid);
199                 }
200                 else if (indent == 1) {
201                         copy_v3_v3_char((char *)cp, grp->cs.select);
202                 }
203                 else {
204                         copy_v3_v3_char((char *)cp, grp->cs.active);
205                 }
206                 
207                 /* copy the colors over, transforming from bytes to floats */
208                 rgb_uchar_to_float(r_color, cp);
209         }
210         else {
211                 // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)?
212                 int colOfs = 20 - 20 * indent;
213                 UI_GetThemeColorShade3fv(TH_HEADER, colOfs, r_color);
214         }
215 }
216
217 /* backdrop for generic channels */
218 static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
219 {
220         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
221         View2D *v2d = &ac->ar->v2d;
222         short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
223         float color[3];
224         
225         /* set backdrop drawing color */
226         acf->get_backdrop_color(ac, ale, color);
227         glColor3fv(color);
228         
229         /* no rounded corners - just rectangular box */
230         glRectf(offset, yminc,  v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
231 }
232
233 /* Indention + Offset ------------------------------------------- */
234
235 /* indention level is always the value in the name */
236 static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
237 {
238         return 0;
239 }
240 static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
241 {
242         return 1;
243 }
244 #if 0 // XXX not used
245 static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
246 {
247         return 2;
248 }
249 #endif
250
251 /* indention which varies with the grouping status */
252 static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale)
253 {
254         short indent = 0;
255         
256         /* grouped F-Curves need extra level of indention */
257         if (ale->type == ANIMTYPE_FCURVE) {
258                 FCurve *fcu = (FCurve *)ale->data;
259                 
260                 // TODO: we need some way of specifying that the indention color should be one less...
261                 if (fcu->grp)
262                         indent++;
263         }
264         
265         /* no indention */
266         return indent;
267 }
268
269 /* basic offset for channels derived from indention */
270 static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
271 {
272         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
273         
274         if (acf && acf->get_indent_level)
275                 return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
276         else
277                 return 0;
278 }
279
280 /* offset based on nodetree type */
281 static short acf_nodetree_rootType_offset(bNodeTree *ntree)
282 {
283         if (ntree) {
284                 switch (ntree->type) {
285                         case NTREE_SHADER:
286                                 /* 1 additional level (i.e. is indented one level in from material, 
287                                  * so shift all right by one step) 
288                                  */
289                                 return INDENT_STEP_SIZE; 
290                                 
291                         case NTREE_COMPOSIT:
292                                 /* no additional levels needed */
293                                 return 0; 
294                                 
295                         case NTREE_TEXTURE:
296                                 /* 2 additional levels */
297                                 return INDENT_STEP_SIZE * 2;
298                 }
299         }
300         
301         /* unknown */
302         return 0;
303 }
304
305 /* offset for groups + grouped entities */
306 static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
307 {
308         short offset = acf_generic_basic_offset(ac, ale);
309         
310         if (ale->id) {
311                 /* texture animdata */
312                 if (GS(ale->id->name) == ID_TE) {
313                         offset += U.widget_unit;
314                 }
315                 /* materials and particles animdata */
316                 else if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
317                         offset += (short)(0.7f * U.widget_unit);
318                         
319                 /* if not in Action Editor mode, action-groups (and their children) must carry some offset too... */
320                 else if (ac->datatype != ANIMCONT_ACTION)
321                         offset += (short)(0.7f * U.widget_unit);
322                         
323                 /* nodetree animdata */
324                 if (GS(ale->id->name) == ID_NT) {
325                         offset += acf_nodetree_rootType_offset((bNodeTree *)ale->id);
326                 }
327         }
328         
329         /* offset is just the normal type - i.e. based on indention */
330         return offset;
331 }
332
333 /* Name ------------------------------------------- */
334
335 /* name for ID block entries */
336 static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
337 {
338         ID *id = (ID *)ale->data;    /* data pointed to should be an ID block */
339         
340         /* just copy the name... */
341         if (id && name)
342                 BLI_strncpy(name, id->name + 2, ANIM_CHAN_NAME_SIZE);
343 }
344
345 /* name property for ID block entries */
346 static bool acf_generic_idblock_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
347 {
348         RNA_id_pointer_create(ale->data, ptr);
349         *prop = RNA_struct_name_property(ptr->type);
350         
351         return (*prop != NULL);
352 }
353
354
355 /* name property for ID block entries which are just subheading "fillers" */
356 static bool acf_generic_idfill_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
357 {
358         /* actual ID we're representing is stored in ale->data not ale->id, as id gives the owner */
359         RNA_id_pointer_create(ale->data, ptr);
360         *prop = RNA_struct_name_property(ptr->type);
361         
362         return (*prop != NULL);
363 }
364
365 /* Settings ------------------------------------------- */
366
367 #if 0
368 /* channel type has no settings */
369 static bool acf_generic_none_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
370 {
371         return false;
372 }
373 #endif
374
375 /* check if some setting exists for this object-based data-expander (datablock only) */
376 static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
377 {
378         switch (setting) {
379                 /* expand is always supported */
380                 case ACHANNEL_SETTING_EXPAND:
381                         return true;
382                         
383                 /* mute is only supported for NLA */
384                 case ACHANNEL_SETTING_MUTE:
385                         return ((ac) && (ac->spacetype == SPACE_NLA));
386                         
387                 /* select is ok for most "ds*" channels (e.g. dsmat) */
388                 case ACHANNEL_SETTING_SELECT:
389                         return true;
390                         
391                 /* other flags are never supported */
392                 default:
393                         return false;
394         }
395 }
396
397 /* *********************************************** */
398 /* Type Specific Functions + Defines */
399
400 /* Animation Summary ----------------------------------- */
401
402 /* get backdrop color for summary widget */
403 static void acf_summary_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
404 {
405         /* reddish color - same as the 'action' line in NLA */
406         UI_GetThemeColor3fv(TH_ANIM_ACTIVE, r_color);
407 }
408
409 /* backdrop for summary widget */
410 static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
411 {
412         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
413         View2D *v2d = &ac->ar->v2d;
414         float color[3];
415         
416         /* set backdrop drawing color */
417         acf->get_backdrop_color(ac, ale, color);
418         glColor3fv(color);
419         
420         /* rounded corners on LHS only 
421          *      - top and bottom 
422          *      - special hack: make the top a bit higher, since we are first... 
423          */
424         UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
425         UI_draw_roundbox_gl_mode(GL_POLYGON, 0,  yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
426 }
427
428 /* name for summary entries */
429 static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
430 {
431         if (name)
432                 BLI_strncpy(name, IFACE_("Dope Sheet Summary"), ANIM_CHAN_NAME_SIZE);
433 }
434
435 // FIXME: this is really a temp icon I think
436 static int acf_summary_icon(bAnimListElem *UNUSED(ale))
437 {
438         return ICON_BORDERMOVE;
439 }
440
441 /* check if some setting exists for this channel */
442 static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
443 {
444         /* only expanded is supported, as it is used for hiding all stuff which the summary covers */
445         return (setting == ACHANNEL_SETTING_EXPAND);
446 }
447
448 /* get the appropriate flag(s) for the setting when it is valid  */
449 static int acf_summary_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
450 {
451         if (setting == ACHANNEL_SETTING_EXPAND) {
452                 /* expanded */
453                 *neg = true;
454                 return ADS_FLAG_SUMMARY_COLLAPSED;
455         }
456         else {
457                 /* unsupported */
458                 *neg = false;
459                 return 0;
460         }
461 }
462
463 /* get pointer to the setting */
464 static void *acf_summary_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
465 {
466         bAnimContext *ac = (bAnimContext *)ale->data;
467         
468         /* if data is valid, return pointer to active dopesheet's relevant flag 
469          *      - this is restricted to DopeSheet/Action Editor only
470          */
471         if ((ac->sl) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
472                 SpaceAction *saction = (SpaceAction *)ac->sl;
473                 bDopeSheet *ads = &saction->ads;
474                 
475                 /* return pointer to DopeSheet's flag */
476                 return GET_ACF_FLAG_PTR(ads->flag, type);
477         }
478         else {
479                 /* can't return anything useful - unsupported */
480                 *type = 0;
481                 return NULL;
482         }
483 }
484
485 /* all animation summary (DopeSheet only) type define */
486 static bAnimChannelType ACF_SUMMARY = 
487 {
488         "Summary",                          /* type name */
489         ACHANNEL_ROLE_EXPANDER,             /* role */
490
491         acf_summary_color,                  /* backdrop color */
492         acf_summary_backdrop,               /* backdrop */
493         acf_generic_indention_0,            /* indent level */
494         NULL,                               /* offset */
495
496         acf_summary_name,                   /* name */
497         NULL,                               /* name prop */
498         acf_summary_icon,                   /* icon */
499
500         acf_summary_setting_valid,          /* has setting */
501         acf_summary_setting_flag,           /* flag for setting */
502         acf_summary_setting_ptr             /* pointer for setting */
503 };
504
505 /* Scene ------------------------------------------- */
506
507 // TODO: just get this from RNA?
508 static int acf_scene_icon(bAnimListElem *UNUSED(ale))
509 {
510         return ICON_SCENE_DATA;
511 }
512
513 /* check if some setting exists for this channel */
514 static bool acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
515 {
516         switch (setting) {
517                 /* muted only in NLA */
518                 case ACHANNEL_SETTING_MUTE: 
519                         return ((ac) && (ac->spacetype == SPACE_NLA));
520                         
521                 /* visible only in Graph Editor */
522                 case ACHANNEL_SETTING_VISIBLE: 
523                         return ((ac) && (ac->spacetype == SPACE_IPO));
524                 
525                 /* only select and expand supported otherwise */
526                 case ACHANNEL_SETTING_SELECT:
527                 case ACHANNEL_SETTING_EXPAND:
528                         return true;
529                         
530                 default:
531                         return false;
532         }
533 }
534
535 /* get the appropriate flag(s) for the setting when it is valid  */
536 static int acf_scene_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
537 {
538         /* clear extra return data first */
539         *neg = false;
540         
541         switch (setting) {
542                 case ACHANNEL_SETTING_SELECT: /* selected */
543                         return SCE_DS_SELECTED;
544                         
545                 case ACHANNEL_SETTING_EXPAND: /* expanded */
546                         *neg = true;
547                         return SCE_DS_COLLAPSED;
548                         
549                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
550                         return ADT_NLA_EVAL_OFF;
551                         
552                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
553                         *neg = true;
554                         return ADT_CURVES_NOT_VISIBLE;
555                         
556                 default: /* unsupported */
557                         return 0;
558         }
559 }
560
561 /* get pointer to the setting */
562 static void *acf_scene_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
563 {
564         Scene *scene = (Scene *)ale->data;
565         
566         /* clear extra return data first */
567         *type = 0;
568         
569         switch (setting) {
570                 case ACHANNEL_SETTING_SELECT: /* selected */
571                         return GET_ACF_FLAG_PTR(scene->flag, type);
572                         
573                 case ACHANNEL_SETTING_EXPAND: /* expanded */
574                         return GET_ACF_FLAG_PTR(scene->flag, type);
575                         
576                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
577                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
578                         if (scene->adt)
579                                 return GET_ACF_FLAG_PTR(scene->adt->flag, type);
580                         return NULL;
581                         
582                 default: /* unsupported */
583                         return NULL;
584         }
585 }
586
587 /* scene type define */
588 static bAnimChannelType ACF_SCENE = 
589 {
590         "Scene",                        /* type name */
591         ACHANNEL_ROLE_EXPANDER,         /* role */
592
593         acf_generic_root_color,         /* backdrop color */
594         acf_generic_root_backdrop,      /* backdrop */
595         acf_generic_indention_0,        /* indent level */
596         NULL,                           /* offset */
597
598         acf_generic_idblock_name,       /* name */
599         acf_generic_idblock_name_prop,   /* name prop */
600         acf_scene_icon,                 /* icon */
601
602         acf_scene_setting_valid,        /* has setting */
603         acf_scene_setting_flag,         /* flag for setting */
604         acf_scene_setting_ptr           /* pointer for setting */
605 };
606
607 /* Object ------------------------------------------- */
608
609 static int acf_object_icon(bAnimListElem *ale)
610 {
611         Base *base = (Base *)ale->data;
612         Object *ob = base->object;
613         
614         /* icon depends on object-type */
615         switch (ob->type) {
616                 case OB_LAMP:
617                         return ICON_OUTLINER_OB_LAMP;
618                 case OB_MESH: 
619                         return ICON_OUTLINER_OB_MESH;
620                 case OB_CAMERA: 
621                         return ICON_OUTLINER_OB_CAMERA;
622                 case OB_CURVE: 
623                         return ICON_OUTLINER_OB_CURVE;
624                 case OB_MBALL: 
625                         return ICON_OUTLINER_OB_META;
626                 case OB_LATTICE: 
627                         return ICON_OUTLINER_OB_LATTICE;
628                 case OB_SPEAKER:
629                         return ICON_OUTLINER_OB_SPEAKER;
630                 case OB_ARMATURE:
631                         return ICON_OUTLINER_OB_ARMATURE;
632                 case OB_FONT: 
633                         return ICON_OUTLINER_OB_FONT;
634                 case OB_SURF: 
635                         return ICON_OUTLINER_OB_SURFACE;
636                 case OB_EMPTY: 
637                         return ICON_OUTLINER_OB_EMPTY;
638                 default:
639                         return ICON_OBJECT_DATA;
640         }
641 }
642
643 /* name for object */
644 static void acf_object_name(bAnimListElem *ale, char *name)
645 {
646         Base *base = (Base *)ale->data;
647         Object *ob = base->object;
648         
649         /* just copy the name... */
650         if (ob && name)
651                 BLI_strncpy(name, ob->id.name + 2, ANIM_CHAN_NAME_SIZE);
652 }
653
654 /* name property for object */
655 static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
656 {
657         RNA_id_pointer_create(ale->id, ptr);
658         *prop = RNA_struct_name_property(ptr->type);
659         
660         return (*prop != NULL);
661 }
662
663 /* check if some setting exists for this channel */
664 static bool acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
665 {
666         Base *base = (Base *)ale->data;
667         Object *ob = base->object;
668         
669         switch (setting) {
670                 /* muted only in NLA */
671                 case ACHANNEL_SETTING_MUTE: 
672                         return ((ac) && (ac->spacetype == SPACE_NLA));
673                         
674                 /* visible only in Graph Editor */
675                 case ACHANNEL_SETTING_VISIBLE: 
676                         return ((ac) && (ac->spacetype == SPACE_IPO) && (ob->adt));
677                 
678                 /* only select and expand supported otherwise */
679                 case ACHANNEL_SETTING_SELECT:
680                 case ACHANNEL_SETTING_EXPAND:
681                         return true;
682                         
683                 default:
684                         return false;
685         }
686 }
687
688 /* get the appropriate flag(s) for the setting when it is valid  */
689 static int acf_object_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
690 {
691         /* clear extra return data first */
692         *neg = false;
693         
694         switch (setting) {
695                 case ACHANNEL_SETTING_SELECT: /* selected */
696                         return SELECT;
697                         
698                 case ACHANNEL_SETTING_EXPAND: /* expanded */
699                         *neg = 1;
700                         return OB_ADS_COLLAPSED;
701                         
702                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
703                         return ADT_NLA_EVAL_OFF;
704                         
705                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
706                         *neg = true;
707                         return ADT_CURVES_NOT_VISIBLE;
708                         
709                 default: /* unsupported */
710                         return 0;
711         }
712 }
713
714 /* get pointer to the setting */
715 static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
716 {
717         Base *base = (Base *)ale->data;
718         Object *ob = base->object;
719         
720         /* clear extra return data first */
721         *type = 0;
722         
723         switch (setting) {
724                 case ACHANNEL_SETTING_SELECT: /* selected */
725                         return GET_ACF_FLAG_PTR(ob->flag, type);
726                         
727                 case ACHANNEL_SETTING_EXPAND: /* expanded */
728                         return GET_ACF_FLAG_PTR(ob->nlaflag, type); // xxx
729                         
730                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
731                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
732                         if (ob->adt)
733                                 return GET_ACF_FLAG_PTR(ob->adt->flag, type);
734                         return NULL;
735
736                 default: /* unsupported */
737                         return NULL;
738         }
739 }
740
741 /* object type define */
742 static bAnimChannelType ACF_OBJECT = 
743 {
744         "Object",                       /* type name */
745         ACHANNEL_ROLE_EXPANDER,         /* role */
746         
747         acf_generic_root_color,         /* backdrop color */
748         acf_generic_root_backdrop,      /* backdrop */
749         acf_generic_indention_0,        /* indent level */
750         NULL,                           /* offset */
751
752         acf_object_name,                /* name */
753         acf_object_name_prop,                   /* name prop */
754         acf_object_icon,                /* icon */
755
756         acf_object_setting_valid,       /* has setting */
757         acf_object_setting_flag,        /* flag for setting */
758         acf_object_setting_ptr          /* pointer for setting */
759 };
760
761 /* Group ------------------------------------------- */
762
763 /* get backdrop color for group widget */
764 static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
765 {
766         bActionGroup *agrp = (bActionGroup *)ale->data;
767         bool showGroupColors = acf_show_channel_colors(ac);
768         
769         if (showGroupColors && agrp->customCol) {
770                 unsigned char cp[3];
771                 
772                 /* highlight only for active */
773                 if (ale->flag & AGRP_ACTIVE)
774                         copy_v3_v3_char((char *)cp, agrp->cs.select);
775                 else
776                         copy_v3_v3_char((char *)cp, agrp->cs.solid);
777                 
778                 /* copy the colors over, transforming from bytes to floats */
779                 rgb_uchar_to_float(r_color, cp);
780         }
781         else {
782                 /* highlight only for active */
783                 if (ale->flag & AGRP_ACTIVE)
784                         UI_GetThemeColorShade3fv(TH_GROUP_ACTIVE, 10, r_color);
785                 else
786                         UI_GetThemeColorShade3fv(TH_GROUP, 20, r_color);
787         }
788 }
789
790 /* backdrop for group widget */
791 static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
792 {
793         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
794         View2D *v2d = &ac->ar->v2d;
795         short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
796         short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
797         float color[3];
798         
799         /* set backdrop drawing color */
800         acf->get_backdrop_color(ac, ale, color);
801         glColor3fv(color);
802         
803         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
804         UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
805         UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8);
806 }
807
808 /* name for group entries */
809 static void acf_group_name(bAnimListElem *ale, char *name)
810 {
811         bActionGroup *agrp = (bActionGroup *)ale->data;
812         
813         /* just copy the name... */
814         if (agrp && name)
815                 BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE);
816 }
817
818 /* name property for group entries */
819 static bool acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
820 {
821         RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
822         *prop = RNA_struct_name_property(ptr->type);
823         
824         return (*prop != NULL);
825 }
826
827 /* check if some setting exists for this channel */
828 static bool acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
829 {
830         /* for now, all settings are supported, though some are only conditionally */
831         switch (setting) {
832                 /* unsupported */
833                 case ACHANNEL_SETTING_SOLO:    /* Only available in NLA Editor for tracks */
834                         return false;
835                 
836                 /* conditionally supported */
837                 case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
838                         return (ac->spacetype == SPACE_IPO);
839                         
840                 default: /* always supported */
841                         return true;
842         }
843 }
844
845 /* get the appropriate flag(s) for the setting when it is valid  */
846 static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
847 {
848         /* clear extra return data first */
849         *neg = false;
850         
851         switch (setting) {
852                 case ACHANNEL_SETTING_SELECT: /* selected */
853                         return AGRP_SELECTED;
854                         
855                 case ACHANNEL_SETTING_EXPAND: /* expanded */
856                 {
857                         /* NOTE: Graph Editor uses a different flag to everywhere else for this,
858                          * allowing different collapsing of groups there, since sharing the flag
859                          * proved to be a hazard for workflows...
860                          */
861                         return (ac->spacetype == SPACE_IPO) ? 
862                                AGRP_EXPANDED_G :        /* Graph Editor case */
863                                AGRP_EXPANDED;           /* DopeSheet and elsewhere */
864                 }
865                         
866                 case ACHANNEL_SETTING_MUTE: /* muted */
867                         return AGRP_MUTED;
868                         
869                 case ACHANNEL_SETTING_PROTECT: /* protected */
870                         return AGRP_PROTECTED;
871                         
872                 case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
873                         *neg = 1;
874                         return AGRP_NOTVISIBLE;
875                         
876                 default:
877                         /* this shouldn't happen */
878                         return 0;
879         }
880 }
881
882 /* get pointer to the setting */
883 static void *acf_group_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
884 {
885         bActionGroup *agrp = (bActionGroup *)ale->data;
886         
887         /* all flags are just in agrp->flag for now... */
888         return GET_ACF_FLAG_PTR(agrp->flag, type);
889 }
890
891 /* group type define */
892 static bAnimChannelType ACF_GROUP = 
893 {
894         "Group",                        /* type name */
895         ACHANNEL_ROLE_CHANNEL,          /* role */
896         
897         acf_group_color,                /* backdrop color */
898         acf_group_backdrop,             /* backdrop */
899         acf_generic_indention_0,        /* indent level */
900         acf_generic_group_offset,       /* offset */
901
902         acf_group_name,                 /* name */
903         acf_group_name_prop,            /* name prop */
904         NULL,                           /* icon */
905
906         acf_group_setting_valid,        /* has setting */
907         acf_group_setting_flag,         /* flag for setting */
908         acf_group_setting_ptr           /* pointer for setting */
909 };
910
911 /* F-Curve ------------------------------------------- */
912
913 /* name for fcurve entries */
914 static void acf_fcurve_name(bAnimListElem *ale, char *name)
915 {
916         getname_anim_fcurve(name, ale->id, ale->data);
917 }
918
919 /* "name" property for fcurve entries */
920 static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
921 {
922         FCurve *fcu = (FCurve *)ale->data;
923         
924         /* Ctrl-Click Usability Convenience Hack: 
925          * For disabled F-Curves, allow access to the RNA Path 
926          * as our "name" so that user can perform quick fixes
927          */
928         if (fcu->flag & FCURVE_DISABLED) {
929                 RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
930                 *prop = RNA_struct_find_property(ptr, "data_path");
931         }
932         else {
933                 /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
934                 *prop = NULL;
935         }
936         
937         return (*prop != NULL);
938 }
939
940 /* check if some setting exists for this channel */
941 static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
942 {
943         FCurve *fcu = (FCurve *)ale->data;
944         
945         switch (setting) {
946                 /* unsupported */
947                 case ACHANNEL_SETTING_SOLO:   /* Solo Flag is only for NLA */
948                 case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
949                         return false;
950                 
951                 /* conditionally available */
952                 case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
953                         if (fcu->bezt)
954                                 return true;
955                         else
956                                 return false;  // NOTE: in this special case, we need to draw ICON_ZOOMOUT
957                                 
958                 case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
959                         return (ac->spacetype == SPACE_IPO);
960                         
961                 /* always available */
962                 default:
963                         return true;
964         }
965 }
966
967 /* get the appropriate flag(s) for the setting when it is valid  */
968 static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
969 {
970         /* clear extra return data first */
971         *neg = false;
972         
973         switch (setting) {
974                 case ACHANNEL_SETTING_SELECT: /* selected */
975                         return FCURVE_SELECTED;
976                         
977                 case ACHANNEL_SETTING_MUTE: /* muted */
978                         return FCURVE_MUTED;
979                         
980                 case ACHANNEL_SETTING_PROTECT: /* protected */
981                         return FCURVE_PROTECTED;
982                         
983                 case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
984                         return FCURVE_VISIBLE;
985                         
986                 default: /* unsupported */
987                         return 0;
988         }
989 }
990
991 /* get pointer to the setting */
992 static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
993 {
994         FCurve *fcu = (FCurve *)ale->data;
995         
996         /* all flags are just in agrp->flag for now... */
997         return GET_ACF_FLAG_PTR(fcu->flag, type);
998 }
999
1000 /* fcurve type define */
1001 static bAnimChannelType ACF_FCURVE = 
1002 {
1003         "F-Curve",                      /* type name */
1004         ACHANNEL_ROLE_CHANNEL,          /* role */
1005         
1006         acf_generic_channel_color,      /* backdrop color */
1007         acf_generic_channel_backdrop,   /* backdrop */
1008         acf_generic_indention_flexible, /* indent level */      // xxx rename this to f-curves only?
1009         acf_generic_group_offset,       /* offset */
1010
1011         acf_fcurve_name,                /* name */
1012         acf_fcurve_name_prop,           /* name prop */
1013         NULL,                           /* icon */
1014
1015         acf_fcurve_setting_valid,       /* has setting */
1016         acf_fcurve_setting_flag,        /* flag for setting */
1017         acf_fcurve_setting_ptr          /* pointer for setting */
1018 };
1019
1020 /* NLA Control FCurves Expander ----------------------- */
1021
1022 /* get backdrop color for nla controls widget */
1023 static void acf_nla_controls_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
1024 {
1025         // TODO: give this its own theme setting?
1026         UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color);
1027 }
1028
1029 /* backdrop for nla controls expander widget */
1030 static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
1031 {
1032         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
1033         View2D *v2d = &ac->ar->v2d;
1034         short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
1035         short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
1036         float color[3];
1037         
1038         /* set backdrop drawing color */
1039         acf->get_backdrop_color(ac, ale, color);
1040         glColor3fv(color);
1041         
1042         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
1043         UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
1044         UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5);
1045 }
1046
1047 /* name for nla controls expander entries */
1048 static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name)
1049 {
1050         BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
1051 }
1052
1053 /* check if some setting exists for this channel */
1054 static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
1055 {
1056         /* for now, all settings are supported, though some are only conditionally */
1057         switch (setting) {
1058                 /* supported */
1059                 case ACHANNEL_SETTING_EXPAND:
1060                         return true;
1061                 
1062                 // TOOD: selected?
1063                 
1064                 default: /* unsupported */
1065                         return false;
1066         }
1067 }
1068
1069 /* get the appropriate flag(s) for the setting when it is valid  */
1070 static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1071 {
1072         /* clear extra return data first */
1073         *neg = false;
1074         
1075         switch (setting) {
1076                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1077                         *neg = true;
1078                         return ADT_NLA_SKEYS_COLLAPSED;
1079                 
1080                 default:
1081                         /* this shouldn't happen */
1082                         return 0;
1083         }
1084 }
1085
1086 /* get pointer to the setting */
1087 static void *acf_nla_controls_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
1088 {
1089         AnimData *adt = (AnimData *)ale->data;
1090         
1091         /* all flags are just in adt->flag for now... */
1092         return GET_ACF_FLAG_PTR(adt->flag, type);
1093 }
1094
1095 static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
1096 {
1097         return ICON_NLA;
1098 }
1099
1100 /* NLA Control FCurves Expander type define */
1101 static bAnimChannelType ACF_NLACONTROLS = 
1102 {
1103         "NLA Controls Expander",        /* type name */
1104         ACHANNEL_ROLE_EXPANDER,         /* role */
1105         
1106         acf_nla_controls_color,         /* backdrop color */
1107         acf_nla_controls_backdrop,      /* backdrop */
1108         acf_generic_indention_0,        /* indent level */
1109         acf_generic_group_offset,       /* offset */
1110
1111         acf_nla_controls_name,          /* name */
1112         NULL,                           /* name prop */
1113         acf_nla_controls_icon,          /* icon */
1114
1115         acf_nla_controls_setting_valid, /* has setting */
1116         acf_nla_controls_setting_flag,  /* flag for setting */
1117         acf_nla_controls_setting_ptr    /* pointer for setting */
1118 };
1119
1120
1121 /* NLA Control F-Curve -------------------------------- */
1122
1123 /* name for nla control fcurve entries */
1124 static void acf_nla_curve_name(bAnimListElem *ale, char *name)
1125 {
1126         NlaStrip *strip = ale->owner;
1127         FCurve *fcu = ale->data;
1128         PropertyRNA *prop;
1129         
1130         /* try to get RNA property that this shortened path (relative to the strip) refers to */
1131         prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path);
1132         if (prop) {
1133                 /* "name" of this strip displays the UI identifier + the name of the NlaStrip */
1134                 BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name);
1135         }
1136         else {
1137                 /* unknown property... */
1138                 BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
1139         }
1140 }
1141
1142
1143 /* NLA Control F-Curve type define */
1144 static bAnimChannelType ACF_NLACURVE = 
1145 {
1146         "NLA Control F-Curve",          /* type name */
1147         ACHANNEL_ROLE_CHANNEL,          /* role */
1148         
1149         acf_generic_channel_color,      /* backdrop color */
1150         acf_generic_channel_backdrop,   /* backdrop */
1151         acf_generic_indention_1,        /* indent level */
1152         acf_generic_group_offset,       /* offset */
1153
1154         acf_nla_curve_name,             /* name */
1155         acf_fcurve_name_prop,           /* name prop */
1156         NULL,                           /* icon */
1157
1158         acf_fcurve_setting_valid,       /* has setting */
1159         acf_fcurve_setting_flag,        /* flag for setting */
1160         acf_fcurve_setting_ptr          /* pointer for setting */
1161 };
1162
1163 /* Object Action Expander  ------------------------------------------- */
1164
1165 // TODO: just get this from RNA?
1166 static int acf_fillactd_icon(bAnimListElem *UNUSED(ale))
1167 {
1168         return ICON_ACTION;
1169 }
1170
1171 /* check if some setting exists for this channel */
1172 static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
1173 {
1174         switch (setting) {
1175                 /* only select and expand supported */
1176                 case ACHANNEL_SETTING_SELECT:
1177                 case ACHANNEL_SETTING_EXPAND:
1178                         return true;
1179                         
1180                 default:
1181                         return false;
1182         }
1183 }
1184
1185 /* get the appropriate flag(s) for the setting when it is valid  */
1186 static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1187 {
1188         /* clear extra return data first */
1189         *neg = false;
1190         
1191         switch (setting) {
1192                 case ACHANNEL_SETTING_SELECT: /* selected */
1193                         return ADT_UI_SELECTED;
1194                         
1195                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1196                         *neg = true;
1197                         return ACT_COLLAPSED;
1198                 
1199                 default: /* unsupported */
1200                         return 0;
1201         }
1202 }
1203
1204 /* get pointer to the setting */
1205 static void *acf_fillactd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1206 {
1207         bAction *act = (bAction *)ale->data;
1208         AnimData *adt = ale->adt;
1209         
1210         /* clear extra return data first */
1211         *type = 0;
1212         
1213         switch (setting) {
1214                 case ACHANNEL_SETTING_SELECT: /* selected */
1215                         if (adt) {
1216                                 return GET_ACF_FLAG_PTR(adt->flag, type);
1217                         }
1218                         return NULL;
1219
1220                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1221                         return GET_ACF_FLAG_PTR(act->flag, type);
1222                 
1223                 default: /* unsupported */
1224                         return NULL;
1225         }
1226 }
1227
1228 /* object action expander type define */
1229 static bAnimChannelType ACF_FILLACTD = 
1230 {
1231         "Ob-Action Filler",             /* type name */
1232         ACHANNEL_ROLE_EXPANDER,         /* role */
1233         
1234         acf_generic_dataexpand_color,   /* backdrop color */
1235         acf_generic_dataexpand_backdrop, /* backdrop */
1236         acf_generic_indention_1,        /* indent level */
1237         acf_generic_basic_offset,       /* offset */
1238
1239         acf_generic_idblock_name,       /* name */
1240         acf_generic_idfill_name_prop,    /* name prop */
1241         acf_fillactd_icon,              /* icon */
1242
1243         acf_fillactd_setting_valid,     /* has setting */
1244         acf_fillactd_setting_flag,      /* flag for setting */
1245         acf_fillactd_setting_ptr        /* pointer for setting */
1246 };
1247
1248 /* Drivers Expander  ------------------------------------------- */
1249
1250 // TODO: just get this from RNA?
1251 static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
1252 {
1253         return ICON_DRIVER;
1254 }
1255
1256 static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
1257 {
1258         BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
1259 }
1260
1261 /* check if some setting exists for this channel */
1262 // TODO: this could be made more generic
1263 static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
1264 {
1265         switch (setting) {
1266                 /* only expand supported */
1267                 case ACHANNEL_SETTING_EXPAND:
1268                         return true;
1269                         
1270                 default:
1271                         return false;
1272         }
1273 }
1274
1275 /* get the appropriate flag(s) for the setting when it is valid  */
1276 static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1277 {
1278         /* clear extra return data first */
1279         *neg = false;
1280         
1281         switch (setting) {
1282                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1283                         *neg = true;
1284                         return ADT_DRIVERS_COLLAPSED;
1285                 
1286                 default: /* unsupported */
1287                         return 0;
1288         }
1289 }
1290
1291 /* get pointer to the setting */
1292 static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1293 {
1294         AnimData *adt = (AnimData *)ale->data;
1295         
1296         /* clear extra return data first */
1297         *type = 0;
1298         
1299         switch (setting) {
1300                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1301                         return GET_ACF_FLAG_PTR(adt->flag, type);
1302                 
1303                 default: /* unsupported */
1304                         return NULL;
1305         }
1306 }
1307
1308 /* drivers expander type define */
1309 static bAnimChannelType ACF_FILLDRIVERS = 
1310 {
1311         "Drivers Filler",               /* type name */
1312         ACHANNEL_ROLE_EXPANDER,         /* role */
1313         
1314         acf_generic_dataexpand_color,   /* backdrop color */
1315         acf_generic_dataexpand_backdrop, /* backdrop */
1316         acf_generic_indention_1,        /* indent level */
1317         acf_generic_basic_offset,       /* offset */
1318
1319         acf_filldrivers_name,           /* name */
1320         NULL,                           /* name prop */
1321         acf_filldrivers_icon,           /* icon */
1322
1323         acf_filldrivers_setting_valid,  /* has setting */
1324         acf_filldrivers_setting_flag,   /* flag for setting */
1325         acf_filldrivers_setting_ptr     /* pointer for setting */
1326 };
1327
1328
1329 /* Material Expander  ------------------------------------------- */
1330
1331 // TODO: just get this from RNA?
1332 static int acf_dsmat_icon(bAnimListElem *UNUSED(ale))
1333 {
1334         return ICON_MATERIAL_DATA;
1335 }
1336
1337 /* get the appropriate flag(s) for the setting when it is valid  */
1338 static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1339 {
1340         /* clear extra return data first */
1341         *neg = false;
1342         
1343         switch (setting) {
1344                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1345                         return MA_DS_EXPAND;
1346                         
1347                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1348                         return ADT_NLA_EVAL_OFF;
1349                         
1350                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1351                         *neg = true;
1352                         return ADT_CURVES_NOT_VISIBLE;
1353                         
1354                 case ACHANNEL_SETTING_SELECT: /* selected */
1355                         return ADT_UI_SELECTED;
1356                 
1357                 default: /* unsupported */
1358                         return 0;
1359         }
1360 }
1361
1362 /* get pointer to the setting */
1363 static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1364 {
1365         Material *ma = (Material *)ale->data;
1366         
1367         /* clear extra return data first */
1368         *type = 0;
1369         
1370         switch (setting) {
1371                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1372                         return GET_ACF_FLAG_PTR(ma->flag, type);
1373                         
1374                 case ACHANNEL_SETTING_SELECT: /* selected */
1375                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1376                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1377                         if (ma->adt)
1378                                 return GET_ACF_FLAG_PTR(ma->adt->flag, type);
1379                         return NULL;
1380
1381                 default: /* unsupported */
1382                         return NULL;
1383         }
1384 }
1385
1386 /* material expander type define */
1387 static bAnimChannelType ACF_DSMAT =
1388 {
1389         "Material Data Expander",       /* type name */
1390         ACHANNEL_ROLE_EXPANDER,         /* role */
1391         
1392         acf_generic_dataexpand_color,   /* backdrop color */
1393         acf_generic_dataexpand_backdrop, /* backdrop */
1394         acf_generic_indention_1,        /* indent level */
1395         acf_generic_basic_offset,       /* offset */
1396
1397         acf_generic_idblock_name,       /* name */
1398         acf_generic_idblock_name_prop,   /* name prop */
1399         acf_dsmat_icon,                 /* icon */
1400
1401         acf_generic_dataexpand_setting_valid,   /* has setting */
1402         acf_dsmat_setting_flag,                 /* flag for setting */
1403         acf_dsmat_setting_ptr                   /* pointer for setting */
1404 };
1405
1406 /* Lamp Expander  ------------------------------------------- */
1407
1408 // TODO: just get this from RNA?
1409 static int acf_dslam_icon(bAnimListElem *UNUSED(ale))
1410 {
1411         return ICON_LAMP_DATA;
1412 }
1413
1414 /* get the appropriate flag(s) for the setting when it is valid  */
1415 static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1416 {
1417         /* clear extra return data first */
1418         *neg = false;
1419         
1420         switch (setting) {
1421                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1422                         return LA_DS_EXPAND;
1423                         
1424                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1425                         return ADT_NLA_EVAL_OFF;
1426                         
1427                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1428                         *neg = true;
1429                         return ADT_CURVES_NOT_VISIBLE;
1430                         
1431                 case ACHANNEL_SETTING_SELECT: /* selected */
1432                         return ADT_UI_SELECTED;
1433                 
1434                 default: /* unsupported */
1435                         return 0;
1436         }
1437 }
1438
1439 /* get pointer to the setting */
1440 static void *acf_dslam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1441 {
1442         Lamp *la = (Lamp *)ale->data;
1443         
1444         /* clear extra return data first */
1445         *type = 0;
1446         
1447         switch (setting) {
1448                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1449                         return GET_ACF_FLAG_PTR(la->flag, type);
1450                         
1451                 case ACHANNEL_SETTING_SELECT: /* selected */
1452                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1453                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1454                         if (la->adt)
1455                                 return GET_ACF_FLAG_PTR(la->adt->flag, type);
1456                         return NULL;
1457                 
1458                 default: /* unsupported */
1459                         return NULL;
1460         }
1461 }
1462
1463 /* lamp expander type define */
1464 static bAnimChannelType ACF_DSLAM =
1465 {
1466         "Lamp Expander",                /* type name */
1467         ACHANNEL_ROLE_EXPANDER,         /* role */
1468         
1469         acf_generic_dataexpand_color,   /* backdrop color */
1470         acf_generic_dataexpand_backdrop, /* backdrop */
1471         acf_generic_indention_1,        /* indent level */
1472         acf_generic_basic_offset,       /* offset */
1473
1474         acf_generic_idblock_name,       /* name */
1475         acf_generic_idblock_name_prop,   /* name prop */
1476         acf_dslam_icon,                 /* icon */
1477
1478         acf_generic_dataexpand_setting_valid,   /* has setting */
1479         acf_dslam_setting_flag,                 /* flag for setting */
1480         acf_dslam_setting_ptr                   /* pointer for setting */
1481 };
1482
1483 /* Texture Expander  ------------------------------------------- */
1484
1485 // TODO: just get this from RNA?
1486 static int acf_dstex_icon(bAnimListElem *UNUSED(ale))
1487 {
1488         return ICON_TEXTURE_DATA;
1489 }
1490
1491 /* offset for texture expanders */
1492 // FIXME: soon to be obsolete?
1493 static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
1494 {
1495         return 14; // XXX: simply include this in indention instead?
1496 }
1497
1498 /* get the appropriate flag(s) for the setting when it is valid  */
1499 static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1500 {
1501         /* clear extra return data first */
1502         *neg = false;
1503         
1504         switch (setting) {
1505                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1506                         return TEX_DS_EXPAND;
1507                         
1508                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1509                         return ADT_NLA_EVAL_OFF;
1510                         
1511                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1512                         *neg = true;
1513                         return ADT_CURVES_NOT_VISIBLE;
1514                         
1515                 case ACHANNEL_SETTING_SELECT: /* selected */
1516                         return ADT_UI_SELECTED;
1517                 
1518                 default: /* unsupported */
1519                         return 0;
1520         }
1521 }
1522
1523 /* get pointer to the setting */
1524 static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1525 {
1526         Tex *tex = (Tex *)ale->data;
1527         
1528         /* clear extra return data first */
1529         *type = 0;
1530         
1531         switch (setting) {
1532                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1533                         return GET_ACF_FLAG_PTR(tex->flag, type);
1534                         
1535                 case ACHANNEL_SETTING_SELECT: /* selected */
1536                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1537                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1538                         if (tex->adt)
1539                                 return GET_ACF_FLAG_PTR(tex->adt->flag, type);
1540                         return NULL;
1541                 
1542                 default: /* unsupported */
1543                         return NULL;
1544         }
1545 }
1546
1547 /* texture expander type define */
1548 static bAnimChannelType ACF_DSTEX =
1549 {
1550         "Texture Data Expander",        /* type name */
1551         ACHANNEL_ROLE_EXPANDER,         /* role */
1552         
1553         acf_generic_dataexpand_color,   /* backdrop color */
1554         acf_generic_dataexpand_backdrop, /* backdrop */
1555         acf_generic_indention_1,        /* indent level */
1556         acf_dstex_offset,               /* offset */
1557
1558         acf_generic_idblock_name,       /* name */
1559         acf_generic_idfill_name_prop,    /* name prop */
1560         acf_dstex_icon,                 /* icon */
1561
1562         acf_generic_dataexpand_setting_valid,   /* has setting */
1563         acf_dstex_setting_flag,                 /* flag for setting */
1564         acf_dstex_setting_ptr                   /* pointer for setting */
1565 };
1566
1567 /* Camera Expander  ------------------------------------------- */
1568
1569 // TODO: just get this from RNA?
1570 static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
1571 {
1572         return ICON_CAMERA_DATA;
1573 }
1574
1575 /* get the appropriate flag(s) for the setting when it is valid  */
1576 static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1577 {
1578         /* clear extra return data first */
1579         *neg = false;
1580         
1581         switch (setting) {
1582                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1583                         return CAM_DS_EXPAND;
1584                         
1585                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1586                         return ADT_NLA_EVAL_OFF;
1587                         
1588                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1589                         *neg = true;
1590                         return ADT_CURVES_NOT_VISIBLE;
1591                         
1592                 case ACHANNEL_SETTING_SELECT: /* selected */
1593                         return ADT_UI_SELECTED;
1594                 
1595                 default: /* unsupported */
1596                         return 0;
1597         }
1598 }
1599
1600 /* get pointer to the setting */
1601 static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1602 {
1603         Camera *ca = (Camera *)ale->data;
1604         
1605         /* clear extra return data first */
1606         *type = 0;
1607         
1608         switch (setting) {
1609                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1610                         return GET_ACF_FLAG_PTR(ca->flag, type);
1611                         
1612                 case ACHANNEL_SETTING_SELECT: /* selected */
1613                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1614                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1615                         if (ca->adt)
1616                                 return GET_ACF_FLAG_PTR(ca->adt->flag, type);
1617                         return NULL;
1618                 
1619                 default: /* unsupported */
1620                         return NULL;
1621         }
1622 }
1623
1624 /* camera expander type define */
1625 static bAnimChannelType ACF_DSCAM =
1626 {
1627         "Camera Expander",              /* type name */
1628         ACHANNEL_ROLE_EXPANDER,         /* role */
1629         
1630         acf_generic_dataexpand_color,   /* backdrop color */
1631         acf_generic_dataexpand_backdrop, /* backdrop */
1632         acf_generic_indention_1,        /* indent level */
1633         acf_generic_basic_offset,       /* offset */
1634
1635         acf_generic_idblock_name,       /* name */
1636         acf_generic_idfill_name_prop,    /* name prop */
1637         acf_dscam_icon,                 /* icon */
1638
1639         acf_generic_dataexpand_setting_valid,   /* has setting */
1640         acf_dscam_setting_flag,                 /* flag for setting */
1641         acf_dscam_setting_ptr                   /* pointer for setting */
1642 };
1643
1644 /* Curve Expander  ------------------------------------------- */
1645
1646 // TODO: just get this from RNA?
1647 static int acf_dscur_icon(bAnimListElem *ale)
1648 {
1649         Curve *cu = (Curve *)ale->data;
1650         short obtype = BKE_curve_type_get(cu);
1651         
1652         switch (obtype) {
1653                 case OB_FONT:
1654                         return ICON_FONT_DATA;
1655                 case OB_SURF:
1656                         return ICON_SURFACE_DATA;
1657                 default:
1658                         return ICON_CURVE_DATA;
1659         }
1660 }
1661
1662 /* get the appropriate flag(s) for the setting when it is valid  */
1663 static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1664 {
1665         /* clear extra return data first */
1666         *neg = false;
1667         
1668         switch (setting) {
1669                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1670                         return CU_DS_EXPAND;
1671                         
1672                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1673                         return ADT_NLA_EVAL_OFF;
1674                         
1675                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1676                         *neg = true;
1677                         return ADT_CURVES_NOT_VISIBLE;
1678                         
1679                 case ACHANNEL_SETTING_SELECT: /* selected */
1680                         return ADT_UI_SELECTED;
1681                 
1682                 default: /* unsupported */
1683                         return 0;
1684         }
1685 }
1686
1687 /* get pointer to the setting */
1688 static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1689 {
1690         Curve *cu = (Curve *)ale->data;
1691         
1692         /* clear extra return data first */
1693         *type = 0;
1694         
1695         switch (setting) {
1696                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1697                         return GET_ACF_FLAG_PTR(cu->flag, type);
1698                         
1699                 case ACHANNEL_SETTING_SELECT: /* selected */
1700                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1701                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1702                         if (cu->adt)
1703                                 return GET_ACF_FLAG_PTR(cu->adt->flag, type);
1704                         return NULL;
1705                 
1706                 default: /* unsupported */
1707                         return NULL;
1708         }
1709 }
1710
1711 /* curve expander type define */
1712 static bAnimChannelType ACF_DSCUR =
1713 {
1714         "Curve Expander",               /* type name */
1715         ACHANNEL_ROLE_EXPANDER,         /* role */
1716         
1717         acf_generic_dataexpand_color,   /* backdrop color */
1718         acf_generic_dataexpand_backdrop, /* backdrop */
1719         acf_generic_indention_1,        /* indent level */
1720         acf_generic_basic_offset,       /* offset */
1721
1722         acf_generic_idblock_name,       /* name */
1723         acf_generic_idblock_name_prop,   /* name prop */
1724         acf_dscur_icon,                 /* icon */
1725
1726         acf_generic_dataexpand_setting_valid,   /* has setting */
1727         acf_dscur_setting_flag,                 /* flag for setting */
1728         acf_dscur_setting_ptr                   /* pointer for setting */
1729 };
1730
1731 /* Shape Key Expander  ------------------------------------------- */
1732
1733 // TODO: just get this from RNA?
1734 static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
1735 {
1736         return ICON_SHAPEKEY_DATA;
1737 }
1738
1739 /* get the appropriate flag(s) for the setting when it is valid  */
1740 static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1741 {
1742         /* clear extra return data first */
1743         *neg = false;
1744         
1745         switch (setting) {
1746                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1747                         return KEY_DS_EXPAND;
1748                         
1749                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1750                         return ADT_NLA_EVAL_OFF;
1751                         
1752                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1753                         *neg = true;
1754                         return ADT_CURVES_NOT_VISIBLE;
1755                         
1756                 case ACHANNEL_SETTING_SELECT: /* selected */
1757                         return ADT_UI_SELECTED;
1758                 
1759                 default: /* unsupported */
1760                         return 0;
1761         }
1762 }
1763
1764 /* get pointer to the setting */
1765 static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1766 {
1767         Key *key = (Key *)ale->data;
1768         
1769         /* clear extra return data first */
1770         *type = 0;
1771         
1772         switch (setting) {
1773                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1774                         return GET_ACF_FLAG_PTR(key->flag, type);
1775                         
1776                 case ACHANNEL_SETTING_SELECT: /* selected */
1777                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1778                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1779                         if (key->adt)
1780                                 return GET_ACF_FLAG_PTR(key->adt->flag, type);
1781                         return NULL;
1782                 
1783                 default: /* unsupported */
1784                         return NULL;
1785         }
1786 }
1787
1788 /* shapekey expander type define */
1789 static bAnimChannelType ACF_DSSKEY =
1790 {
1791         "Shape Key Expander",           /* type name */
1792         ACHANNEL_ROLE_EXPANDER,         /* role */
1793         
1794         acf_generic_dataexpand_color,   /* backdrop color */
1795         acf_generic_dataexpand_backdrop, /* backdrop */
1796         acf_generic_indention_1,        /* indent level */
1797         acf_generic_basic_offset,       /* offset */
1798
1799         acf_generic_idblock_name,       /* name */
1800         acf_generic_idblock_name_prop,   /* name prop */
1801         acf_dsskey_icon,                /* icon */
1802
1803         acf_generic_dataexpand_setting_valid,   /* has setting */
1804         acf_dsskey_setting_flag,                /* flag for setting */
1805         acf_dsskey_setting_ptr                  /* pointer for setting */
1806 };
1807
1808 /* World Expander  ------------------------------------------- */
1809
1810 // TODO: just get this from RNA?
1811 static int acf_dswor_icon(bAnimListElem *UNUSED(ale))
1812 {
1813         return ICON_WORLD_DATA;
1814 }
1815
1816 /* get the appropriate flag(s) for the setting when it is valid  */
1817 static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1818 {
1819         /* clear extra return data first */
1820         *neg = false;
1821         
1822         switch (setting) {
1823                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1824                         return WO_DS_EXPAND;
1825                         
1826                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1827                         return ADT_NLA_EVAL_OFF;
1828                         
1829                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1830                         *neg = true;
1831                         return ADT_CURVES_NOT_VISIBLE;
1832                         
1833                 case ACHANNEL_SETTING_SELECT: /* selected */
1834                         return ADT_UI_SELECTED;
1835                 
1836                 default: /* unsupported */
1837                         return 0;
1838         }
1839 }
1840
1841 /* get pointer to the setting */
1842 static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1843 {
1844         World *wo = (World *)ale->data;
1845         
1846         /* clear extra return data first */
1847         *type = 0;
1848         
1849         switch (setting) {
1850                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1851                         return GET_ACF_FLAG_PTR(wo->flag, type);
1852                         
1853                 case ACHANNEL_SETTING_SELECT: /* selected */
1854                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1855                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1856                         if (wo->adt)
1857                                 return GET_ACF_FLAG_PTR(wo->adt->flag, type);
1858                         return NULL;
1859                 
1860                 default: /* unsupported */
1861                         return NULL;
1862         }
1863 }
1864
1865 /* world expander type define */
1866 static bAnimChannelType ACF_DSWOR =
1867 {
1868         "World Expander",               /* type name */
1869         ACHANNEL_ROLE_EXPANDER,         /* role */
1870         
1871         acf_generic_dataexpand_color,   /* backdrop color */
1872         acf_generic_dataexpand_backdrop, /* backdrop */
1873         acf_generic_indention_1,        /* indent level */
1874         acf_generic_basic_offset,       /* offset */
1875
1876         acf_generic_idblock_name,       /* name */
1877         acf_generic_idfill_name_prop,    /* name prop */
1878         acf_dswor_icon,                 /* icon */
1879
1880         acf_generic_dataexpand_setting_valid,   /* has setting */
1881         acf_dswor_setting_flag,                 /* flag for setting */
1882         acf_dswor_setting_ptr                   /* pointer for setting */
1883 };
1884
1885 /* Particle Expander  ------------------------------------------- */
1886
1887 // TODO: just get this from RNA?
1888 static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
1889 {
1890         return ICON_PARTICLE_DATA;
1891 }
1892
1893 /* get the appropriate flag(s) for the setting when it is valid  */
1894 static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1895 {
1896         /* clear extra return data first */
1897         *neg = false;
1898         
1899         switch (setting) {
1900                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1901                         return PART_DS_EXPAND;
1902                         
1903                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1904                         return ADT_NLA_EVAL_OFF;
1905                         
1906                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1907                         *neg = true;
1908                         return ADT_CURVES_NOT_VISIBLE;
1909                         
1910                 case ACHANNEL_SETTING_SELECT: /* selected */
1911                         return ADT_UI_SELECTED;
1912                 
1913                 default: /* unsupported */
1914                         return 0;
1915         }
1916 }
1917
1918 /* get pointer to the setting */
1919 static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1920 {
1921         ParticleSettings *part = (ParticleSettings *)ale->data;
1922         
1923         /* clear extra return data first */
1924         *type = 0;
1925         
1926         switch (setting) {
1927                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1928                         return GET_ACF_FLAG_PTR(part->flag, type);
1929                         
1930                 case ACHANNEL_SETTING_SELECT: /* selected */
1931                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1932                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1933                         if (part->adt)
1934                                 return GET_ACF_FLAG_PTR(part->adt->flag, type);
1935                         return NULL;
1936                 
1937                 default: /* unsupported */
1938                         return NULL;
1939         }
1940 }
1941
1942 /* particle expander type define */
1943 static bAnimChannelType ACF_DSPART =
1944 {
1945         "Particle Data Expander",       /* type name */
1946         ACHANNEL_ROLE_EXPANDER,         /* role */
1947         
1948         acf_generic_dataexpand_color,   /* backdrop color */
1949         acf_generic_dataexpand_backdrop, /* backdrop */
1950         acf_generic_indention_1,        /* indent level */
1951         acf_generic_basic_offset,       /* offset */
1952
1953         acf_generic_idblock_name,       /* name */
1954         acf_generic_idblock_name_prop,   /* name prop */
1955         acf_dspart_icon,                /* icon */
1956
1957         acf_generic_dataexpand_setting_valid,   /* has setting */
1958         acf_dspart_setting_flag,                /* flag for setting */
1959         acf_dspart_setting_ptr                  /* pointer for setting */
1960 };
1961
1962 /* MetaBall Expander  ------------------------------------------- */
1963
1964 // TODO: just get this from RNA?
1965 static int acf_dsmball_icon(bAnimListElem *UNUSED(ale))
1966 {
1967         return ICON_META_DATA;
1968 }
1969
1970 /* get the appropriate flag(s) for the setting when it is valid  */
1971 static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1972 {
1973         /* clear extra return data first */
1974         *neg = false;
1975         
1976         switch (setting) {
1977                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1978                         return MB_DS_EXPAND;
1979                         
1980                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1981                         return ADT_NLA_EVAL_OFF;
1982                         
1983                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1984                         *neg = true;
1985                         return ADT_CURVES_NOT_VISIBLE;
1986                 
1987                 case ACHANNEL_SETTING_SELECT: /* selected */
1988                         return ADT_UI_SELECTED;
1989                 
1990                 default: /* unsupported */
1991                         return 0;
1992         }
1993 }
1994
1995 /* get pointer to the setting */
1996 static void *acf_dsmball_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1997 {
1998         MetaBall *mb = (MetaBall *)ale->data;
1999         
2000         /* clear extra return data first */
2001         *type = 0;
2002         
2003         switch (setting) {
2004                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2005                         return GET_ACF_FLAG_PTR(mb->flag2, type);
2006                         
2007                 case ACHANNEL_SETTING_SELECT: /* selected */
2008                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2009                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2010                         if (mb->adt)
2011                                 return GET_ACF_FLAG_PTR(mb->adt->flag, type);
2012                         return NULL;
2013                 
2014                 default: /* unsupported */
2015                         return NULL;
2016         }
2017 }
2018
2019 /* metaball expander type define */
2020 static bAnimChannelType ACF_DSMBALL =
2021 {
2022         "Metaball Expander",            /* type name */
2023         ACHANNEL_ROLE_EXPANDER,         /* role */
2024         
2025         acf_generic_dataexpand_color,   /* backdrop color */
2026         acf_generic_dataexpand_backdrop, /* backdrop */
2027         acf_generic_indention_1,        /* indent level */
2028         acf_generic_basic_offset,       /* offset */
2029
2030         acf_generic_idblock_name,       /* name */
2031         acf_generic_idblock_name_prop,   /* name prop */
2032         acf_dsmball_icon,               /* icon */
2033
2034         acf_generic_dataexpand_setting_valid,   /* has setting */
2035         acf_dsmball_setting_flag,               /* flag for setting */
2036         acf_dsmball_setting_ptr                 /* pointer for setting */
2037 };
2038
2039 /* Armature Expander  ------------------------------------------- */
2040
2041 // TODO: just get this from RNA?
2042 static int acf_dsarm_icon(bAnimListElem *UNUSED(ale))
2043 {
2044         return ICON_ARMATURE_DATA;
2045 }
2046
2047 /* get the appropriate flag(s) for the setting when it is valid  */
2048 static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2049 {
2050         /* clear extra return data first */
2051         *neg = false;
2052         
2053         switch (setting) {
2054                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2055                         return ARM_DS_EXPAND;
2056                         
2057                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2058                         return ADT_NLA_EVAL_OFF;
2059                         
2060                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2061                         *neg = true;
2062                         return ADT_CURVES_NOT_VISIBLE;
2063                         
2064                 case ACHANNEL_SETTING_SELECT: /* selected */
2065                         return ADT_UI_SELECTED;
2066                 
2067                 default: /* unsupported */
2068                         return 0;
2069         }
2070 }
2071
2072 /* get pointer to the setting */
2073 static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2074 {
2075         bArmature *arm = (bArmature *)ale->data;
2076         
2077         /* clear extra return data first */
2078         *type = 0;
2079         
2080         switch (setting) {
2081                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2082                         return GET_ACF_FLAG_PTR(arm->flag, type);
2083                         
2084                 case ACHANNEL_SETTING_SELECT: /* selected */
2085                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2086                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2087                         if (arm->adt)
2088                                 return GET_ACF_FLAG_PTR(arm->adt->flag, type);
2089                         return NULL;
2090                 
2091                 default: /* unsupported */
2092                         return NULL;
2093         }
2094 }
2095
2096 /* metaball expander type define */
2097 static bAnimChannelType ACF_DSARM =
2098 {
2099         "Armature Expander",            /* type name */
2100         ACHANNEL_ROLE_EXPANDER,         /* role */
2101         
2102         acf_generic_dataexpand_color,   /* backdrop color */
2103         acf_generic_dataexpand_backdrop, /* backdrop */
2104         acf_generic_indention_1,        /* indent level */
2105         acf_generic_basic_offset,       /* offset */
2106
2107         acf_generic_idblock_name,       /* name */
2108         acf_generic_idblock_name_prop,   /* name prop */
2109         acf_dsarm_icon,             /* icon */
2110
2111         acf_generic_dataexpand_setting_valid,   /* has setting */
2112         acf_dsarm_setting_flag,                 /* flag for setting */
2113         acf_dsarm_setting_ptr                   /* pointer for setting */
2114 };
2115
2116 /* NodeTree Expander  ------------------------------------------- */
2117
2118 // TODO: just get this from RNA?
2119 static int acf_dsntree_icon(bAnimListElem *UNUSED(ale))
2120 {
2121         return ICON_NODETREE;
2122 }
2123
2124 /* offset for nodetree expanders */
2125 static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale)
2126 {
2127         bNodeTree *ntree = (bNodeTree *)ale->data;
2128         short offset = acf_generic_basic_offset(ac, ale);
2129         
2130         offset += acf_nodetree_rootType_offset(ntree); 
2131         
2132         return offset;
2133 }
2134
2135 /* get the appropriate flag(s) for the setting when it is valid  */
2136 static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2137 {
2138         /* clear extra return data first */
2139         *neg = false;
2140         
2141         switch (setting) {
2142                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2143                         return NTREE_DS_EXPAND;
2144                         
2145                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2146                         return ADT_NLA_EVAL_OFF;
2147                         
2148                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2149                         *neg = true;
2150                         return ADT_CURVES_NOT_VISIBLE;
2151                         
2152                 case ACHANNEL_SETTING_SELECT: /* selected */
2153                         return ADT_UI_SELECTED;
2154                         
2155                 default: /* unsupported */
2156                         return 0;
2157         }
2158 }
2159
2160 /* get pointer to the setting */
2161 static void *acf_dsntree_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2162 {
2163         bNodeTree *ntree = (bNodeTree *)ale->data;
2164         
2165         /* clear extra return data first */
2166         *type = 0;
2167         
2168         switch (setting) {
2169                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2170                         return GET_ACF_FLAG_PTR(ntree->flag, type);
2171                         
2172                 case ACHANNEL_SETTING_SELECT: /* selected */
2173                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2174                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2175                         if (ntree->adt)
2176                                 return GET_ACF_FLAG_PTR(ntree->adt->flag, type);
2177                         return NULL;
2178                         
2179                 default: /* unsupported */
2180                         return NULL;
2181         }
2182 }
2183
2184 /* node tree expander type define */
2185 static bAnimChannelType ACF_DSNTREE =
2186 {
2187         "Node Tree Expander",           /* type name */
2188         ACHANNEL_ROLE_EXPANDER,         /* role */
2189         
2190         acf_generic_dataexpand_color,   /* backdrop color */
2191         acf_generic_dataexpand_backdrop, /* backdrop */
2192         acf_generic_indention_1,        /* indent level */
2193         acf_dsntree_offset,             /* offset */
2194
2195         acf_generic_idblock_name,       /* name */
2196         acf_generic_idblock_name_prop,   /* name prop */
2197         acf_dsntree_icon,               /* icon */
2198
2199         acf_generic_dataexpand_setting_valid,   /* has setting */
2200         acf_dsntree_setting_flag,               /* flag for setting */
2201         acf_dsntree_setting_ptr                 /* pointer for setting */
2202 };
2203
2204 /* LineStyle Expander  ------------------------------------------- */
2205
2206 /* TODO: just get this from RNA? */
2207 static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale))
2208 {
2209         return ICON_LINE_DATA;
2210 }
2211
2212 /* get the appropriate flag(s) for the setting when it is valid  */
2213 static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2214 {
2215         /* clear extra return data first */
2216         *neg = false;
2217         
2218         switch (setting) {
2219                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2220                         return LS_DS_EXPAND;
2221                         
2222                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2223                         return ADT_NLA_EVAL_OFF;
2224                         
2225                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2226                         *neg = true;
2227                         return ADT_CURVES_NOT_VISIBLE;
2228                         
2229                 case ACHANNEL_SETTING_SELECT: /* selected */
2230                         return ADT_UI_SELECTED;
2231                         
2232                 default: /* unsupported */
2233                         return 0;
2234         }
2235 }
2236
2237 /* get pointer to the setting */
2238 static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2239 {
2240         FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
2241         
2242         /* clear extra return data first */
2243         *type = 0;
2244         
2245         switch (setting) {
2246                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2247                         return GET_ACF_FLAG_PTR(linestyle->flag, type);
2248                         
2249                 case ACHANNEL_SETTING_SELECT: /* selected */
2250                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2251                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2252                         if (linestyle->adt)
2253                                 return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
2254                         return NULL;
2255                         
2256                 default: /* unsupported */
2257                         return NULL;
2258         }
2259 }
2260
2261 /* node tree expander type define */
2262 static bAnimChannelType ACF_DSLINESTYLE =
2263 {
2264         "Line Style Expander",                  /* type name */
2265         ACHANNEL_ROLE_EXPANDER,         /* role */
2266         
2267         acf_generic_dataexpand_color,   /* backdrop color */
2268         acf_generic_dataexpand_backdrop,/* backdrop */
2269         acf_generic_indention_1,                /* indent level */
2270         acf_generic_basic_offset,               /* offset */
2271         
2272         acf_generic_idblock_name,               /* name */
2273         acf_generic_idblock_name_prop,  /* name prop */
2274         acf_dslinestyle_icon,                   /* icon */
2275         
2276         acf_generic_dataexpand_setting_valid,   /* has setting */
2277         acf_dslinestyle_setting_flag,                   /* flag for setting */
2278         acf_dslinestyle_setting_ptr                             /* pointer for setting */
2279 };
2280
2281 /* Mesh Expander  ------------------------------------------- */
2282
2283 // TODO: just get this from RNA?
2284 static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale))
2285 {
2286         return ICON_MESH_DATA;
2287 }
2288
2289 /* get the appropriate flag(s) for the setting when it is valid  */
2290 static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2291 {
2292         /* clear extra return data first */
2293         *neg = false;
2294         
2295         switch (setting) {
2296                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2297                         return ME_DS_EXPAND;
2298                         
2299                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2300                         return ADT_NLA_EVAL_OFF;
2301                         
2302                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2303                         *neg = true;
2304                         return ADT_CURVES_NOT_VISIBLE;
2305                         
2306                 case ACHANNEL_SETTING_SELECT: /* selected */
2307                         return ADT_UI_SELECTED;
2308                         
2309                 default: /* unsupported */
2310                         return 0;
2311         }
2312 }
2313
2314 /* get pointer to the setting */
2315 static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2316 {
2317         Mesh *me = (Mesh *)ale->data;
2318         
2319         /* clear extra return data first */
2320         *type = 0;
2321         
2322         switch (setting) {
2323                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2324                         return GET_ACF_FLAG_PTR(me->flag, type);
2325                         
2326                 case ACHANNEL_SETTING_SELECT: /* selected */
2327                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2328                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2329                         if (me->adt)
2330                                 return GET_ACF_FLAG_PTR(me->adt->flag, type);
2331                         return NULL;
2332                         
2333                 default: /* unsupported */
2334                         return NULL;
2335         }
2336 }
2337
2338 /* node tree expander type define */
2339 static bAnimChannelType ACF_DSMESH =
2340 {
2341         "Mesh Expander",                /* type name */
2342         ACHANNEL_ROLE_EXPANDER,         /* role */
2343         
2344         acf_generic_dataexpand_color,   /* backdrop color */
2345         acf_generic_dataexpand_backdrop, /* backdrop */
2346         acf_generic_indention_1,        /* indent level */      // XXX this only works for compositing
2347         acf_generic_basic_offset,       /* offset */
2348
2349         acf_generic_idblock_name,       /* name */
2350         acf_generic_idblock_name_prop,   /* name prop */
2351         acf_dsmesh_icon,                /* icon */
2352
2353         acf_generic_dataexpand_setting_valid,   /* has setting */
2354         acf_dsmesh_setting_flag,                /* flag for setting */
2355         acf_dsmesh_setting_ptr                  /* pointer for setting */
2356 };
2357
2358 /* Lattice Expander  ------------------------------------------- */
2359
2360 // TODO: just get this from RNA?
2361 static int acf_dslat_icon(bAnimListElem *UNUSED(ale))
2362 {
2363         return ICON_LATTICE_DATA;
2364 }
2365
2366 /* get the appropriate flag(s) for the setting when it is valid  */
2367 static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2368 {
2369         /* clear extra return data first */
2370         *neg = false;
2371         
2372         switch (setting) {
2373                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2374                         return LT_DS_EXPAND;
2375                         
2376                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2377                         return ADT_NLA_EVAL_OFF;
2378                         
2379                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2380                         *neg = true;
2381                         return ADT_CURVES_NOT_VISIBLE;
2382                         
2383                 case ACHANNEL_SETTING_SELECT: /* selected */
2384                         return ADT_UI_SELECTED;
2385                         
2386                 default: /* unsupported */
2387                         return 0;
2388         }
2389 }
2390
2391 /* get pointer to the setting */
2392 static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2393 {
2394         Lattice *lt = (Lattice *)ale->data;
2395         
2396         /* clear extra return data first */
2397         *type = 0;
2398         
2399         switch (setting) {
2400                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2401                         return GET_ACF_FLAG_PTR(lt->flag, type);
2402                         
2403                 case ACHANNEL_SETTING_SELECT: /* selected */
2404                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2405                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2406                         if (lt->adt)
2407                                 return GET_ACF_FLAG_PTR(lt->adt->flag, type);
2408                         return NULL;
2409                         
2410                 default: /* unsupported */
2411                         return NULL;
2412         }
2413 }
2414
2415 /* node tree expander type define */
2416 static bAnimChannelType ACF_DSLAT =
2417 {
2418         "Lattice Expander",             /* type name */
2419         ACHANNEL_ROLE_EXPANDER,         /* role */
2420         
2421         acf_generic_dataexpand_color,   /* backdrop color */
2422         acf_generic_dataexpand_backdrop, /* backdrop */
2423         acf_generic_indention_1,        /* indent level */      // XXX this only works for compositing
2424         acf_generic_basic_offset,       /* offset */
2425
2426         acf_generic_idblock_name,       /* name */
2427         acf_generic_idblock_name_prop,   /* name prop */
2428         acf_dslat_icon,                 /* icon */
2429
2430         acf_generic_dataexpand_setting_valid,   /* has setting */
2431         acf_dslat_setting_flag,                 /* flag for setting */
2432         acf_dslat_setting_ptr                   /* pointer for setting */
2433 };
2434
2435 /* Speaker Expander  ------------------------------------------- */
2436
2437 // TODO: just get this from RNA?
2438 static int acf_dsspk_icon(bAnimListElem *UNUSED(ale))
2439 {
2440         return ICON_SPEAKER;
2441 }
2442
2443 /* get the appropriate flag(s) for the setting when it is valid  */
2444 static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2445 {
2446         /* clear extra return data first */
2447         *neg = false;
2448         
2449         switch (setting) {
2450                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2451                         return SPK_DS_EXPAND;
2452                 
2453                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2454                         return ADT_NLA_EVAL_OFF;
2455                 
2456                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2457                         *neg = true;
2458                         return ADT_CURVES_NOT_VISIBLE;
2459                 
2460                 case ACHANNEL_SETTING_SELECT: /* selected */
2461                         return ADT_UI_SELECTED;
2462                 
2463                 default: /* unsupported */
2464                         return 0;
2465         }
2466 }
2467
2468 /* get pointer to the setting */
2469 static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2470 {
2471         Speaker *spk = (Speaker *)ale->data;
2472         
2473         /* clear extra return data first */
2474         *type = 0;
2475         
2476         switch (setting) {
2477                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2478                         return GET_ACF_FLAG_PTR(spk->flag, type);
2479                 
2480                 case ACHANNEL_SETTING_SELECT: /* selected */
2481                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2482                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2483                         if (spk->adt)
2484                                 return GET_ACF_FLAG_PTR(spk->adt->flag, type);
2485                         return NULL;
2486                 
2487                 default: /* unsupported */
2488                         return NULL;
2489         }
2490 }
2491
2492 /* speaker expander type define */
2493 static bAnimChannelType ACF_DSSPK =
2494 {
2495         "Speaker Expander",             /* type name */
2496         ACHANNEL_ROLE_EXPANDER,         /* role */
2497         
2498         acf_generic_dataexpand_color,   /* backdrop color */
2499         acf_generic_dataexpand_backdrop, /* backdrop */
2500         acf_generic_indention_1,        /* indent level */
2501         acf_generic_basic_offset,       /* offset */
2502
2503         acf_generic_idblock_name,       /* name */
2504         acf_generic_idblock_name_prop,   /* name prop */
2505         acf_dsspk_icon,                 /* icon */
2506
2507         acf_generic_dataexpand_setting_valid,   /* has setting */
2508         acf_dsspk_setting_flag,                 /* flag for setting */
2509         acf_dsspk_setting_ptr                   /* pointer for setting */
2510 };
2511
2512 /* GPencil Expander  ------------------------------------------- */
2513
2514 // TODO: just get this from RNA?
2515 static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
2516 {
2517         return ICON_GREASEPENCIL;
2518 }
2519
2520 /* get the appropriate flag(s) for the setting when it is valid  */
2521 static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2522 {
2523         /* clear extra return data first */
2524         *neg = false;
2525         
2526         switch (setting) {
2527                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2528                         return GP_DATA_EXPAND;
2529                 
2530                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2531                         return ADT_NLA_EVAL_OFF;
2532                 
2533                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2534                         *neg = true;
2535                         return ADT_CURVES_NOT_VISIBLE;
2536                 
2537                 case ACHANNEL_SETTING_SELECT: /* selected */
2538                         return ADT_UI_SELECTED;
2539                 
2540                 default: /* unsupported */
2541                         return 0;
2542         }
2543 }
2544
2545 /* get pointer to the setting */
2546 static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2547 {
2548         bGPdata *gpd = (bGPdata *)ale->data;
2549         
2550         /* clear extra return data first */
2551         *type = 0;
2552         
2553         switch (setting) {
2554                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2555                         return GET_ACF_FLAG_PTR(gpd->flag, type);
2556                 
2557                 case ACHANNEL_SETTING_SELECT: /* selected */
2558                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2559                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2560                         if (gpd->adt)
2561                                 return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
2562                         return NULL;
2563                 
2564                 default: /* unsupported */
2565                         return NULL;
2566         }
2567 }
2568
2569 /* grease pencil expander type define */
2570 static bAnimChannelType ACF_DSGPENCIL =
2571 {
2572         "GPencil DS Expander",          /* type name */
2573         ACHANNEL_ROLE_EXPANDER,         /* role */
2574         
2575         acf_generic_dataexpand_color,   /* backdrop color */
2576         acf_generic_dataexpand_backdrop, /* backdrop */
2577         acf_generic_indention_1,        /* indent level */
2578         acf_generic_basic_offset,       /* offset */
2579
2580         acf_generic_idblock_name,       /* name */
2581         acf_generic_idblock_name_prop,  /* name prop */
2582         acf_dsgpencil_icon,             /* icon */
2583
2584         acf_generic_dataexpand_setting_valid,   /* has setting */
2585         acf_dsgpencil_setting_flag,             /* flag for setting */
2586         acf_dsgpencil_setting_ptr               /* pointer for setting */
2587 };
2588
2589 /* ShapeKey Entry  ------------------------------------------- */
2590
2591 /* name for ShapeKey */
2592 static void acf_shapekey_name(bAnimListElem *ale, char *name)
2593 {
2594         KeyBlock *kb = (KeyBlock *)ale->data;
2595         
2596         /* just copy the name... */
2597         if (kb && name) {
2598                 /* if the KeyBlock had a name, use it, otherwise use the index */
2599                 if (kb->name[0])
2600                         BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE);
2601                 else
2602                         BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index);
2603         }
2604 }
2605
2606 /* name property for ShapeKey entries */
2607 static bool acf_shapekey_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
2608 {
2609         KeyBlock *kb = (KeyBlock *)ale->data;
2610         
2611         /* if the KeyBlock had a name, use it, otherwise use the index */
2612         if (kb && kb->name[0]) {
2613                 RNA_pointer_create(ale->id, &RNA_ShapeKey, kb, ptr);
2614                 *prop = RNA_struct_name_property(ptr->type);
2615                 
2616                 return (*prop != NULL);
2617         }
2618         
2619         return false;
2620 }
2621
2622 /* check if some setting exists for this channel */
2623 static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2624 {
2625         switch (setting) {
2626                 case ACHANNEL_SETTING_SELECT: /* selected */
2627                 case ACHANNEL_SETTING_MUTE: /* muted */
2628                 case ACHANNEL_SETTING_PROTECT: /* protected */
2629                         return true;
2630                         
2631                 /* nothing else is supported */
2632                 default:
2633                         return false;
2634         }
2635 }
2636
2637 /* get the appropriate flag(s) for the setting when it is valid  */
2638 static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2639 {
2640         /* clear extra return data first */
2641         *neg = false;
2642         
2643         switch (setting) {
2644                 case ACHANNEL_SETTING_MUTE: /* mute */
2645                         return KEYBLOCK_MUTE;
2646                 
2647                 case ACHANNEL_SETTING_SELECT: /* selected */
2648                         return KEYBLOCK_SEL;
2649                 
2650                 case ACHANNEL_SETTING_PROTECT: /* locked */
2651                         return KEYBLOCK_LOCKED;
2652                 
2653                 default: /* unsupported */
2654                         return 0;
2655         }
2656 }
2657
2658 /* get pointer to the setting */
2659 static void *acf_shapekey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2660 {
2661         KeyBlock *kb = (KeyBlock *)ale->data;
2662         
2663         /* clear extra return data first */
2664         *type = 0;
2665         
2666         switch (setting) {
2667                 case ACHANNEL_SETTING_SELECT: /* selected */
2668                 case ACHANNEL_SETTING_MUTE: /* muted */
2669                 case ACHANNEL_SETTING_PROTECT: /* protected */
2670                         return GET_ACF_FLAG_PTR(kb->flag, type);
2671                 
2672                 default: /* unsupported */
2673                         return NULL;
2674         }
2675 }
2676
2677 /* shapekey expander type define */
2678 static bAnimChannelType ACF_SHAPEKEY =
2679 {
2680         "Shape Key",                    /* type name */
2681         ACHANNEL_ROLE_CHANNEL,          /* role */
2682         
2683         acf_generic_channel_color,      /* backdrop color */
2684         acf_generic_channel_backdrop,   /* backdrop */
2685         acf_generic_indention_0,        /* indent level */
2686         acf_generic_basic_offset,       /* offset */
2687
2688         acf_shapekey_name,              /* name */
2689         acf_shapekey_name_prop,          /* name prop */
2690         NULL,                           /* icon */
2691
2692         acf_shapekey_setting_valid,     /* has setting */
2693         acf_shapekey_setting_flag,      /* flag for setting */
2694         acf_shapekey_setting_ptr        /* pointer for setting */
2695 };
2696
2697 /* GPencil Datablock ------------------------------------------- */
2698
2699 /* get backdrop color for gpencil datablock widget */
2700 static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
2701 {
2702         /* these are ID-blocks, but not exactly standalone... */
2703         UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
2704 }
2705
2706 // TODO: just get this from RNA?
2707 static int acf_gpd_icon(bAnimListElem *UNUSED(ale))
2708 {
2709         return ICON_GREASEPENCIL;
2710 }
2711
2712 /* check if some setting exists for this channel */
2713 static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2714 {
2715         switch (setting) {
2716                 /* only select and expand supported */
2717                 case ACHANNEL_SETTING_SELECT:
2718                 case ACHANNEL_SETTING_EXPAND:
2719                         return true;
2720                         
2721                 default:
2722                         return false;
2723         }
2724 }
2725
2726 /* get the appropriate flag(s) for the setting when it is valid  */
2727 static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2728 {
2729         /* clear extra return data first */
2730         *neg = false;
2731         
2732         switch (setting) {
2733                 case ACHANNEL_SETTING_SELECT: /* selected */
2734                         return AGRP_SELECTED;
2735                         
2736                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2737                         return GP_DATA_EXPAND;
2738                 
2739                 default:
2740                         /* these shouldn't happen */
2741                         return 0;
2742         }
2743 }
2744
2745 /* get pointer to the setting */
2746 static void *acf_gpd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
2747 {
2748         bGPdata *gpd = (bGPdata *)ale->data;
2749         
2750         /* all flags are just in gpd->flag for now... */
2751         return GET_ACF_FLAG_PTR(gpd->flag, type);
2752 }
2753
2754 /* gpencil datablock type define */
2755 static bAnimChannelType ACF_GPD = 
2756 {
2757         "GPencil Datablock",            /* type name */
2758         ACHANNEL_ROLE_EXPANDER,         /* role */
2759         
2760         acf_gpd_color,                  /* backdrop color */
2761         acf_group_backdrop,             /* backdrop */
2762         acf_generic_indention_0,        /* indent level */
2763         acf_generic_group_offset,       /* offset */
2764
2765         acf_generic_idblock_name,       /* name */
2766         acf_generic_idfill_name_prop,    /* name prop */
2767         acf_gpd_icon,                   /* icon */
2768
2769         acf_gpd_setting_valid,          /* has setting */
2770         acf_gpd_setting_flag,           /* flag for setting */
2771         acf_gpd_setting_ptr             /* pointer for setting */
2772 };
2773
2774 /* GPencil Layer ------------------------------------------- */
2775
2776 /* name for grease pencil layer entries */
2777 static void acf_gpl_name(bAnimListElem *ale, char *name)
2778 {
2779         bGPDlayer *gpl = (bGPDlayer *)ale->data;
2780         
2781         if (gpl && name)
2782                 BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
2783 }
2784
2785 /* name property for grease pencil layer entries */
2786 static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
2787 {
2788         if (ale->data) {
2789                 RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
2790                 *prop = RNA_struct_name_property(ptr->type);
2791                 
2792                 return (*prop != NULL);
2793         }
2794         
2795         return false;
2796 }
2797
2798 /* check if some setting exists for this channel */
2799 static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2800 {
2801         switch (setting) {
2802                 /* unsupported */
2803                 case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
2804                 case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
2805                 case ACHANNEL_SETTING_SOLO: /* nla editor only */
2806                         return false;
2807                 
2808                 /* always available */
2809                 default:
2810                         return true;
2811         }
2812 }
2813
2814 /* get the appropriate flag(s) for the setting when it is valid  */
2815 static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2816 {
2817         /* clear extra return data first */
2818         *neg = false;
2819         
2820         switch (setting) {
2821                 case ACHANNEL_SETTING_SELECT: /* selected */
2822                         return GP_LAYER_SELECT;
2823                         
2824                 case ACHANNEL_SETTING_MUTE: /* muted */
2825                         return GP_LAYER_HIDE;
2826                         
2827                 case ACHANNEL_SETTING_PROTECT: /* protected */
2828                         return GP_LAYER_LOCKED;
2829                         
2830                 default: /* unsupported */
2831                         return 0;
2832         }
2833 }
2834
2835 /* get pointer to the setting */
2836 static void *acf_gpl_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
2837 {
2838         bGPDlayer *gpl = (bGPDlayer *)ale->data;
2839         
2840         /* all flags are just in gpl->flag for now... */
2841         return GET_ACF_FLAG_PTR(gpl->flag, type);
2842 }
2843
2844 /* grease pencil layer type define */
2845 static bAnimChannelType ACF_GPL = 
2846 {
2847         "GPencil Layer",                /* type name */
2848         ACHANNEL_ROLE_CHANNEL,          /* role */
2849         
2850         acf_generic_channel_color,      /* backdrop color */
2851         acf_generic_channel_backdrop,   /* backdrop */
2852         acf_generic_indention_flexible, /* indent level */
2853         acf_generic_group_offset,       /* offset */
2854         
2855         acf_gpl_name,                   /* name */
2856         acf_gpl_name_prop,              /* name prop */
2857         NULL,                           /* icon */
2858         
2859         acf_gpl_setting_valid,          /* has setting */
2860         acf_gpl_setting_flag,           /* flag for setting */
2861         acf_gpl_setting_ptr             /* pointer for setting */
2862 };
2863
2864
2865 /* Mask Datablock ------------------------------------------- */
2866
2867 /* get backdrop color for mask datablock widget */
2868 static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
2869 {
2870         /* these are ID-blocks, but not exactly standalone... */
2871         UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
2872 }
2873
2874 // TODO: just get this from RNA?
2875 static int acf_mask_icon(bAnimListElem *UNUSED(ale))
2876 {
2877         return ICON_MOD_MASK;
2878 }
2879
2880 /* check if some setting exists for this channel */
2881 static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2882 {
2883         switch (setting) {
2884                 /* only select and expand supported */
2885                 case ACHANNEL_SETTING_SELECT:
2886                 case ACHANNEL_SETTING_EXPAND:
2887                         return true;
2888                 
2889                 default:
2890                         return false;
2891         }
2892 }
2893
2894 /* get the appropriate flag(s) for the setting when it is valid  */
2895 static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2896 {
2897         /* clear extra return data first */
2898         *neg = false;
2899         
2900         switch (setting) {
2901                 case ACHANNEL_SETTING_SELECT: /* selected */
2902                         return AGRP_SELECTED;
2903                 
2904                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2905                         return MASK_ANIMF_EXPAND;
2906                         
2907                 default:        
2908                         /* this shouldn't happen */
2909                         return 0;
2910         }
2911 }
2912
2913 /* get pointer to the setting */
2914 static void *acf_mask_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
2915 {
2916         Mask *mask = (Mask *)ale->data;
2917         
2918         /* all flags are just in mask->flag for now... */
2919         return GET_ACF_FLAG_PTR(mask->flag, type);
2920 }
2921
2922 /* mask datablock type define */
2923 static bAnimChannelType ACF_MASKDATA =
2924 {
2925         "Mask Datablock",                /* type name */
2926         ACHANNEL_ROLE_EXPANDER,          /* role */
2927         
2928         acf_mask_color,                  /* backdrop color */
2929         acf_group_backdrop,              /* backdrop */
2930         acf_generic_indention_0,         /* indent level */
2931         acf_generic_group_offset,        /* offset */
2932         
2933         acf_generic_idblock_name,        /* name */
2934         acf_generic_idfill_name_prop,     /* name prop */
2935         acf_mask_icon,                   /* icon */
2936         
2937         acf_mask_setting_valid,          /* has setting */
2938         acf_mask_setting_flag,           /* flag for setting */
2939         acf_mask_setting_ptr             /* pointer for setting */
2940 };
2941
2942 /* Mask Layer ------------------------------------------- */
2943
2944 /* name for grease pencil layer entries */
2945 static void acf_masklay_name(bAnimListElem *ale, char *name)
2946 {
2947         MaskLayer *masklay = (MaskLayer *)ale->data;
2948         
2949         if (masklay && name)
2950                 BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
2951 }
2952
2953 /* name property for grease pencil layer entries */
2954 static bool acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
2955 {
2956         if (ale->data) {
2957                 RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
2958                 *prop = RNA_struct_name_property(ptr->type);
2959                 
2960                 return (*prop != NULL);
2961         }
2962
2963         return false;
2964 }
2965
2966 /* check if some setting exists for this channel */
2967 static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2968 {
2969         switch (setting) {
2970                 /* unsupported */
2971                 case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */
2972                 case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
2973                 case ACHANNEL_SETTING_SOLO: /* nla editor only */
2974                         return false;
2975                 
2976                 /* always available */
2977                 default:
2978                         return true;
2979         }
2980 }
2981
2982 /* get the appropriate flag(s) for the setting when it is valid  */
2983 static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2984 {
2985         /* clear extra return data first */
2986         *neg = false;
2987         
2988         switch (setting) {
2989                 case ACHANNEL_SETTING_SELECT: /* selected */
2990                         return MASK_LAYERFLAG_SELECT;
2991                 
2992                 case ACHANNEL_SETTING_PROTECT: /* protected */
2993                         return MASK_LAYERFLAG_LOCKED;
2994                 
2995                 default: /* unsupported */
2996                         return 0;
2997         }
2998 }
2999
3000 /* get pointer to the setting */
3001 static void *acf_masklay_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
3002 {
3003         MaskLayer *masklay = (MaskLayer *)ale->data;
3004         
3005         /* all flags are just in masklay->flag for now... */
3006         return GET_ACF_FLAG_PTR(masklay->flag, type);
3007 }
3008
3009 /* grease pencil layer type define */
3010 static bAnimChannelType ACF_MASKLAYER =
3011 {
3012         "Mask Layer",                   /* type name */
3013         ACHANNEL_ROLE_CHANNEL,          /* role */
3014         
3015         acf_generic_channel_color,      /* backdrop color */
3016         acf_generic_channel_backdrop,   /* backdrop */
3017         acf_generic_indention_flexible, /* indent level */
3018         acf_generic_group_offset,       /* offset */
3019         
3020         acf_masklay_name,               /* name */
3021         acf_masklay_name_prop,          /* name prop */
3022         NULL,                           /* icon */
3023         
3024         acf_masklay_setting_valid,      /* has setting */
3025         acf_masklay_setting_flag,       /* flag for setting */
3026         acf_masklay_setting_ptr         /* pointer for setting */
3027 };
3028
3029 /* NLA Track ----------------------------------------------- */
3030
3031 /* get backdrop color for nla track channels */
3032 static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
3033 {
3034         NlaTrack *nlt = (NlaTrack *)ale->data;
3035         AnimData *adt = ale->adt;
3036         bool nonSolo = false;
3037         
3038         /* is track enabled for solo drawing? */
3039         if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
3040                 if ((nlt->flag & NLATRACK_SOLO) == 0) {
3041                         /* tag for special non-solo handling */
3042                         nonSolo = true;
3043                 }
3044         }
3045         
3046         /* set color for nla track */
3047         UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
3048 }
3049
3050 /* name for nla track entries */
3051 static void acf_nlatrack_name(bAnimListElem *ale, char *name)
3052 {
3053         NlaTrack *nlt = (NlaTrack *)ale->data;
3054         
3055         if (nlt && name)
3056                 BLI_strncpy(name, nlt->name, ANIM_CHAN_NAME_SIZE);
3057 }
3058
3059 /* name property for nla track entries */
3060 static bool acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3061 {
3062         if (ale->data) {
3063                 RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
3064                 *prop = RNA_struct_name_property(ptr->type);
3065                 
3066                 return (*prop != NULL);
3067         }
3068         
3069         return false;
3070 }
3071