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