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