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