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