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