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