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