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