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