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