Dopesheet: Keyframe size can be adjusted as part of theme settings
[blender.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 "BLT_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_MOD_OFF: /* muted */
872                         *neg = 1;
873                         return AGRP_MODIFIERS_OFF;
874
875                 case ACHANNEL_SETTING_PROTECT: /* protected */
876                         return AGRP_PROTECTED;
877                         
878                 case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
879                         *neg = 1;
880                         return AGRP_NOTVISIBLE;
881                         
882                 default:
883                         /* this shouldn't happen */
884                         return 0;
885         }
886 }
887
888 /* get pointer to the setting */
889 static void *acf_group_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
890 {
891         bActionGroup *agrp = (bActionGroup *)ale->data;
892         
893         /* all flags are just in agrp->flag for now... */
894         return GET_ACF_FLAG_PTR(agrp->flag, type);
895 }
896
897 /* group type define */
898 static bAnimChannelType ACF_GROUP = 
899 {
900         "Group",                        /* type name */
901         ACHANNEL_ROLE_CHANNEL,          /* role */
902         
903         acf_group_color,                /* backdrop color */
904         acf_group_backdrop,             /* backdrop */
905         acf_generic_indention_0,        /* indent level */
906         acf_generic_group_offset,       /* offset */
907
908         acf_group_name,                 /* name */
909         acf_group_name_prop,            /* name prop */
910         NULL,                           /* icon */
911
912         acf_group_setting_valid,        /* has setting */
913         acf_group_setting_flag,         /* flag for setting */
914         acf_group_setting_ptr           /* pointer for setting */
915 };
916
917 /* F-Curve ------------------------------------------- */
918
919 /* name for fcurve entries */
920 static void acf_fcurve_name(bAnimListElem *ale, char *name)
921 {
922         getname_anim_fcurve(name, ale->id, ale->data);
923 }
924
925 /* "name" property for fcurve entries */
926 static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
927 {
928         FCurve *fcu = (FCurve *)ale->data;
929         
930         /* Ctrl-Click Usability Convenience Hack: 
931          * For disabled F-Curves, allow access to the RNA Path 
932          * as our "name" so that user can perform quick fixes
933          */
934         if (fcu->flag & FCURVE_DISABLED) {
935                 RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
936                 *prop = RNA_struct_find_property(ptr, "data_path");
937         }
938         else {
939                 /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
940                 *prop = NULL;
941         }
942         
943         return (*prop != NULL);
944 }
945
946 /* check if some setting exists for this channel */
947 static bool acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
948 {
949         FCurve *fcu = (FCurve *)ale->data;
950         
951         switch (setting) {
952                 /* unsupported */
953                 case ACHANNEL_SETTING_SOLO:   /* Solo Flag is only for NLA */
954                 case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
955                 case ACHANNEL_SETTING_PINNED: /* This is only for NLA Actions */
956                         return false;
957                 
958                 /* conditionally available */
959                 case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
960                         if (fcu->bezt)
961                                 return true;
962                         else
963                                 return false;  // NOTE: in this special case, we need to draw ICON_ZOOMOUT
964                                 
965                 case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
966                         return (ac->spacetype == SPACE_IPO);
967                         
968                 /* always available */
969                 default:
970                         return true;
971         }
972 }
973
974 /* get the appropriate flag(s) for the setting when it is valid  */
975 static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
976 {
977         /* clear extra return data first */
978         *neg = false;
979         
980         switch (setting) {
981                 case ACHANNEL_SETTING_SELECT: /* selected */
982                         return FCURVE_SELECTED;
983                         
984                 case ACHANNEL_SETTING_MUTE: /* muted */
985                         return FCURVE_MUTED;
986                         
987                 case ACHANNEL_SETTING_PROTECT: /* protected */
988                         return FCURVE_PROTECTED;
989                         
990                 case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
991                         return FCURVE_VISIBLE;
992                         
993                 case ACHANNEL_SETTING_MOD_OFF:
994                         *neg = 1;
995                         return FCURVE_MOD_OFF;
996
997                 default: /* unsupported */
998                         return 0;
999         }
1000 }
1001
1002 /* get pointer to the setting */
1003 static void *acf_fcurve_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
1004 {
1005         FCurve *fcu = (FCurve *)ale->data;
1006         
1007         /* all flags are just in agrp->flag for now... */
1008         return GET_ACF_FLAG_PTR(fcu->flag, type);
1009 }
1010
1011 /* fcurve type define */
1012 static bAnimChannelType ACF_FCURVE = 
1013 {
1014         "F-Curve",                      /* type name */
1015         ACHANNEL_ROLE_CHANNEL,          /* role */
1016         
1017         acf_generic_channel_color,      /* backdrop color */
1018         acf_generic_channel_backdrop,   /* backdrop */
1019         acf_generic_indention_flexible, /* indent level */      // xxx rename this to f-curves only?
1020         acf_generic_group_offset,       /* offset */
1021
1022         acf_fcurve_name,                /* name */
1023         acf_fcurve_name_prop,           /* name prop */
1024         NULL,                           /* icon */
1025
1026         acf_fcurve_setting_valid,       /* has setting */
1027         acf_fcurve_setting_flag,        /* flag for setting */
1028         acf_fcurve_setting_ptr          /* pointer for setting */
1029 };
1030
1031 /* NLA Control FCurves Expander ----------------------- */
1032
1033 /* get backdrop color for nla controls widget */
1034 static void acf_nla_controls_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
1035 {
1036         // TODO: give this its own theme setting?
1037         UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color);
1038 }
1039
1040 /* backdrop for nla controls expander widget */
1041 static void acf_nla_controls_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
1042 {
1043         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
1044         View2D *v2d = &ac->ar->v2d;
1045         short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
1046         short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
1047         float color[3];
1048         
1049         /* set backdrop drawing color */
1050         acf->get_backdrop_color(ac, ale, color);
1051         glColor3fv(color);
1052         
1053         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
1054         UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
1055         UI_draw_roundbox_gl_mode(GL_POLYGON, offset,  yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5);
1056 }
1057
1058 /* name for nla controls expander entries */
1059 static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name)
1060 {
1061         BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
1062 }
1063
1064 /* check if some setting exists for this channel */
1065 static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
1066 {
1067         /* for now, all settings are supported, though some are only conditionally */
1068         switch (setting) {
1069                 /* supported */
1070                 case ACHANNEL_SETTING_EXPAND:
1071                         return true;
1072                 
1073                 // TOOD: selected?
1074                 
1075                 default: /* unsupported */
1076                         return false;
1077         }
1078 }
1079
1080 /* get the appropriate flag(s) for the setting when it is valid  */
1081 static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1082 {
1083         /* clear extra return data first */
1084         *neg = false;
1085         
1086         switch (setting) {
1087                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1088                         *neg = true;
1089                         return ADT_NLA_SKEYS_COLLAPSED;
1090                 
1091                 default:
1092                         /* this shouldn't happen */
1093                         return 0;
1094         }
1095 }
1096
1097 /* get pointer to the setting */
1098 static void *acf_nla_controls_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
1099 {
1100         AnimData *adt = (AnimData *)ale->data;
1101         
1102         /* all flags are just in adt->flag for now... */
1103         return GET_ACF_FLAG_PTR(adt->flag, type);
1104 }
1105
1106 static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
1107 {
1108         return ICON_NLA;
1109 }
1110
1111 /* NLA Control FCurves Expander type define */
1112 static bAnimChannelType ACF_NLACONTROLS = 
1113 {
1114         "NLA Controls Expander",        /* type name */
1115         ACHANNEL_ROLE_EXPANDER,         /* role */
1116         
1117         acf_nla_controls_color,         /* backdrop color */
1118         acf_nla_controls_backdrop,      /* backdrop */
1119         acf_generic_indention_0,        /* indent level */
1120         acf_generic_group_offset,       /* offset */
1121
1122         acf_nla_controls_name,          /* name */
1123         NULL,                           /* name prop */
1124         acf_nla_controls_icon,          /* icon */
1125
1126         acf_nla_controls_setting_valid, /* has setting */
1127         acf_nla_controls_setting_flag,  /* flag for setting */
1128         acf_nla_controls_setting_ptr    /* pointer for setting */
1129 };
1130
1131
1132 /* NLA Control F-Curve -------------------------------- */
1133
1134 /* name for nla control fcurve entries */
1135 static void acf_nla_curve_name(bAnimListElem *ale, char *name)
1136 {
1137         NlaStrip *strip = ale->owner;
1138         FCurve *fcu = ale->data;
1139         PropertyRNA *prop;
1140         
1141         /* try to get RNA property that this shortened path (relative to the strip) refers to */
1142         prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path);
1143         if (prop) {
1144                 /* "name" of this strip displays the UI identifier + the name of the NlaStrip */
1145                 BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name);
1146         }
1147         else {
1148                 /* unknown property... */
1149                 BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
1150         }
1151 }
1152
1153
1154 /* NLA Control F-Curve type define */
1155 static bAnimChannelType ACF_NLACURVE = 
1156 {
1157         "NLA Control F-Curve",          /* type name */
1158         ACHANNEL_ROLE_CHANNEL,          /* role */
1159         
1160         acf_generic_channel_color,      /* backdrop color */
1161         acf_generic_channel_backdrop,   /* backdrop */
1162         acf_generic_indention_1,        /* indent level */
1163         acf_generic_group_offset,       /* offset */
1164
1165         acf_nla_curve_name,             /* name */
1166         acf_fcurve_name_prop,           /* name prop */
1167         NULL,                           /* icon */
1168
1169         acf_fcurve_setting_valid,       /* has setting */
1170         acf_fcurve_setting_flag,        /* flag for setting */
1171         acf_fcurve_setting_ptr          /* pointer for setting */
1172 };
1173
1174 /* Object Action Expander  ------------------------------------------- */
1175
1176 // TODO: just get this from RNA?
1177 static int acf_fillactd_icon(bAnimListElem *UNUSED(ale))
1178 {
1179         return ICON_ACTION;
1180 }
1181
1182 /* check if some setting exists for this channel */
1183 static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
1184 {
1185         switch (setting) {
1186                 /* only select and expand supported */
1187                 case ACHANNEL_SETTING_SELECT:
1188                 case ACHANNEL_SETTING_EXPAND:
1189                         return true;
1190                         
1191                 default:
1192                         return false;
1193         }
1194 }
1195
1196 /* get the appropriate flag(s) for the setting when it is valid  */
1197 static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1198 {
1199         /* clear extra return data first */
1200         *neg = false;
1201         
1202         switch (setting) {
1203                 case ACHANNEL_SETTING_SELECT: /* selected */
1204                         return ADT_UI_SELECTED;
1205                         
1206                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1207                         *neg = true;
1208                         return ACT_COLLAPSED;
1209                 
1210                 default: /* unsupported */
1211                         return 0;
1212         }
1213 }
1214
1215 /* get pointer to the setting */
1216 static void *acf_fillactd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1217 {
1218         bAction *act = (bAction *)ale->data;
1219         AnimData *adt = ale->adt;
1220         
1221         /* clear extra return data first */
1222         *type = 0;
1223         
1224         switch (setting) {
1225                 case ACHANNEL_SETTING_SELECT: /* selected */
1226                         if (adt) {
1227                                 return GET_ACF_FLAG_PTR(adt->flag, type);
1228                         }
1229                         return NULL;
1230
1231                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1232                         return GET_ACF_FLAG_PTR(act->flag, type);
1233                 
1234                 default: /* unsupported */
1235                         return NULL;
1236         }
1237 }
1238
1239 /* object action expander type define */
1240 static bAnimChannelType ACF_FILLACTD = 
1241 {
1242         "Ob-Action Filler",             /* type name */
1243         ACHANNEL_ROLE_EXPANDER,         /* role */
1244         
1245         acf_generic_dataexpand_color,   /* backdrop color */
1246         acf_generic_dataexpand_backdrop, /* backdrop */
1247         acf_generic_indention_1,        /* indent level */
1248         acf_generic_basic_offset,       /* offset */
1249
1250         acf_generic_idblock_name,       /* name */
1251         acf_generic_idfill_name_prop,    /* name prop */
1252         acf_fillactd_icon,              /* icon */
1253
1254         acf_fillactd_setting_valid,     /* has setting */
1255         acf_fillactd_setting_flag,      /* flag for setting */
1256         acf_fillactd_setting_ptr        /* pointer for setting */
1257 };
1258
1259 /* Drivers Expander  ------------------------------------------- */
1260
1261 // TODO: just get this from RNA?
1262 static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
1263 {
1264         return ICON_DRIVER;
1265 }
1266
1267 static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
1268 {
1269         BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
1270 }
1271
1272 /* check if some setting exists for this channel */
1273 // TODO: this could be made more generic
1274 static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
1275 {
1276         switch (setting) {
1277                 /* only expand supported */
1278                 case ACHANNEL_SETTING_EXPAND:
1279                         return true;
1280                         
1281                 default:
1282                         return false;
1283         }
1284 }
1285
1286 /* get the appropriate flag(s) for the setting when it is valid  */
1287 static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1288 {
1289         /* clear extra return data first */
1290         *neg = false;
1291         
1292         switch (setting) {
1293                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1294                         *neg = true;
1295                         return ADT_DRIVERS_COLLAPSED;
1296                 
1297                 default: /* unsupported */
1298                         return 0;
1299         }
1300 }
1301
1302 /* get pointer to the setting */
1303 static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1304 {
1305         AnimData *adt = (AnimData *)ale->data;
1306         
1307         /* clear extra return data first */
1308         *type = 0;
1309         
1310         switch (setting) {
1311                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1312                         return GET_ACF_FLAG_PTR(adt->flag, type);
1313                 
1314                 default: /* unsupported */
1315                         return NULL;
1316         }
1317 }
1318
1319 /* drivers expander type define */
1320 static bAnimChannelType ACF_FILLDRIVERS = 
1321 {
1322         "Drivers Filler",               /* type name */
1323         ACHANNEL_ROLE_EXPANDER,         /* role */
1324         
1325         acf_generic_dataexpand_color,   /* backdrop color */
1326         acf_generic_dataexpand_backdrop, /* backdrop */
1327         acf_generic_indention_1,        /* indent level */
1328         acf_generic_basic_offset,       /* offset */
1329
1330         acf_filldrivers_name,           /* name */
1331         NULL,                           /* name prop */
1332         acf_filldrivers_icon,           /* icon */
1333
1334         acf_filldrivers_setting_valid,  /* has setting */
1335         acf_filldrivers_setting_flag,   /* flag for setting */
1336         acf_filldrivers_setting_ptr     /* pointer for setting */
1337 };
1338
1339
1340 /* Material Expander  ------------------------------------------- */
1341
1342 // TODO: just get this from RNA?
1343 static int acf_dsmat_icon(bAnimListElem *UNUSED(ale))
1344 {
1345         return ICON_MATERIAL_DATA;
1346 }
1347
1348 /* get the appropriate flag(s) for the setting when it is valid  */
1349 static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1350 {
1351         /* clear extra return data first */
1352         *neg = false;
1353         
1354         switch (setting) {
1355                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1356                         return MA_DS_EXPAND;
1357                         
1358                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1359                         return ADT_NLA_EVAL_OFF;
1360                         
1361                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1362                         *neg = true;
1363                         return ADT_CURVES_NOT_VISIBLE;
1364                         
1365                 case ACHANNEL_SETTING_SELECT: /* selected */
1366                         return ADT_UI_SELECTED;
1367                 
1368                 default: /* unsupported */
1369                         return 0;
1370         }
1371 }
1372
1373 /* get pointer to the setting */
1374 static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1375 {
1376         Material *ma = (Material *)ale->data;
1377         
1378         /* clear extra return data first */
1379         *type = 0;
1380         
1381         switch (setting) {
1382                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1383                         return GET_ACF_FLAG_PTR(ma->flag, type);
1384                         
1385                 case ACHANNEL_SETTING_SELECT: /* selected */
1386                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1387                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1388                         if (ma->adt)
1389                                 return GET_ACF_FLAG_PTR(ma->adt->flag, type);
1390                         return NULL;
1391
1392                 default: /* unsupported */
1393                         return NULL;
1394         }
1395 }
1396
1397 /* material expander type define */
1398 static bAnimChannelType ACF_DSMAT =
1399 {
1400         "Material Data Expander",       /* type name */
1401         ACHANNEL_ROLE_EXPANDER,         /* role */
1402         
1403         acf_generic_dataexpand_color,   /* backdrop color */
1404         acf_generic_dataexpand_backdrop, /* backdrop */
1405         acf_generic_indention_1,        /* indent level */
1406         acf_generic_basic_offset,       /* offset */
1407
1408         acf_generic_idblock_name,       /* name */
1409         acf_generic_idblock_name_prop,   /* name prop */
1410         acf_dsmat_icon,                 /* icon */
1411
1412         acf_generic_dataexpand_setting_valid,   /* has setting */
1413         acf_dsmat_setting_flag,                 /* flag for setting */
1414         acf_dsmat_setting_ptr                   /* pointer for setting */
1415 };
1416
1417 /* Lamp Expander  ------------------------------------------- */
1418
1419 // TODO: just get this from RNA?
1420 static int acf_dslam_icon(bAnimListElem *UNUSED(ale))
1421 {
1422         return ICON_LAMP_DATA;
1423 }
1424
1425 /* get the appropriate flag(s) for the setting when it is valid  */
1426 static int acf_dslam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1427 {
1428         /* clear extra return data first */
1429         *neg = false;
1430         
1431         switch (setting) {
1432                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1433                         return LA_DS_EXPAND;
1434                         
1435                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1436                         return ADT_NLA_EVAL_OFF;
1437                         
1438                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1439                         *neg = true;
1440                         return ADT_CURVES_NOT_VISIBLE;
1441                         
1442                 case ACHANNEL_SETTING_SELECT: /* selected */
1443                         return ADT_UI_SELECTED;
1444                 
1445                 default: /* unsupported */
1446                         return 0;
1447         }
1448 }
1449
1450 /* get pointer to the setting */
1451 static void *acf_dslam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1452 {
1453         Lamp *la = (Lamp *)ale->data;
1454         
1455         /* clear extra return data first */
1456         *type = 0;
1457         
1458         switch (setting) {
1459                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1460                         return GET_ACF_FLAG_PTR(la->flag, type);
1461                         
1462                 case ACHANNEL_SETTING_SELECT: /* selected */
1463                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1464                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1465                         if (la->adt)
1466                                 return GET_ACF_FLAG_PTR(la->adt->flag, type);
1467                         return NULL;
1468                 
1469                 default: /* unsupported */
1470                         return NULL;
1471         }
1472 }
1473
1474 /* lamp expander type define */
1475 static bAnimChannelType ACF_DSLAM =
1476 {
1477         "Lamp Expander",                /* type name */
1478         ACHANNEL_ROLE_EXPANDER,         /* role */
1479         
1480         acf_generic_dataexpand_color,   /* backdrop color */
1481         acf_generic_dataexpand_backdrop, /* backdrop */
1482         acf_generic_indention_1,        /* indent level */
1483         acf_generic_basic_offset,       /* offset */
1484
1485         acf_generic_idblock_name,       /* name */
1486         acf_generic_idblock_name_prop,   /* name prop */
1487         acf_dslam_icon,                 /* icon */
1488
1489         acf_generic_dataexpand_setting_valid,   /* has setting */
1490         acf_dslam_setting_flag,                 /* flag for setting */
1491         acf_dslam_setting_ptr                   /* pointer for setting */
1492 };
1493
1494 /* Texture Expander  ------------------------------------------- */
1495
1496 // TODO: just get this from RNA?
1497 static int acf_dstex_icon(bAnimListElem *UNUSED(ale))
1498 {
1499         return ICON_TEXTURE_DATA;
1500 }
1501
1502 /* offset for texture expanders */
1503 // FIXME: soon to be obsolete?
1504 static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
1505 {
1506         return 14; // XXX: simply include this in indention instead?
1507 }
1508
1509 /* get the appropriate flag(s) for the setting when it is valid  */
1510 static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1511 {
1512         /* clear extra return data first */
1513         *neg = false;
1514         
1515         switch (setting) {
1516                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1517                         return TEX_DS_EXPAND;
1518                         
1519                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1520                         return ADT_NLA_EVAL_OFF;
1521                         
1522                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1523                         *neg = true;
1524                         return ADT_CURVES_NOT_VISIBLE;
1525                         
1526                 case ACHANNEL_SETTING_SELECT: /* selected */
1527                         return ADT_UI_SELECTED;
1528                 
1529                 default: /* unsupported */
1530                         return 0;
1531         }
1532 }
1533
1534 /* get pointer to the setting */
1535 static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1536 {
1537         Tex *tex = (Tex *)ale->data;
1538         
1539         /* clear extra return data first */
1540         *type = 0;
1541         
1542         switch (setting) {
1543                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1544                         return GET_ACF_FLAG_PTR(tex->flag, type);
1545                         
1546                 case ACHANNEL_SETTING_SELECT: /* selected */
1547                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1548                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1549                         if (tex->adt)
1550                                 return GET_ACF_FLAG_PTR(tex->adt->flag, type);
1551                         return NULL;
1552                 
1553                 default: /* unsupported */
1554                         return NULL;
1555         }
1556 }
1557
1558 /* texture expander type define */
1559 static bAnimChannelType ACF_DSTEX =
1560 {
1561         "Texture Data Expander",        /* type name */
1562         ACHANNEL_ROLE_EXPANDER,         /* role */
1563         
1564         acf_generic_dataexpand_color,   /* backdrop color */
1565         acf_generic_dataexpand_backdrop, /* backdrop */
1566         acf_generic_indention_1,        /* indent level */
1567         acf_dstex_offset,               /* offset */
1568
1569         acf_generic_idblock_name,       /* name */
1570         acf_generic_idfill_name_prop,    /* name prop */
1571         acf_dstex_icon,                 /* icon */
1572
1573         acf_generic_dataexpand_setting_valid,   /* has setting */
1574         acf_dstex_setting_flag,                 /* flag for setting */
1575         acf_dstex_setting_ptr                   /* pointer for setting */
1576 };
1577
1578 /* Camera Expander  ------------------------------------------- */
1579
1580 // TODO: just get this from RNA?
1581 static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
1582 {
1583         return ICON_CAMERA_DATA;
1584 }
1585
1586 /* get the appropriate flag(s) for the setting when it is valid  */
1587 static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1588 {
1589         /* clear extra return data first */
1590         *neg = false;
1591         
1592         switch (setting) {
1593                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1594                         return CAM_DS_EXPAND;
1595                         
1596                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1597                         return ADT_NLA_EVAL_OFF;
1598                         
1599                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1600                         *neg = true;
1601                         return ADT_CURVES_NOT_VISIBLE;
1602                         
1603                 case ACHANNEL_SETTING_SELECT: /* selected */
1604                         return ADT_UI_SELECTED;
1605                 
1606                 default: /* unsupported */
1607                         return 0;
1608         }
1609 }
1610
1611 /* get pointer to the setting */
1612 static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1613 {
1614         Camera *ca = (Camera *)ale->data;
1615         
1616         /* clear extra return data first */
1617         *type = 0;
1618         
1619         switch (setting) {
1620                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1621                         return GET_ACF_FLAG_PTR(ca->flag, type);
1622                         
1623                 case ACHANNEL_SETTING_SELECT: /* selected */
1624                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1625                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1626                         if (ca->adt)
1627                                 return GET_ACF_FLAG_PTR(ca->adt->flag, type);
1628                         return NULL;
1629                 
1630                 default: /* unsupported */
1631                         return NULL;
1632         }
1633 }
1634
1635 /* camera expander type define */
1636 static bAnimChannelType ACF_DSCAM =
1637 {
1638         "Camera Expander",              /* type name */
1639         ACHANNEL_ROLE_EXPANDER,         /* role */
1640         
1641         acf_generic_dataexpand_color,   /* backdrop color */
1642         acf_generic_dataexpand_backdrop, /* backdrop */
1643         acf_generic_indention_1,        /* indent level */
1644         acf_generic_basic_offset,       /* offset */
1645
1646         acf_generic_idblock_name,       /* name */
1647         acf_generic_idfill_name_prop,    /* name prop */
1648         acf_dscam_icon,                 /* icon */
1649
1650         acf_generic_dataexpand_setting_valid,   /* has setting */
1651         acf_dscam_setting_flag,                 /* flag for setting */
1652         acf_dscam_setting_ptr                   /* pointer for setting */
1653 };
1654
1655 /* Curve Expander  ------------------------------------------- */
1656
1657 // TODO: just get this from RNA?
1658 static int acf_dscur_icon(bAnimListElem *ale)
1659 {
1660         Curve *cu = (Curve *)ale->data;
1661         short obtype = BKE_curve_type_get(cu);
1662         
1663         switch (obtype) {
1664                 case OB_FONT:
1665                         return ICON_FONT_DATA;
1666                 case OB_SURF:
1667                         return ICON_SURFACE_DATA;
1668                 default:
1669                         return ICON_CURVE_DATA;
1670         }
1671 }
1672
1673 /* get the appropriate flag(s) for the setting when it is valid  */
1674 static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1675 {
1676         /* clear extra return data first */
1677         *neg = false;
1678         
1679         switch (setting) {
1680                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1681                         return CU_DS_EXPAND;
1682                         
1683                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1684                         return ADT_NLA_EVAL_OFF;
1685                         
1686                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1687                         *neg = true;
1688                         return ADT_CURVES_NOT_VISIBLE;
1689                         
1690                 case ACHANNEL_SETTING_SELECT: /* selected */
1691                         return ADT_UI_SELECTED;
1692                 
1693                 default: /* unsupported */
1694                         return 0;
1695         }
1696 }
1697
1698 /* get pointer to the setting */
1699 static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1700 {
1701         Curve *cu = (Curve *)ale->data;
1702         
1703         /* clear extra return data first */
1704         *type = 0;
1705         
1706         switch (setting) {
1707                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1708                         return GET_ACF_FLAG_PTR(cu->flag, type);
1709                         
1710                 case ACHANNEL_SETTING_SELECT: /* selected */
1711                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1712                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1713                         if (cu->adt)
1714                                 return GET_ACF_FLAG_PTR(cu->adt->flag, type);
1715                         return NULL;
1716                 
1717                 default: /* unsupported */
1718                         return NULL;
1719         }
1720 }
1721
1722 /* curve expander type define */
1723 static bAnimChannelType ACF_DSCUR =
1724 {
1725         "Curve Expander",               /* type name */
1726         ACHANNEL_ROLE_EXPANDER,         /* role */
1727         
1728         acf_generic_dataexpand_color,   /* backdrop color */
1729         acf_generic_dataexpand_backdrop, /* backdrop */
1730         acf_generic_indention_1,        /* indent level */
1731         acf_generic_basic_offset,       /* offset */
1732
1733         acf_generic_idblock_name,       /* name */
1734         acf_generic_idblock_name_prop,   /* name prop */
1735         acf_dscur_icon,                 /* icon */
1736
1737         acf_generic_dataexpand_setting_valid,   /* has setting */
1738         acf_dscur_setting_flag,                 /* flag for setting */
1739         acf_dscur_setting_ptr                   /* pointer for setting */
1740 };
1741
1742 /* Shape Key Expander  ------------------------------------------- */
1743
1744 // TODO: just get this from RNA?
1745 static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
1746 {
1747         return ICON_SHAPEKEY_DATA;
1748 }
1749
1750 /* get the appropriate flag(s) for the setting when it is valid  */
1751 static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1752 {
1753         /* clear extra return data first */
1754         *neg = false;
1755         
1756         switch (setting) {
1757                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1758                         return KEY_DS_EXPAND;
1759                         
1760                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1761                         return ADT_NLA_EVAL_OFF;
1762                         
1763                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1764                         *neg = true;
1765                         return ADT_CURVES_NOT_VISIBLE;
1766                         
1767                 case ACHANNEL_SETTING_SELECT: /* selected */
1768                         return ADT_UI_SELECTED;
1769                 
1770                 default: /* unsupported */
1771                         return 0;
1772         }
1773 }
1774
1775 /* get pointer to the setting */
1776 static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1777 {
1778         Key *key = (Key *)ale->data;
1779         
1780         /* clear extra return data first */
1781         *type = 0;
1782         
1783         switch (setting) {
1784                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1785                         return GET_ACF_FLAG_PTR(key->flag, type);
1786                         
1787                 case ACHANNEL_SETTING_SELECT: /* selected */
1788                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1789                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1790                         if (key->adt)
1791                                 return GET_ACF_FLAG_PTR(key->adt->flag, type);
1792                         return NULL;
1793                 
1794                 default: /* unsupported */
1795                         return NULL;
1796         }
1797 }
1798
1799 /* shapekey expander type define */
1800 static bAnimChannelType ACF_DSSKEY =
1801 {
1802         "Shape Key Expander",           /* type name */
1803         ACHANNEL_ROLE_EXPANDER,         /* role */
1804         
1805         acf_generic_dataexpand_color,   /* backdrop color */
1806         acf_generic_dataexpand_backdrop, /* backdrop */
1807         acf_generic_indention_1,        /* indent level */
1808         acf_generic_basic_offset,       /* offset */
1809
1810         acf_generic_idblock_name,       /* name */
1811         acf_generic_idblock_name_prop,   /* name prop */
1812         acf_dsskey_icon,                /* icon */
1813
1814         acf_generic_dataexpand_setting_valid,   /* has setting */
1815         acf_dsskey_setting_flag,                /* flag for setting */
1816         acf_dsskey_setting_ptr                  /* pointer for setting */
1817 };
1818
1819 /* World Expander  ------------------------------------------- */
1820
1821 // TODO: just get this from RNA?
1822 static int acf_dswor_icon(bAnimListElem *UNUSED(ale))
1823 {
1824         return ICON_WORLD_DATA;
1825 }
1826
1827 /* get the appropriate flag(s) for the setting when it is valid  */
1828 static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1829 {
1830         /* clear extra return data first */
1831         *neg = false;
1832         
1833         switch (setting) {
1834                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1835                         return WO_DS_EXPAND;
1836                         
1837                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1838                         return ADT_NLA_EVAL_OFF;
1839                         
1840                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1841                         *neg = true;
1842                         return ADT_CURVES_NOT_VISIBLE;
1843                         
1844                 case ACHANNEL_SETTING_SELECT: /* selected */
1845                         return ADT_UI_SELECTED;
1846                 
1847                 default: /* unsupported */
1848                         return 0;
1849         }
1850 }
1851
1852 /* get pointer to the setting */
1853 static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1854 {
1855         World *wo = (World *)ale->data;
1856         
1857         /* clear extra return data first */
1858         *type = 0;
1859         
1860         switch (setting) {
1861                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1862                         return GET_ACF_FLAG_PTR(wo->flag, type);
1863                         
1864                 case ACHANNEL_SETTING_SELECT: /* selected */
1865                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1866                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1867                         if (wo->adt)
1868                                 return GET_ACF_FLAG_PTR(wo->adt->flag, type);
1869                         return NULL;
1870                 
1871                 default: /* unsupported */
1872                         return NULL;
1873         }
1874 }
1875
1876 /* world expander type define */
1877 static bAnimChannelType ACF_DSWOR =
1878 {
1879         "World Expander",               /* type name */
1880         ACHANNEL_ROLE_EXPANDER,         /* role */
1881         
1882         acf_generic_dataexpand_color,   /* backdrop color */
1883         acf_generic_dataexpand_backdrop, /* backdrop */
1884         acf_generic_indention_1,        /* indent level */
1885         acf_generic_basic_offset,       /* offset */
1886
1887         acf_generic_idblock_name,       /* name */
1888         acf_generic_idfill_name_prop,    /* name prop */
1889         acf_dswor_icon,                 /* icon */
1890
1891         acf_generic_dataexpand_setting_valid,   /* has setting */
1892         acf_dswor_setting_flag,                 /* flag for setting */
1893         acf_dswor_setting_ptr                   /* pointer for setting */
1894 };
1895
1896 /* Particle Expander  ------------------------------------------- */
1897
1898 // TODO: just get this from RNA?
1899 static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
1900 {
1901         return ICON_PARTICLE_DATA;
1902 }
1903
1904 /* get the appropriate flag(s) for the setting when it is valid  */
1905 static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1906 {
1907         /* clear extra return data first */
1908         *neg = false;
1909         
1910         switch (setting) {
1911                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1912                         return PART_DS_EXPAND;
1913                         
1914                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1915                         return ADT_NLA_EVAL_OFF;
1916                         
1917                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1918                         *neg = true;
1919                         return ADT_CURVES_NOT_VISIBLE;
1920                         
1921                 case ACHANNEL_SETTING_SELECT: /* selected */
1922                         return ADT_UI_SELECTED;
1923                 
1924                 default: /* unsupported */
1925                         return 0;
1926         }
1927 }
1928
1929 /* get pointer to the setting */
1930 static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1931 {
1932         ParticleSettings *part = (ParticleSettings *)ale->data;
1933         
1934         /* clear extra return data first */
1935         *type = 0;
1936         
1937         switch (setting) {
1938                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1939                         return GET_ACF_FLAG_PTR(part->flag, type);
1940                         
1941                 case ACHANNEL_SETTING_SELECT: /* selected */
1942                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1943                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1944                         if (part->adt)
1945                                 return GET_ACF_FLAG_PTR(part->adt->flag, type);
1946                         return NULL;
1947                 
1948                 default: /* unsupported */
1949                         return NULL;
1950         }
1951 }
1952
1953 /* particle expander type define */
1954 static bAnimChannelType ACF_DSPART =
1955 {
1956         "Particle Data Expander",       /* type name */
1957         ACHANNEL_ROLE_EXPANDER,         /* role */
1958         
1959         acf_generic_dataexpand_color,   /* backdrop color */
1960         acf_generic_dataexpand_backdrop, /* backdrop */
1961         acf_generic_indention_1,        /* indent level */
1962         acf_generic_basic_offset,       /* offset */
1963
1964         acf_generic_idblock_name,       /* name */
1965         acf_generic_idblock_name_prop,   /* name prop */
1966         acf_dspart_icon,                /* icon */
1967
1968         acf_generic_dataexpand_setting_valid,   /* has setting */
1969         acf_dspart_setting_flag,                /* flag for setting */
1970         acf_dspart_setting_ptr                  /* pointer for setting */
1971 };
1972
1973 /* MetaBall Expander  ------------------------------------------- */
1974
1975 // TODO: just get this from RNA?
1976 static int acf_dsmball_icon(bAnimListElem *UNUSED(ale))
1977 {
1978         return ICON_META_DATA;
1979 }
1980
1981 /* get the appropriate flag(s) for the setting when it is valid  */
1982 static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
1983 {
1984         /* clear extra return data first */
1985         *neg = false;
1986         
1987         switch (setting) {
1988                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1989                         return MB_DS_EXPAND;
1990                         
1991                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1992                         return ADT_NLA_EVAL_OFF;
1993                         
1994                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1995                         *neg = true;
1996                         return ADT_CURVES_NOT_VISIBLE;
1997                 
1998                 case ACHANNEL_SETTING_SELECT: /* selected */
1999                         return ADT_UI_SELECTED;
2000                 
2001                 default: /* unsupported */
2002                         return 0;
2003         }
2004 }
2005
2006 /* get pointer to the setting */
2007 static void *acf_dsmball_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2008 {
2009         MetaBall *mb = (MetaBall *)ale->data;
2010         
2011         /* clear extra return data first */
2012         *type = 0;
2013         
2014         switch (setting) {
2015                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2016                         return GET_ACF_FLAG_PTR(mb->flag2, type);
2017                         
2018                 case ACHANNEL_SETTING_SELECT: /* selected */
2019                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2020                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2021                         if (mb->adt)
2022                                 return GET_ACF_FLAG_PTR(mb->adt->flag, type);
2023                         return NULL;
2024                 
2025                 default: /* unsupported */
2026                         return NULL;
2027         }
2028 }
2029
2030 /* metaball expander type define */
2031 static bAnimChannelType ACF_DSMBALL =
2032 {
2033         "Metaball Expander",            /* type name */
2034         ACHANNEL_ROLE_EXPANDER,         /* role */
2035         
2036         acf_generic_dataexpand_color,   /* backdrop color */
2037         acf_generic_dataexpand_backdrop, /* backdrop */
2038         acf_generic_indention_1,        /* indent level */
2039         acf_generic_basic_offset,       /* offset */
2040
2041         acf_generic_idblock_name,       /* name */
2042         acf_generic_idblock_name_prop,   /* name prop */
2043         acf_dsmball_icon,               /* icon */
2044
2045         acf_generic_dataexpand_setting_valid,   /* has setting */
2046         acf_dsmball_setting_flag,               /* flag for setting */
2047         acf_dsmball_setting_ptr                 /* pointer for setting */
2048 };
2049
2050 /* Armature Expander  ------------------------------------------- */
2051
2052 // TODO: just get this from RNA?
2053 static int acf_dsarm_icon(bAnimListElem *UNUSED(ale))
2054 {
2055         return ICON_ARMATURE_DATA;
2056 }
2057
2058 /* get the appropriate flag(s) for the setting when it is valid  */
2059 static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2060 {
2061         /* clear extra return data first */
2062         *neg = false;
2063         
2064         switch (setting) {
2065                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2066                         return ARM_DS_EXPAND;
2067                         
2068                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2069                         return ADT_NLA_EVAL_OFF;
2070                         
2071                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2072                         *neg = true;
2073                         return ADT_CURVES_NOT_VISIBLE;
2074                         
2075                 case ACHANNEL_SETTING_SELECT: /* selected */
2076                         return ADT_UI_SELECTED;
2077                 
2078                 default: /* unsupported */
2079                         return 0;
2080         }
2081 }
2082
2083 /* get pointer to the setting */
2084 static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2085 {
2086         bArmature *arm = (bArmature *)ale->data;
2087         
2088         /* clear extra return data first */
2089         *type = 0;
2090         
2091         switch (setting) {
2092                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2093                         return GET_ACF_FLAG_PTR(arm->flag, type);
2094                         
2095                 case ACHANNEL_SETTING_SELECT: /* selected */
2096                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2097                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2098                         if (arm->adt)
2099                                 return GET_ACF_FLAG_PTR(arm->adt->flag, type);
2100                         return NULL;
2101                 
2102                 default: /* unsupported */
2103                         return NULL;
2104         }
2105 }
2106
2107 /* metaball expander type define */
2108 static bAnimChannelType ACF_DSARM =
2109 {
2110         "Armature Expander",            /* type name */
2111         ACHANNEL_ROLE_EXPANDER,         /* role */
2112         
2113         acf_generic_dataexpand_color,   /* backdrop color */
2114         acf_generic_dataexpand_backdrop, /* backdrop */
2115         acf_generic_indention_1,        /* indent level */
2116         acf_generic_basic_offset,       /* offset */
2117
2118         acf_generic_idblock_name,       /* name */
2119         acf_generic_idblock_name_prop,   /* name prop */
2120         acf_dsarm_icon,             /* icon */
2121
2122         acf_generic_dataexpand_setting_valid,   /* has setting */
2123         acf_dsarm_setting_flag,                 /* flag for setting */
2124         acf_dsarm_setting_ptr                   /* pointer for setting */
2125 };
2126
2127 /* NodeTree Expander  ------------------------------------------- */
2128
2129 // TODO: just get this from RNA?
2130 static int acf_dsntree_icon(bAnimListElem *UNUSED(ale))
2131 {
2132         return ICON_NODETREE;
2133 }
2134
2135 /* offset for nodetree expanders */
2136 static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale)
2137 {
2138         bNodeTree *ntree = (bNodeTree *)ale->data;
2139         short offset = acf_generic_basic_offset(ac, ale);
2140         
2141         offset += acf_nodetree_rootType_offset(ntree); 
2142         
2143         return offset;
2144 }
2145
2146 /* get the appropriate flag(s) for the setting when it is valid  */
2147 static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2148 {
2149         /* clear extra return data first */
2150         *neg = false;
2151         
2152         switch (setting) {
2153                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2154                         return NTREE_DS_EXPAND;
2155                         
2156                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2157                         return ADT_NLA_EVAL_OFF;
2158                         
2159                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2160                         *neg = true;
2161                         return ADT_CURVES_NOT_VISIBLE;
2162                         
2163                 case ACHANNEL_SETTING_SELECT: /* selected */
2164                         return ADT_UI_SELECTED;
2165                         
2166                 default: /* unsupported */
2167                         return 0;
2168         }
2169 }
2170
2171 /* get pointer to the setting */
2172 static void *acf_dsntree_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2173 {
2174         bNodeTree *ntree = (bNodeTree *)ale->data;
2175         
2176         /* clear extra return data first */
2177         *type = 0;
2178         
2179         switch (setting) {
2180                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2181                         return GET_ACF_FLAG_PTR(ntree->flag, type);
2182                         
2183                 case ACHANNEL_SETTING_SELECT: /* selected */
2184                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2185                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2186                         if (ntree->adt)
2187                                 return GET_ACF_FLAG_PTR(ntree->adt->flag, type);
2188                         return NULL;
2189                         
2190                 default: /* unsupported */
2191                         return NULL;
2192         }
2193 }
2194
2195 /* node tree expander type define */
2196 static bAnimChannelType ACF_DSNTREE =
2197 {
2198         "Node Tree Expander",           /* type name */
2199         ACHANNEL_ROLE_EXPANDER,         /* role */
2200         
2201         acf_generic_dataexpand_color,   /* backdrop color */
2202         acf_generic_dataexpand_backdrop, /* backdrop */
2203         acf_generic_indention_1,        /* indent level */
2204         acf_dsntree_offset,             /* offset */
2205
2206         acf_generic_idblock_name,       /* name */
2207         acf_generic_idblock_name_prop,   /* name prop */
2208         acf_dsntree_icon,               /* icon */
2209
2210         acf_generic_dataexpand_setting_valid,   /* has setting */
2211         acf_dsntree_setting_flag,               /* flag for setting */
2212         acf_dsntree_setting_ptr                 /* pointer for setting */
2213 };
2214
2215 /* LineStyle Expander  ------------------------------------------- */
2216
2217 /* TODO: just get this from RNA? */
2218 static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale))
2219 {
2220         return ICON_LINE_DATA;
2221 }
2222
2223 /* get the appropriate flag(s) for the setting when it is valid  */
2224 static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2225 {
2226         /* clear extra return data first */
2227         *neg = false;
2228         
2229         switch (setting) {
2230                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2231                         return LS_DS_EXPAND;
2232                         
2233                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2234                         return ADT_NLA_EVAL_OFF;
2235                         
2236                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2237                         *neg = true;
2238                         return ADT_CURVES_NOT_VISIBLE;
2239                         
2240                 case ACHANNEL_SETTING_SELECT: /* selected */
2241                         return ADT_UI_SELECTED;
2242                         
2243                 default: /* unsupported */
2244                         return 0;
2245         }
2246 }
2247
2248 /* get pointer to the setting */
2249 static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2250 {
2251         FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
2252         
2253         /* clear extra return data first */
2254         *type = 0;
2255         
2256         switch (setting) {
2257                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2258                         return GET_ACF_FLAG_PTR(linestyle->flag, type);
2259                         
2260                 case ACHANNEL_SETTING_SELECT: /* selected */
2261                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2262                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2263                         if (linestyle->adt)
2264                                 return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
2265                         return NULL;
2266                         
2267                 default: /* unsupported */
2268                         return NULL;
2269         }
2270 }
2271
2272 /* node tree expander type define */
2273 static bAnimChannelType ACF_DSLINESTYLE =
2274 {
2275         "Line Style Expander",                  /* type name */
2276         ACHANNEL_ROLE_EXPANDER,         /* role */
2277         
2278         acf_generic_dataexpand_color,   /* backdrop color */
2279         acf_generic_dataexpand_backdrop,/* backdrop */
2280         acf_generic_indention_1,                /* indent level */
2281         acf_generic_basic_offset,               /* offset */
2282         
2283         acf_generic_idblock_name,               /* name */
2284         acf_generic_idblock_name_prop,  /* name prop */
2285         acf_dslinestyle_icon,                   /* icon */
2286         
2287         acf_generic_dataexpand_setting_valid,   /* has setting */
2288         acf_dslinestyle_setting_flag,                   /* flag for setting */
2289         acf_dslinestyle_setting_ptr                             /* pointer for setting */
2290 };
2291
2292 /* Mesh Expander  ------------------------------------------- */
2293
2294 // TODO: just get this from RNA?
2295 static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale))
2296 {
2297         return ICON_MESH_DATA;
2298 }
2299
2300 /* get the appropriate flag(s) for the setting when it is valid  */
2301 static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2302 {
2303         /* clear extra return data first */
2304         *neg = false;
2305         
2306         switch (setting) {
2307                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2308                         return ME_DS_EXPAND;
2309                         
2310                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2311                         return ADT_NLA_EVAL_OFF;
2312                         
2313                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2314                         *neg = true;
2315                         return ADT_CURVES_NOT_VISIBLE;
2316                         
2317                 case ACHANNEL_SETTING_SELECT: /* selected */
2318                         return ADT_UI_SELECTED;
2319                         
2320                 default: /* unsupported */
2321                         return 0;
2322         }
2323 }
2324
2325 /* get pointer to the setting */
2326 static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2327 {
2328         Mesh *me = (Mesh *)ale->data;
2329         
2330         /* clear extra return data first */
2331         *type = 0;
2332         
2333         switch (setting) {
2334                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2335                         return GET_ACF_FLAG_PTR(me->flag, type);
2336                         
2337                 case ACHANNEL_SETTING_SELECT: /* selected */
2338                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2339                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2340                         if (me->adt)
2341                                 return GET_ACF_FLAG_PTR(me->adt->flag, type);
2342                         return NULL;
2343                         
2344                 default: /* unsupported */
2345                         return NULL;
2346         }
2347 }
2348
2349 /* node tree expander type define */
2350 static bAnimChannelType ACF_DSMESH =
2351 {
2352         "Mesh Expander",                /* type name */
2353         ACHANNEL_ROLE_EXPANDER,         /* role */
2354         
2355         acf_generic_dataexpand_color,   /* backdrop color */
2356         acf_generic_dataexpand_backdrop, /* backdrop */
2357         acf_generic_indention_1,        /* indent level */      // XXX this only works for compositing
2358         acf_generic_basic_offset,       /* offset */
2359
2360         acf_generic_idblock_name,       /* name */
2361         acf_generic_idblock_name_prop,   /* name prop */
2362         acf_dsmesh_icon,                /* icon */
2363
2364         acf_generic_dataexpand_setting_valid,   /* has setting */
2365         acf_dsmesh_setting_flag,                /* flag for setting */
2366         acf_dsmesh_setting_ptr                  /* pointer for setting */
2367 };
2368
2369 /* Lattice Expander  ------------------------------------------- */
2370
2371 // TODO: just get this from RNA?
2372 static int acf_dslat_icon(bAnimListElem *UNUSED(ale))
2373 {
2374         return ICON_LATTICE_DATA;
2375 }
2376
2377 /* get the appropriate flag(s) for the setting when it is valid  */
2378 static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2379 {
2380         /* clear extra return data first */
2381         *neg = false;
2382         
2383         switch (setting) {
2384                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2385                         return LT_DS_EXPAND;
2386                         
2387                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2388                         return ADT_NLA_EVAL_OFF;
2389                         
2390                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2391                         *neg = true;
2392                         return ADT_CURVES_NOT_VISIBLE;
2393                         
2394                 case ACHANNEL_SETTING_SELECT: /* selected */
2395                         return ADT_UI_SELECTED;
2396                         
2397                 default: /* unsupported */
2398                         return 0;
2399         }
2400 }
2401
2402 /* get pointer to the setting */
2403 static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2404 {
2405         Lattice *lt = (Lattice *)ale->data;
2406         
2407         /* clear extra return data first */
2408         *type = 0;
2409         
2410         switch (setting) {
2411                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2412                         return GET_ACF_FLAG_PTR(lt->flag, type);
2413                         
2414                 case ACHANNEL_SETTING_SELECT: /* selected */
2415                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2416                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2417                         if (lt->adt)
2418                                 return GET_ACF_FLAG_PTR(lt->adt->flag, type);
2419                         return NULL;
2420                         
2421                 default: /* unsupported */
2422                         return NULL;
2423         }
2424 }
2425
2426 /* node tree expander type define */
2427 static bAnimChannelType ACF_DSLAT =
2428 {
2429         "Lattice Expander",             /* type name */
2430         ACHANNEL_ROLE_EXPANDER,         /* role */
2431         
2432         acf_generic_dataexpand_color,   /* backdrop color */
2433         acf_generic_dataexpand_backdrop, /* backdrop */
2434         acf_generic_indention_1,        /* indent level */      // XXX this only works for compositing
2435         acf_generic_basic_offset,       /* offset */
2436
2437         acf_generic_idblock_name,       /* name */
2438         acf_generic_idblock_name_prop,   /* name prop */
2439         acf_dslat_icon,                 /* icon */
2440
2441         acf_generic_dataexpand_setting_valid,   /* has setting */
2442         acf_dslat_setting_flag,                 /* flag for setting */
2443         acf_dslat_setting_ptr                   /* pointer for setting */
2444 };
2445
2446 /* Speaker Expander  ------------------------------------------- */
2447
2448 // TODO: just get this from RNA?
2449 static int acf_dsspk_icon(bAnimListElem *UNUSED(ale))
2450 {
2451         return ICON_SPEAKER;
2452 }
2453
2454 /* get the appropriate flag(s) for the setting when it is valid  */
2455 static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2456 {
2457         /* clear extra return data first */
2458         *neg = false;
2459         
2460         switch (setting) {
2461                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2462                         return SPK_DS_EXPAND;
2463                 
2464                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2465                         return ADT_NLA_EVAL_OFF;
2466                 
2467                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2468                         *neg = true;
2469                         return ADT_CURVES_NOT_VISIBLE;
2470                 
2471                 case ACHANNEL_SETTING_SELECT: /* selected */
2472                         return ADT_UI_SELECTED;
2473                 
2474                 default: /* unsupported */
2475                         return 0;
2476         }
2477 }
2478
2479 /* get pointer to the setting */
2480 static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2481 {
2482         Speaker *spk = (Speaker *)ale->data;
2483         
2484         /* clear extra return data first */
2485         *type = 0;
2486         
2487         switch (setting) {
2488                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2489                         return GET_ACF_FLAG_PTR(spk->flag, type);
2490                 
2491                 case ACHANNEL_SETTING_SELECT: /* selected */
2492                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2493                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2494                         if (spk->adt)
2495                                 return GET_ACF_FLAG_PTR(spk->adt->flag, type);
2496                         return NULL;
2497                 
2498                 default: /* unsupported */
2499                         return NULL;
2500         }
2501 }
2502
2503 /* speaker expander type define */
2504 static bAnimChannelType ACF_DSSPK =
2505 {
2506         "Speaker Expander",             /* type name */
2507         ACHANNEL_ROLE_EXPANDER,         /* role */
2508         
2509         acf_generic_dataexpand_color,   /* backdrop color */
2510         acf_generic_dataexpand_backdrop, /* backdrop */
2511         acf_generic_indention_1,        /* indent level */
2512         acf_generic_basic_offset,       /* offset */
2513
2514         acf_generic_idblock_name,       /* name */
2515         acf_generic_idblock_name_prop,   /* name prop */
2516         acf_dsspk_icon,                 /* icon */
2517
2518         acf_generic_dataexpand_setting_valid,   /* has setting */
2519         acf_dsspk_setting_flag,                 /* flag for setting */
2520         acf_dsspk_setting_ptr                   /* pointer for setting */
2521 };
2522
2523 /* GPencil Expander  ------------------------------------------- */
2524
2525 // TODO: just get this from RNA?
2526 static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
2527 {
2528         return ICON_GREASEPENCIL;
2529 }
2530
2531 /* get the appropriate flag(s) for the setting when it is valid  */
2532 static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2533 {
2534         /* clear extra return data first */
2535         *neg = false;
2536         
2537         switch (setting) {
2538                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2539                         return GP_DATA_EXPAND;
2540                 
2541                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2542                         return ADT_NLA_EVAL_OFF;
2543                 
2544                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2545                         *neg = true;
2546                         return ADT_CURVES_NOT_VISIBLE;
2547                 
2548                 case ACHANNEL_SETTING_SELECT: /* selected */
2549                         return ADT_UI_SELECTED;
2550                 
2551                 default: /* unsupported */
2552                         return 0;
2553         }
2554 }
2555
2556 /* get pointer to the setting */
2557 static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2558 {
2559         bGPdata *gpd = (bGPdata *)ale->data;
2560         
2561         /* clear extra return data first */
2562         *type = 0;
2563         
2564         switch (setting) {
2565                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2566                         return GET_ACF_FLAG_PTR(gpd->flag, type);
2567                 
2568                 case ACHANNEL_SETTING_SELECT: /* selected */
2569                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
2570                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2571                         if (gpd->adt)
2572                                 return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
2573                         return NULL;
2574                 
2575                 default: /* unsupported */
2576                         return NULL;
2577         }
2578 }
2579
2580 /* grease pencil expander type define */
2581 static bAnimChannelType ACF_DSGPENCIL =
2582 {
2583         "GPencil DS Expander",          /* type name */
2584         ACHANNEL_ROLE_EXPANDER,         /* role */
2585         
2586         acf_generic_dataexpand_color,   /* backdrop color */
2587         acf_generic_dataexpand_backdrop, /* backdrop */
2588         acf_generic_indention_1,        /* indent level */
2589         acf_generic_basic_offset,       /* offset */
2590
2591         acf_generic_idblock_name,       /* name */
2592         acf_generic_idblock_name_prop,  /* name prop */
2593         acf_dsgpencil_icon,             /* icon */
2594
2595         acf_generic_dataexpand_setting_valid,   /* has setting */
2596         acf_dsgpencil_setting_flag,             /* flag for setting */
2597         acf_dsgpencil_setting_ptr               /* pointer for setting */
2598 };
2599
2600 /* ShapeKey Entry  ------------------------------------------- */
2601
2602 /* name for ShapeKey */
2603 static void acf_shapekey_name(bAnimListElem *ale, char *name)
2604 {
2605         KeyBlock *kb = (KeyBlock *)ale->data;
2606         
2607         /* just copy the name... */
2608         if (kb && name) {
2609                 /* if the KeyBlock had a name, use it, otherwise use the index */
2610                 if (kb->name[0])
2611                         BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE);
2612                 else
2613                         BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index);
2614         }
2615 }
2616
2617 /* name property for ShapeKey entries */
2618 static bool acf_shapekey_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
2619 {
2620         KeyBlock *kb = (KeyBlock *)ale->data;
2621         
2622         /* if the KeyBlock had a name, use it, otherwise use the index */
2623         if (kb && kb->name[0]) {
2624                 RNA_pointer_create(ale->id, &RNA_ShapeKey, kb, ptr);
2625                 *prop = RNA_struct_name_property(ptr->type);
2626                 
2627                 return (*prop != NULL);
2628         }
2629         
2630         return false;
2631 }
2632
2633 /* check if some setting exists for this channel */
2634 static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2635 {
2636         switch (setting) {
2637                 case ACHANNEL_SETTING_SELECT: /* selected */
2638                 case ACHANNEL_SETTING_MUTE: /* muted */
2639                 case ACHANNEL_SETTING_PROTECT: /* protected */
2640                         return true;
2641                         
2642                 /* nothing else is supported */
2643                 default:
2644                         return false;
2645         }
2646 }
2647
2648 /* get the appropriate flag(s) for the setting when it is valid  */
2649 static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2650 {
2651         /* clear extra return data first */
2652         *neg = false;
2653         
2654         switch (setting) {
2655                 case ACHANNEL_SETTING_MUTE: /* mute */
2656                         return KEYBLOCK_MUTE;
2657                 
2658                 case ACHANNEL_SETTING_SELECT: /* selected */
2659                         return KEYBLOCK_SEL;
2660                 
2661                 case ACHANNEL_SETTING_PROTECT: /* locked */
2662                         return KEYBLOCK_LOCKED;
2663                 
2664                 default: /* unsupported */
2665                         return 0;
2666         }
2667 }
2668
2669 /* get pointer to the setting */
2670 static void *acf_shapekey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2671 {
2672         KeyBlock *kb = (KeyBlock *)ale->data;
2673         
2674         /* clear extra return data first */
2675         *type = 0;
2676         
2677         switch (setting) {
2678                 case ACHANNEL_SETTING_SELECT: /* selected */
2679                 case ACHANNEL_SETTING_MUTE: /* muted */
2680                 case ACHANNEL_SETTING_PROTECT: /* protected */
2681                         return GET_ACF_FLAG_PTR(kb->flag, type);
2682                 
2683                 default: /* unsupported */
2684                         return NULL;
2685         }
2686 }
2687
2688 /* shapekey expander type define */
2689 static bAnimChannelType ACF_SHAPEKEY =
2690 {
2691         "Shape Key",                    /* type name */
2692         ACHANNEL_ROLE_CHANNEL,          /* role */
2693         
2694         acf_generic_channel_color,      /* backdrop color */
2695         acf_generic_channel_backdrop,   /* backdrop */
2696         acf_generic_indention_0,        /* indent level */
2697         acf_generic_basic_offset,       /* offset */
2698
2699         acf_shapekey_name,              /* name */
2700         acf_shapekey_name_prop,          /* name prop */
2701         NULL,                           /* icon */
2702
2703         acf_shapekey_setting_valid,     /* has setting */
2704         acf_shapekey_setting_flag,      /* flag for setting */
2705         acf_shapekey_setting_ptr        /* pointer for setting */
2706 };
2707
2708 /* GPencil Datablock ------------------------------------------- */
2709
2710 /* get backdrop color for gpencil datablock widget */
2711 static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
2712 {
2713         /* these are ID-blocks, but not exactly standalone... */
2714         UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
2715 }
2716
2717 // TODO: just get this from RNA?
2718 static int acf_gpd_icon(bAnimListElem *UNUSED(ale))
2719 {
2720         return ICON_GREASEPENCIL;
2721 }
2722
2723 /* check if some setting exists for this channel */
2724 static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2725 {
2726         switch (setting) {
2727                 /* only select and expand supported */
2728                 case ACHANNEL_SETTING_SELECT:
2729                 case ACHANNEL_SETTING_EXPAND:
2730                         return true;
2731                         
2732                 default:
2733                         return false;
2734         }
2735 }
2736
2737 /* get the appropriate flag(s) for the setting when it is valid  */
2738 static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2739 {
2740         /* clear extra return data first */
2741         *neg = false;
2742         
2743         switch (setting) {
2744                 case ACHANNEL_SETTING_SELECT: /* selected */
2745                         return AGRP_SELECTED;
2746                         
2747                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2748                         return GP_DATA_EXPAND;
2749                 
2750                 default:
2751                         /* these shouldn't happen */
2752                         return 0;
2753         }
2754 }
2755
2756 /* get pointer to the setting */
2757 static void *acf_gpd_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
2758 {
2759         bGPdata *gpd = (bGPdata *)ale->data;
2760         
2761         /* all flags are just in gpd->flag for now... */
2762         return GET_ACF_FLAG_PTR(gpd->flag, type);
2763 }
2764
2765 /* gpencil datablock type define */
2766 static bAnimChannelType ACF_GPD = 
2767 {
2768         "GPencil Datablock",            /* type name */
2769         ACHANNEL_ROLE_EXPANDER,         /* role */
2770         
2771         acf_gpd_color,                  /* backdrop color */
2772         acf_group_backdrop,             /* backdrop */
2773         acf_generic_indention_0,        /* indent level */
2774         acf_generic_group_offset,       /* offset */
2775
2776         acf_generic_idblock_name,       /* name */
2777         acf_generic_idfill_name_prop,    /* name prop */
2778         acf_gpd_icon,                   /* icon */
2779
2780         acf_gpd_setting_valid,          /* has setting */
2781         acf_gpd_setting_flag,           /* flag for setting */
2782         acf_gpd_setting_ptr             /* pointer for setting */
2783 };
2784
2785 /* GPencil Layer ------------------------------------------- */
2786
2787 /* name for grease pencil layer entries */
2788 static void acf_gpl_name(bAnimListElem *ale, char *name)
2789 {
2790         bGPDlayer *gpl = (bGPDlayer *)ale->data;
2791         
2792         if (gpl && name)
2793                 BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
2794 }
2795
2796 /* name property for grease pencil layer entries */
2797 static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
2798 {
2799         if (ale->data) {
2800                 RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
2801                 *prop = RNA_struct_name_property(ptr->type);
2802                 
2803                 return (*prop != NULL);
2804         }
2805         
2806         return false;
2807 }
2808
2809 /* check if some setting exists for this channel */
2810 static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2811 {
2812         switch (setting) {
2813                 /* unsupported */
2814                 case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
2815                 case ACHANNEL_SETTING_SOLO: /* nla editor only */
2816                         return false;
2817                 
2818                 /* always available */
2819                 default:
2820                         return true;
2821         }
2822 }
2823
2824 /* get the appropriate flag(s) for the setting when it is valid  */
2825 static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2826 {
2827         /* clear extra return data first */
2828         *neg = false;
2829         
2830         switch (setting) {
2831                 case ACHANNEL_SETTING_SELECT: /* selected */
2832                         return GP_LAYER_SELECT;
2833                         
2834                 case ACHANNEL_SETTING_MUTE: /* animation muting - similar to frame lock... */
2835                         return GP_LAYER_FRAMELOCK;
2836                         
2837                 case ACHANNEL_SETTING_VISIBLE: /* visiblity of the layers (NOT muting) */
2838                         *neg = true;
2839                         return GP_LAYER_HIDE;
2840                         
2841                 case ACHANNEL_SETTING_PROTECT: /* protected */
2842                         return GP_LAYER_LOCKED;
2843                         
2844                 default: /* unsupported */
2845                         return 0;
2846         }
2847 }
2848
2849 /* get pointer to the setting */
2850 static void *acf_gpl_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
2851 {
2852         bGPDlayer *gpl = (bGPDlayer *)ale->data;
2853         
2854         /* all flags are just in gpl->flag for now... */
2855         return GET_ACF_FLAG_PTR(gpl->flag, type);
2856 }
2857
2858 /* grease pencil layer type define */
2859 static bAnimChannelType ACF_GPL = 
2860 {
2861         "GPencil Layer",                /* type name */
2862         ACHANNEL_ROLE_CHANNEL,          /* role */
2863         
2864         acf_generic_channel_color,      /* backdrop color */
2865         acf_generic_channel_backdrop,   /* backdrop */
2866         acf_generic_indention_flexible, /* indent level */
2867         acf_generic_group_offset,       /* offset */
2868         
2869         acf_gpl_name,                   /* name */
2870         acf_gpl_name_prop,              /* name prop */
2871         NULL,                           /* icon */
2872         
2873         acf_gpl_setting_valid,          /* has setting */
2874         acf_gpl_setting_flag,           /* flag for setting */
2875         acf_gpl_setting_ptr             /* pointer for setting */
2876 };
2877
2878
2879 /* Mask Datablock ------------------------------------------- */
2880
2881 /* get backdrop color for mask datablock widget */
2882 static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
2883 {
2884         /* these are ID-blocks, but not exactly standalone... */
2885         UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
2886 }
2887
2888 // TODO: just get this from RNA?
2889 static int acf_mask_icon(bAnimListElem *UNUSED(ale))
2890 {
2891         return ICON_MOD_MASK;
2892 }
2893
2894 /* check if some setting exists for this channel */
2895 static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2896 {
2897         switch (setting) {
2898                 /* only select and expand supported */
2899                 case ACHANNEL_SETTING_SELECT:
2900                 case ACHANNEL_SETTING_EXPAND:
2901                         return true;
2902                 
2903                 default:
2904                         return false;
2905         }
2906 }
2907
2908 /* get the appropriate flag(s) for the setting when it is valid  */
2909 static int acf_mask_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2910 {
2911         /* clear extra return data first */
2912         *neg = false;
2913         
2914         switch (setting) {
2915                 case ACHANNEL_SETTING_SELECT: /* selected */
2916                         return AGRP_SELECTED;
2917                 
2918                 case ACHANNEL_SETTING_EXPAND: /* expanded */
2919                         return MASK_ANIMF_EXPAND;
2920                         
2921                 default:        
2922                         /* this shouldn't happen */
2923                         return 0;
2924         }
2925 }
2926
2927 /* get pointer to the setting */
2928 static void *acf_mask_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
2929 {
2930         Mask *mask = (Mask *)ale->data;
2931         
2932         /* all flags are just in mask->flag for now... */
2933         return GET_ACF_FLAG_PTR(mask->flag, type);
2934 }
2935
2936 /* mask datablock type define */
2937 static bAnimChannelType ACF_MASKDATA =
2938 {
2939         "Mask Datablock",                /* type name */
2940         ACHANNEL_ROLE_EXPANDER,          /* role */
2941         
2942         acf_mask_color,                  /* backdrop color */
2943         acf_group_backdrop,              /* backdrop */
2944         acf_generic_indention_0,         /* indent level */
2945         acf_generic_group_offset,        /* offset */
2946         
2947         acf_generic_idblock_name,        /* name */
2948         acf_generic_idfill_name_prop,     /* name prop */
2949         acf_mask_icon,                   /* icon */
2950         
2951         acf_mask_setting_valid,          /* has setting */
2952         acf_mask_setting_flag,           /* flag for setting */
2953         acf_mask_setting_ptr             /* pointer for setting */
2954 };
2955
2956 /* Mask Layer ------------------------------------------- */
2957
2958 /* name for grease pencil layer entries */
2959 static void acf_masklay_name(bAnimListElem *ale, char *name)
2960 {
2961         MaskLayer *masklay = (MaskLayer *)ale->data;
2962         
2963         if (masklay && name)
2964                 BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
2965 }
2966
2967 /* name property for grease pencil layer entries */
2968 static bool acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
2969 {
2970         if (ale->data) {
2971                 RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
2972                 *prop = RNA_struct_name_property(ptr->type);
2973                 
2974                 return (*prop != NULL);
2975         }
2976
2977         return false;
2978 }
2979
2980 /* check if some setting exists for this channel */
2981 static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
2982 {
2983         switch (setting) {
2984                 /* unsupported */
2985                 case ACHANNEL_SETTING_EXPAND: /* mask layers are more like F-Curves than groups */
2986                 case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
2987                 case ACHANNEL_SETTING_SOLO: /* nla editor only */
2988                         return false;
2989                 
2990                 /* always available */
2991                 default:
2992                         return true;
2993         }
2994 }
2995
2996 /* get the appropriate flag(s) for the setting when it is valid  */
2997 static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
2998 {
2999         /* clear extra return data first */
3000         *neg = false;
3001         
3002         switch (setting) {
3003                 case ACHANNEL_SETTING_SELECT: /* selected */
3004                         return MASK_LAYERFLAG_SELECT;
3005                 
3006                 case ACHANNEL_SETTING_PROTECT: /* protected */
3007                         return MASK_LAYERFLAG_LOCKED;
3008                 
3009                 default: /* unsupported */
3010                         return 0;
3011         }
3012 }
3013
3014 /* get pointer to the setting */
3015 static void *acf_masklay_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings UNUSED(setting), short *type)
3016 {
3017         MaskLayer *masklay = (MaskLayer *)ale->data;
3018         
3019         /* all flags are just in masklay->flag for now... */
3020         return GET_ACF_FLAG_PTR(masklay->flag, type);
3021 }
3022
3023 /* grease pencil layer type define */
3024 static bAnimChannelType ACF_MASKLAYER =
3025 {
3026         "Mask Layer",                   /* type name */
3027         ACHANNEL_ROLE_CHANNEL,          /* role */
3028         
3029         acf_generic_channel_color,      /* backdrop color */
3030         acf_generic_channel_backdrop,   /* backdrop */
3031         acf_generic_indention_flexible, /* indent level */
3032         acf_generic_group_offset,       /* offset */
3033         
3034         acf_masklay_name,               /* name */
3035         acf_masklay_name_prop,          /* name prop */
3036         NULL,                           /* icon */
3037         
3038         acf_masklay_setting_valid,      /* has setting */
3039         acf_masklay_setting_flag,       /* flag for setting */
3040         acf_masklay_setting_ptr         /* pointer for setting */
3041 };
3042
3043 /* NLA Track ----------------------------------------------- */
3044
3045 /* get backdrop color for nla track channels */
3046 static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
3047 {
3048         NlaTrack *nlt = (NlaTrack *)ale->data;
3049         AnimData *adt = ale->adt;
3050         bool nonSolo = false;
3051         
3052         /* is track enabled for solo drawing? */
3053         if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
3054                 if ((nlt->flag & NLATRACK_SOLO) == 0) {
3055                         /* tag for special non-solo handling */
3056                         nonSolo = true;
3057                 }
3058         }
3059         
3060         /* set color for nla track */
3061         UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
3062 }
3063
3064 /* name for nla track entries */
3065 static void acf_nlatrack_name(bAnimListElem *ale, char *name)
3066 {
3067         NlaTrack *nlt = (NlaTrack *)ale->data;
3068         
3069         if (nlt && name)
3070                 BLI_strncpy(name, nlt->name, ANIM_CHAN_NAME_SIZE);
3071 }
3072
3073 /* name property for nla track entries */
3074 static bool acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3075 {
3076         if (ale->data) {
3077                 RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
3078                 *prop = RNA_struct_name_property(ptr->type);
3079                 
3080                 return (*prop != NULL);
3081         }
3082         
3083         return false;
3084 }
3085
3086 /* check if some setting exists for this channel */
3087 static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *ale, eAnimChannel_Settings setting)
3088 {
3089         NlaTrack *nlt = (NlaTrack *)ale->data;
3090         AnimData *adt = ale->adt;
3091         
3092         /* visibility of settings depends on various states... */
3093         switch (setting) {
3094                 /* always supported */
3095                 case ACHANNEL_SETTING_SELECT:
3096                 case ACHANNEL_SETTING_SOLO:
3097                         return true;
3098                 
3099                 /* conditionally supported... */
3100                 case ACHANNEL_SETTING_PROTECT:
3101                 case ACHANNEL_SETTING_MUTE:
3102                         /* if this track is active and we're tweaking it, don't draw these toggles */
3103                         if (((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0) {
3104                                 /* is track enabled for solo drawing? */
3105                                 if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
3106                                         if (nlt->flag & NLATRACK_SOLO) {
3107                                                 /* ok - we've got a solo track, and this is it */
3108                                                 return true;
3109                                         }
3110                                         else {
3111                                                 /* not ok - we've got a solo track, but this isn't it, so make it more obvious */
3112                                                 return false;
3113                                         }
3114                                 }
3115                                 
3116                                 
3117                                 /* ok - no tracks are solo'd, and this isn't being tweaked */
3118                                 return true;
3119                         }
3120                         else {
3121                                 /* unsupported - this track is being tweaked */
3122                                 return false;
3123                         }
3124                 
3125                 /* unsupported */
3126                 default:
3127                         return false;
3128         }
3129 }
3130
3131 /* get the appropriate flag(s) for the setting when it is valid  */
3132 static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
3133 {
3134         /* clear extra return data first */
3135         *neg = false;
3136         
3137         switch (setting) {
3138                 case ACHANNEL_SETTING_SELECT: /* selected */
3139                &nb