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