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