32bda94f79696f6eda0ed137365d74511439a02d
[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_arithb.h"
41
42 #include "DNA_listBase.h"
43 #include "DNA_anim_types.h"
44 #include "DNA_action_types.h"
45 #include "DNA_armature_types.h"
46 #include "DNA_camera_types.h"
47 #include "DNA_curve_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_particle_types.h"
50 #include "DNA_screen_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_space_types.h"
53 #include "DNA_constraint_types.h"
54 #include "DNA_key_types.h"
55 #include "DNA_lamp_types.h"
56 #include "DNA_material_types.h"
57 #include "DNA_meta_types.h"
58 #include "DNA_userdef_types.h"
59 #include "DNA_gpencil_types.h"
60 #include "DNA_windowmanager_types.h"
61 #include "DNA_world_types.h"
62
63 #include "RNA_access.h"
64 #include "RNA_define.h"
65
66 #include "BKE_animsys.h"
67 #include "BKE_action.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_fcurve.h"
70 #include "BKE_key.h"
71 #include "BKE_material.h"
72 #include "BKE_object.h"
73 #include "BKE_context.h"
74 #include "BKE_utildefines.h"
75
76 #include "UI_interface.h"
77 #include "UI_interface_icons.h"
78 #include "UI_resources.h"
79 #include "UI_view2d.h"
80
81 #include "ED_anim_api.h"
82 #include "ED_keyframes_edit.h" // XXX move the select modes out of there!
83 #include "ED_screen.h"
84 #include "ED_space_api.h"
85
86 #include "BIF_gl.h"
87
88 #include "WM_api.h"
89 #include "WM_types.h"
90
91 /* *********************************************** */
92 // XXX constant defines to be moved elsewhere?
93
94 /* extra padding for lengths (to go under scrollers) */
95 #define EXTRA_SCROLL_PAD        100.0f
96
97 /* size of indent steps */
98 #define INDENT_STEP_SIZE        7
99
100 /* macros used for type defines */
101         /* get the pointer used for some flag */
102 #define GET_ACF_FLAG_PTR(ptr) \
103         { \
104                 *type= sizeof((ptr)); \
105                 return &(ptr); \
106         } 
107
108
109 /* XXX */
110 extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
111 extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
112
113
114 /* *********************************************** */
115 /* Generic Functions (Type independent) */
116
117 /* Draw Backdrop ---------------------------------- */
118
119 /* backdrop for top-level widgets (Scene and Object only) */
120 static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
121 {
122         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
123         View2D *v2d= &ac->ar->v2d;
124         short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
125         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
126         
127         /* darker blue for top-level widgets */
128         UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
129         
130         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
131         uiSetRoundBox((expanded)? (1):(1|8));
132         gl_round_box(GL_POLYGON, offset,  yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8);
133 }
134
135 /* backdrop for data expanders under top-level Scene/Object */
136 static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
137 {
138         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
139         View2D *v2d= &ac->ar->v2d;
140         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
141         
142         /* lighter color than top-level widget */
143         UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
144         
145         /* no rounded corner - just rectangular box */
146         glRectf(offset, yminc,  v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc);
147 }
148
149 /* backdrop for generic channels */
150 static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
151 {
152         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
153         View2D *v2d= &ac->ar->v2d;
154         SpaceAction *saction = NULL;
155         bActionGroup *grp = NULL;
156         short indent= (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
157         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
158         
159         /* get context info needed... */
160         if ((ac->sa) && (ac->sa->spacetype == SPACE_ACTION))
161                 saction= (SpaceAction *)ac->sa->spacedata.first;
162                 
163         if (ale->type == ANIMTYPE_FCURVE) {
164                 FCurve *fcu= (FCurve *)ale->data;
165                 grp= fcu->grp;
166         }
167         
168         /* set color for normal channels 
169          *      - use 3 shades of color group/standard color for 3 indention level
170          *      - only use group colors if allowed to, and if actually feasible
171          */
172         if ( (saction && !(saction->flag & SACTION_NODRAWGCOLORS)) && 
173                  ((grp) && (grp->customCol)) ) 
174         {
175                 char cp[3];
176                 
177                 if (indent == 2) {
178                         VECCOPY(cp, grp->cs.solid);
179                 }
180                 else if (indent == 1) {
181                         VECCOPY(cp, grp->cs.select);
182                 }
183                 else {
184                         VECCOPY(cp, grp->cs.active);
185                 }
186                 
187                 glColor3ub(cp[0], cp[1], cp[2]);
188         }
189         else // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)?
190                 UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
191         
192         /* no rounded corners - just rectangular box */
193         glRectf(offset, yminc,  v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc);
194 }
195
196 /* Indention + Offset ------------------------------------------- */
197
198 /* indention level is always the value in the name */
199 static short acf_generic_indention_0(bAnimContext *ac, bAnimListElem *ale)
200 {
201         return 0;
202 }
203 static short acf_generic_indention_1(bAnimContext *ac, bAnimListElem *ale)
204 {
205         return 1;
206 }
207 #if 0 // XXX not used
208 static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
209 {
210         return 2;
211 }
212 #endif
213
214 /* indention which varies with the grouping status */
215 static short acf_generic_indention_flexible(bAnimContext *ac, bAnimListElem *ale)
216 {
217         short indent= 0;
218         
219         if (ale->id) {
220                 /* special exception for materials and particles */
221                 if (ELEM(GS(ale->id->name),ID_MA,ID_PA))
222                         indent++;
223         }
224         
225         /* grouped F-Curves need extra level of indention */
226         if (ale->type == ANIMTYPE_FCURVE) {
227                 FCurve *fcu= (FCurve *)ale->data;
228                 
229                 // TODO: we need some way of specifying that the indention color should be one less...
230                 if (fcu->grp)
231                         indent++;
232         }
233         
234         /* no indention */
235         return indent;
236 }
237
238 /* basic offset for channels derived from indention */
239 static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
240 {
241         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
242         
243         if (acf && acf->get_indent_level)
244                 return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
245         else
246                 return 0;
247 }
248
249 /* offset for groups + grouped entities */
250 static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
251 {
252         short offset= acf_generic_basic_offset(ac, ale);
253         
254         if (ale->id) {
255                 /* special exception for materials and particles */
256                 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) 
257                         offset += 21;
258                         
259                 /* if not in Action Editor mode, groupings must carry some offset too... */
260                 else if (ac->datatype != ANIMCONT_ACTION)
261                         offset += 14;
262         }
263         
264         /* offset is just the normal type - i.e. based on indention */
265         return offset;
266 }
267
268 /* Name ------------------------------------------- */
269
270 /* name for ID block entries */
271 static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
272 {
273         ID *id= (ID *)ale->data;        /* data pointed to should be an ID block */
274         
275         /* just copy the name... */
276         if (id && name)
277                 sprintf(name, id->name+2);
278 }
279
280 /* Settings ------------------------------------------- */
281
282 /* check if some setting exists for this object-based data-expander (category only) */
283 static short acf_generic_dsexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
284 {
285         switch (setting) {
286                 /* only expand supported */
287                 case ACHANNEL_SETTING_EXPAND:
288                         return 1;
289                         
290                 default:
291                         return 0;
292         }
293 }
294
295 /* get pointer to the setting (category only) */
296 static void *acf_generic_dsexpand_setting_ptr(bAnimListElem *ale, int setting, short *type)
297 {
298         Object *ob= (Object *)ale->data;
299         
300         /* clear extra return data first */
301         *type= 0;
302         
303         switch (setting) {
304                 case ACHANNEL_SETTING_EXPAND: /* expanded */
305                         GET_ACF_FLAG_PTR(ob->nlaflag); // XXX
306                 
307                 default: /* unsupported */
308                         return NULL;
309         }
310 }
311
312 /* check if some setting exists for this object-based data-expander (datablock only) */
313 static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
314 {
315         switch (setting) {
316                 /* expand is always supported */
317                 case ACHANNEL_SETTING_EXPAND:
318                         return 1;
319                         
320                 /* mute is only supported for NLA */
321                 case ACHANNEL_SETTING_MUTE:
322                         return ((ac) && (ac->spacetype == SPACE_NLA));
323                         
324                 /* other flags are never supported */
325                 default:
326                         return 0;
327         }
328 }
329
330 /* *********************************************** */
331 /* Type Specific Functions + Defines */
332
333 /* Scene ------------------------------------------- */
334
335 // TODO: just get this from RNA?
336 static int acf_scene_icon(bAnimListElem *ale)
337 {
338         return ICON_SCENE_DATA;
339 }
340
341 /* check if some setting exists for this channel */
342 static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
343 {
344         switch (setting) {
345                 /* muted only in NLA */
346                 case ACHANNEL_SETTING_MUTE: 
347                         return ((ac) && (ac->spacetype == SPACE_NLA));
348                 
349                 /* only select and expand supported otherwise */
350                 case ACHANNEL_SETTING_SELECT:
351                 case ACHANNEL_SETTING_EXPAND:
352                         return 1;
353                         
354                 default:
355                         return 0;
356         }
357 }
358
359 /* get the appropriate flag(s) for the setting when it is valid  */
360 static int acf_scene_setting_flag(int setting, short *neg)
361 {
362         /* clear extra return data first */
363         *neg= 0;
364         
365         switch (setting) {
366                 case ACHANNEL_SETTING_SELECT: /* selected */
367                         return SCE_DS_SELECTED;
368                         
369                 case ACHANNEL_SETTING_EXPAND: /* expanded */
370                         *neg= 1;
371                         return SCE_DS_COLLAPSED;
372                         
373                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
374                         return ADT_NLA_EVAL_OFF;
375                         
376                 default: /* unsupported */
377                         return 0;
378         }
379 }
380
381 /* get pointer to the setting */
382 static void *acf_scene_setting_ptr(bAnimListElem *ale, int setting, short *type)
383 {
384         Scene *scene= (Scene *)ale->data;
385         
386         /* clear extra return data first */
387         *type= 0;
388         
389         switch (setting) {
390                 case ACHANNEL_SETTING_SELECT: /* selected */
391                         GET_ACF_FLAG_PTR(scene->flag);
392                         
393                 case ACHANNEL_SETTING_EXPAND: /* expanded */
394                         GET_ACF_FLAG_PTR(scene->flag);
395                         
396                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
397                         if (scene->adt)
398                                 GET_ACF_FLAG_PTR(scene->adt->flag)
399                         else
400                                 return NULL;
401                         
402                 default: /* unsupported */
403                         return 0;
404         }
405 }
406
407 /* scene type define */
408 static bAnimChannelType ACF_SCENE = 
409 {
410         acf_generic_root_backdrop,              /* backdrop */
411         acf_generic_indention_0,                /* indent level */
412         NULL,                                                   /* offset */
413         
414         acf_generic_idblock_name,               /* name */
415         acf_scene_icon,                                 /* icon */
416         
417         acf_scene_setting_valid,                /* has setting */
418         acf_scene_setting_flag,                 /* flag for setting */
419         acf_scene_setting_ptr                   /* pointer for setting */
420 };
421
422 /* Object ------------------------------------------- */
423
424 static int acf_object_icon(bAnimListElem *ale)
425 {
426         Base *base= (Base *)ale->data;
427         Object *ob= base->object;
428         
429         /* icon depends on object-type */
430         if (ob->type == OB_ARMATURE)
431                 return ICON_ARMATURE_DATA;
432         else    
433                 return ICON_OBJECT_DATA;
434 }
435
436 /* name for object */
437 static void acf_object_name(bAnimListElem *ale, char *name)
438 {
439         Base *base= (Base *)ale->data;
440         Object *ob= base->object;
441         
442         /* just copy the name... */
443         if (ob && name)
444                 sprintf(name, ob->id.name+2);
445 }
446
447 /* check if some setting exists for this channel */
448 static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
449 {
450         switch (setting) {
451                 /* muted only in NLA */
452                 case ACHANNEL_SETTING_MUTE: 
453                         return ((ac) && (ac->spacetype == SPACE_NLA));
454                 
455                 /* only select and expand supported otherwise */
456                 case ACHANNEL_SETTING_SELECT:
457                 case ACHANNEL_SETTING_EXPAND:
458                         return 1;
459                         
460                 default:
461                         return 0;
462         }
463 }
464
465 /* get the appropriate flag(s) for the setting when it is valid  */
466 static int acf_object_setting_flag(int setting, short *neg)
467 {
468         /* clear extra return data first */
469         *neg= 0;
470         
471         switch (setting) {
472                 case ACHANNEL_SETTING_SELECT: /* selected */
473                         return SELECT;
474                         
475                 case ACHANNEL_SETTING_EXPAND: /* expanded */
476                         *neg= 1;
477                         return OB_ADS_COLLAPSED;
478                         
479                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
480                         return ADT_NLA_EVAL_OFF;
481                         
482                 default: /* unsupported */
483                         return 0;
484         }
485 }
486
487 /* get pointer to the setting */
488 static void *acf_object_setting_ptr(bAnimListElem *ale, int setting, short *type)
489 {
490         Base *base= (Base *)ale->data;
491         Object *ob= base->object;
492         
493         /* clear extra return data first */
494         *type= 0;
495         
496         switch (setting) {
497                 case ACHANNEL_SETTING_SELECT: /* selected */
498                         GET_ACF_FLAG_PTR(ob->flag);
499                         
500                 case ACHANNEL_SETTING_EXPAND: /* expanded */
501                         GET_ACF_FLAG_PTR(ob->nlaflag); // xxx
502                         
503                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
504                         if (ob->adt)
505                                 GET_ACF_FLAG_PTR(ob->adt->flag)
506                         else
507                                 return NULL;
508                         
509                 default: /* unsupported */
510                         return 0;
511         }
512 }
513
514 /* object type define */
515 static bAnimChannelType ACF_OBJECT = 
516 {
517         acf_generic_root_backdrop,              /* backdrop */
518         acf_generic_indention_0,                /* indent level */
519         NULL,                                                   /* offset */
520         
521         acf_object_name,                                /* name */
522         acf_object_icon,                                /* icon */
523         
524         acf_object_setting_valid,               /* has setting */
525         acf_object_setting_flag,                /* flag for setting */
526         acf_object_setting_ptr                  /* pointer for setting */
527 };
528
529 /* Group ------------------------------------------- */
530
531 /* backdrop for group widget */
532 static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
533 {
534         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
535         View2D *v2d= &ac->ar->v2d;
536         short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
537         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
538         
539         /* only for action group channels */
540         if (ale->flag & AGRP_ACTIVE)
541                 UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
542         else
543                 UI_ThemeColorShade(TH_GROUP, 20);
544         
545         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
546         uiSetRoundBox((expanded)? (1):(1|8));
547         gl_round_box(GL_POLYGON, offset,  yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8);
548 }
549
550 /* name for group entries */
551 static void acf_group_name(bAnimListElem *ale, char *name)
552 {
553         bActionGroup *agrp= (bActionGroup *)ale->data;
554         
555         /* just copy the name... */
556         if (agrp && name)
557                 sprintf(name, agrp->name);
558 }
559
560 /* check if some setting exists for this channel */
561 static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
562 {
563         /* for now, all settings are supported */
564         return 1;
565 }
566
567 /* get the appropriate flag(s) for the setting when it is valid  */
568 static int acf_group_setting_flag(int setting, short *neg)
569 {
570         /* clear extra return data first */
571         *neg= 0;
572         
573         switch (setting) {
574                 case ACHANNEL_SETTING_SELECT: /* selected */
575                         return AGRP_SELECTED;
576                         
577                 case ACHANNEL_SETTING_EXPAND: /* expanded */
578                         return AGRP_EXPANDED;
579                         
580                 case ACHANNEL_SETTING_MUTE: /* muted */
581                         return AGRP_MUTED;
582                         
583                 case ACHANNEL_SETTING_PROTECT: /* protected */
584                         //*neg= 1; - if we change this to edtiability
585                         return AGRP_PROTECTED;
586                         
587                 case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
588                         *neg= 1;
589                         return AGRP_NOTVISIBLE;
590         }
591         
592         /* this shouldn't happen */
593         return 0;
594 }
595
596 /* get pointer to the setting */
597 static void *acf_group_setting_ptr(bAnimListElem *ale, int setting, short *type)
598 {
599         bActionGroup *agrp= (bActionGroup *)ale->data;
600         
601         /* all flags are just in agrp->flag for now... */
602         GET_ACF_FLAG_PTR(agrp->flag);
603 }
604
605 /* group type define */
606 static bAnimChannelType ACF_GROUP = 
607 {
608         acf_group_backdrop,                             /* backdrop */
609         acf_generic_indention_0,                /* indent level */
610         acf_generic_group_offset,               /* offset */
611         
612         acf_group_name,                                 /* name */
613         NULL,                                                   /* icon */
614         
615         acf_group_setting_valid,                /* has setting */
616         acf_group_setting_flag,                 /* flag for setting */
617         acf_group_setting_ptr                   /* pointer for setting */
618 };
619
620 /* F-Curve ------------------------------------------- */
621
622 /* name for fcurve entries */
623 static void acf_fcurve_name(bAnimListElem *ale, char *name)
624 {
625         getname_anim_fcurve(name, ale->id, ale->data);
626 }
627
628 /* check if some setting exists for this channel */
629 static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
630 {
631         FCurve *fcu= (FCurve *)ale->data;
632         
633         switch (setting) {
634                 /* unsupported */
635                 case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
636                         return 0;
637                 
638                 /* conditionally available */
639                 case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
640                         if (fcu->bezt)
641                                 return 1;
642                         else
643                                 return 0; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
644                         
645                 /* always available */
646                 default:
647                         return 1;
648         }
649 }
650
651 /* get the appropriate flag(s) for the setting when it is valid  */
652 static int acf_fcurve_setting_flag(int setting, short *neg)
653 {
654         /* clear extra return data first */
655         *neg= 0;
656         
657         switch (setting) {
658                 case ACHANNEL_SETTING_SELECT: /* selected */
659                         return FCURVE_SELECTED;
660                         
661                 case ACHANNEL_SETTING_MUTE: /* muted */
662                         return FCURVE_MUTED;
663                         
664                 case ACHANNEL_SETTING_PROTECT: /* protected */
665                         //*neg= 1; - if we change this to edtiability
666                         return FCURVE_PROTECTED;
667                         
668                 case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
669                         return FCURVE_VISIBLE;
670                         
671                 default: /* unsupported */
672                         return 0;
673         }
674 }
675
676 /* get pointer to the setting */
677 static void *acf_fcurve_setting_ptr(bAnimListElem *ale, int setting, short *type)
678 {
679         FCurve *fcu= (FCurve *)ale->data;
680         
681         /* all flags are just in agrp->flag for now... */
682         GET_ACF_FLAG_PTR(fcu->flag);
683 }
684
685 /* fcurve type define */
686 static bAnimChannelType ACF_FCURVE = 
687 {
688         acf_generic_channel_backdrop,   /* backdrop */
689         acf_generic_indention_flexible, /* indent level */              // xxx rename this to f-curves only?
690         acf_generic_group_offset,               /* offset */
691         
692         acf_fcurve_name,                                /* name */
693         NULL,                                                   /* icon */
694         
695         acf_fcurve_setting_valid,               /* has setting */
696         acf_fcurve_setting_flag,                /* flag for setting */
697         acf_fcurve_setting_ptr                  /* pointer for setting */
698 };
699
700 /* Object Action Expander  ------------------------------------------- */
701
702 // TODO: just get this from RNA?
703 static int acf_fillactd_icon(bAnimListElem *ale)
704 {
705         return ICON_ACTION;
706 }
707
708 /* check if some setting exists for this channel */
709 static short acf_fillactd_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
710 {
711         switch (setting) {
712                 /* only select and expand supported */
713                 case ACHANNEL_SETTING_SELECT:
714                 case ACHANNEL_SETTING_EXPAND:
715                         return 1;
716                         
717                 default:
718                         return 0;
719         }
720 }
721
722 /* get the appropriate flag(s) for the setting when it is valid  */
723 static int acf_fillactd_setting_flag(int setting, short *neg)
724 {
725         /* clear extra return data first */
726         *neg= 0;
727         
728         switch (setting) {
729                 case ACHANNEL_SETTING_SELECT: /* selected */
730                         return ACT_SELECTED;
731                         
732                 case ACHANNEL_SETTING_EXPAND: /* expanded */
733                         *neg= 1;
734                         return ACT_COLLAPSED;
735                 
736                 default: /* unsupported */
737                         return 0;
738         }
739 }
740
741 /* get pointer to the setting */
742 static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *type)
743 {
744         bAction *act= (bAction *)ale->data;
745         
746         /* clear extra return data first */
747         *type= 0;
748         
749         switch (setting) {
750                 case ACHANNEL_SETTING_SELECT: /* selected */
751                         GET_ACF_FLAG_PTR(act->flag);
752                         
753                 case ACHANNEL_SETTING_EXPAND: /* expanded */
754                         GET_ACF_FLAG_PTR(act->flag);
755                 
756                 default: /* unsupported */
757                         return 0;
758         }
759 }
760
761 /* object action expander type define */
762 static bAnimChannelType ACF_FILLACTD = 
763 {
764         acf_generic_dataexpand_backdrop,/* backdrop */
765         acf_generic_indention_1,                /* indent level */
766         acf_generic_basic_offset,               /* offset */
767         
768         acf_generic_idblock_name,               /* name */
769         acf_fillactd_icon,                              /* icon */
770         
771         acf_fillactd_setting_valid,             /* has setting */
772         acf_fillactd_setting_flag,              /* flag for setting */
773         acf_fillactd_setting_ptr                /* pointer for setting */
774 };
775
776 /* Drivers Expander  ------------------------------------------- */
777
778 // TODO: just get this from RNA?
779 static int acf_filldrivers_icon(bAnimListElem *ale)
780 {
781         return ICON_ANIM_DATA;
782 }
783
784 static void acf_filldrivers_name(bAnimListElem *ale, char *name)
785 {
786         sprintf(name, "Drivers");
787 }
788
789 /* check if some setting exists for this channel */
790 // TODO: this could be made more generic
791 static short acf_filldrivers_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
792 {
793         switch (setting) {
794                 /* only expand supported */
795                 case ACHANNEL_SETTING_EXPAND:
796                         return 1;
797                         
798                 default:
799                         return 0;
800         }
801 }
802
803 /* get the appropriate flag(s) for the setting when it is valid  */
804 static int acf_filldrivers_setting_flag(int setting, short *neg)
805 {
806         /* clear extra return data first */
807         *neg= 0;
808         
809         switch (setting) {
810                 case ACHANNEL_SETTING_EXPAND: /* expanded */
811                         *neg= 1;
812                         return ADT_DRIVERS_COLLAPSED;
813                 
814                 default: /* unsupported */
815                         return 0;
816         }
817 }
818
819 /* get pointer to the setting */
820 static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, int setting, short *type)
821 {
822         AnimData *adt= (AnimData *)ale->data;
823         
824         /* clear extra return data first */
825         *type= 0;
826         
827         switch (setting) {
828                 case ACHANNEL_SETTING_EXPAND: /* expanded */
829                         GET_ACF_FLAG_PTR(adt->flag);
830                 
831                 default: /* unsupported */
832                         return 0;
833         }
834 }
835
836 /* drivers expander type define */
837 static bAnimChannelType ACF_FILLDRIVERS = 
838 {
839         acf_generic_dataexpand_backdrop,/* backdrop */
840         acf_generic_indention_1,                /* indent level */
841         acf_generic_basic_offset,               /* offset */
842         
843         acf_filldrivers_name,                   /* name */
844         acf_filldrivers_icon,                   /* icon */
845         
846         acf_filldrivers_setting_valid,  /* has setting */
847         acf_filldrivers_setting_flag,   /* flag for setting */
848         acf_filldrivers_setting_ptr             /* pointer for setting */
849 };
850
851 /* Materials Expander  ------------------------------------------- */
852
853 // TODO: just get this from RNA?
854 static int acf_fillmatd_icon(bAnimListElem *ale)
855 {
856         return ICON_MATERIAL_DATA;
857 }
858
859 static void acf_fillmatd_name(bAnimListElem *ale, char *name)
860 {
861         sprintf(name, "Materials");
862 }
863
864 /* get the appropriate flag(s) for the setting when it is valid  */
865 static int acf_fillmatd_setting_flag(int setting, short *neg)
866 {
867         /* clear extra return data first */
868         *neg= 0;
869         
870         switch (setting) {
871                 case ACHANNEL_SETTING_EXPAND: /* expanded */
872                         *neg= 1;
873                         return OB_ADS_SHOWMATS;
874                 
875                 default: /* unsupported */
876                         return 0;
877         }
878 }
879
880 /* materials expander type define */
881 static bAnimChannelType ACF_FILLMATD= 
882 {
883         acf_generic_dataexpand_backdrop,/* backdrop */
884         acf_generic_indention_1,                /* indent level */
885         acf_generic_basic_offset,               /* offset */
886         
887         acf_fillmatd_name,                              /* name */
888         acf_fillmatd_icon,                              /* icon */
889         
890         acf_generic_dsexpand_setting_valid,     /* has setting */
891         acf_fillmatd_setting_flag,                              /* flag for setting */
892         acf_generic_dsexpand_setting_ptr                /* pointer for setting */
893 };
894
895 /* Particles Expander  ------------------------------------------- */
896
897 // TODO: just get this from RNA?
898 static int acf_fillpartd_icon(bAnimListElem *ale)
899 {
900         return ICON_PARTICLE_DATA;
901 }
902
903 static void acf_fillpartd_name(bAnimListElem *ale, char *name)
904 {
905         sprintf(name, "Particles");
906 }
907
908 /* get the appropriate flag(s) for the setting when it is valid  */
909 static int acf_fillpartd_setting_flag(int setting, short *neg)
910 {
911         /* clear extra return data first */
912         *neg= 0;
913         
914         switch (setting) {
915                 case ACHANNEL_SETTING_EXPAND: /* expanded */
916                         *neg= 1;
917                         return OB_ADS_SHOWPARTS;
918                 
919                 default: /* unsupported */
920                         return 0;
921         }
922 }
923
924 /* particles expander type define */
925 static bAnimChannelType ACF_FILLPARTD= 
926 {
927         acf_generic_dataexpand_backdrop,/* backdrop */
928         acf_generic_indention_1,                /* indent level */
929         acf_generic_basic_offset,               /* offset */
930         
931         acf_fillpartd_name,                             /* name */
932         acf_fillpartd_icon,                             /* icon */
933         
934         acf_generic_dsexpand_setting_valid,     /* has setting */
935         acf_fillpartd_setting_flag,                             /* flag for setting */
936         acf_generic_dsexpand_setting_ptr                /* pointer for setting */
937 };
938
939 /* Material Expander  ------------------------------------------- */
940
941 // TODO: just get this from RNA?
942 static int acf_dsmat_icon(bAnimListElem *ale)
943 {
944         return ICON_MATERIAL_DATA;
945 }
946
947 /* offset for material expanders */
948 static short acf_dsmat_offset(bAnimContext *ac, bAnimListElem *ale)
949 {
950         return 21;
951 }
952
953 /* get the appropriate flag(s) for the setting when it is valid  */
954 static int acf_dsmat_setting_flag(int setting, short *neg)
955 {
956         /* clear extra return data first */
957         *neg= 0;
958         
959         switch (setting) {
960                 case ACHANNEL_SETTING_EXPAND: /* expanded */
961                         return MA_DS_EXPAND;
962                         
963                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
964                         return ADT_NLA_EVAL_OFF;
965                 
966                 default: /* unsupported */
967                         return 0;
968         }
969 }
970
971 /* get pointer to the setting */
972 static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type)
973 {
974         Material *ma= (Material *)ale->data;
975         
976         /* clear extra return data first */
977         *type= 0;
978         
979         switch (setting) {
980                 case ACHANNEL_SETTING_EXPAND: /* expanded */
981                         GET_ACF_FLAG_PTR(ma->flag);
982                         
983                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
984                         if (ma->adt)
985                                 GET_ACF_FLAG_PTR(ma->adt->flag)
986                         else
987                                 return NULL;
988                 
989                 default: /* unsupported */
990                         return NULL;
991         }
992 }
993
994 /* material expander type define */
995 static bAnimChannelType ACF_DSMAT= 
996 {
997         acf_generic_channel_backdrop,   /* backdrop */
998         acf_generic_indention_0,                /* indent level */
999         acf_dsmat_offset,                               /* offset */
1000         
1001         acf_generic_idblock_name,               /* name */
1002         acf_dsmat_icon,                                 /* icon */
1003         
1004         acf_generic_dataexpand_setting_valid,   /* has setting */
1005         acf_dsmat_setting_flag,                                 /* flag for setting */
1006         acf_dsmat_setting_ptr                                   /* pointer for setting */
1007 };
1008
1009 /* Lamp Expander  ------------------------------------------- */
1010
1011 // TODO: just get this from RNA?
1012 static int acf_dslam_icon(bAnimListElem *ale)
1013 {
1014         return ICON_LAMP_DATA;
1015 }
1016
1017 /* get the appropriate flag(s) for the setting when it is valid  */
1018 static int acf_dslam_setting_flag(int setting, short *neg)
1019 {
1020         /* clear extra return data first */
1021         *neg= 0;
1022         
1023         switch (setting) {
1024                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1025                         return LA_DS_EXPAND;
1026                         
1027                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1028                         return ADT_NLA_EVAL_OFF;
1029                 
1030                 default: /* unsupported */
1031                         return 0;
1032         }
1033 }
1034
1035 /* get pointer to the setting */
1036 static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type)
1037 {
1038         Lamp *la= (Lamp *)ale->data;
1039         
1040         /* clear extra return data first */
1041         *type= 0;
1042         
1043         switch (setting) {
1044                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1045                         GET_ACF_FLAG_PTR(la->flag);
1046                         
1047                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1048                         if (la->adt)
1049                                 GET_ACF_FLAG_PTR(la->adt->flag)
1050                         else
1051                                 return NULL;
1052                 
1053                 default: /* unsupported */
1054                         return NULL;
1055         }
1056 }
1057
1058 /* lamp expander type define */
1059 static bAnimChannelType ACF_DSLAM= 
1060 {
1061         acf_generic_dataexpand_backdrop,/* backdrop */
1062         acf_generic_indention_1,                /* indent level */
1063         acf_generic_basic_offset,               /* offset */
1064         
1065         acf_generic_idblock_name,               /* name */
1066         acf_dslam_icon,                                 /* icon */
1067         
1068         acf_generic_dataexpand_setting_valid,   /* has setting */
1069         acf_dslam_setting_flag,                                 /* flag for setting */
1070         acf_dslam_setting_ptr                                   /* pointer for setting */
1071 };
1072
1073 /* Camera Expander  ------------------------------------------- */
1074
1075 // TODO: just get this from RNA?
1076 static int acf_dscam_icon(bAnimListElem *ale)
1077 {
1078         return ICON_CAMERA_DATA;
1079 }
1080
1081 /* get the appropriate flag(s) for the setting when it is valid  */
1082 static int acf_dscam_setting_flag(int setting, short *neg)
1083 {
1084         /* clear extra return data first */
1085         *neg= 0;
1086         
1087         switch (setting) {
1088                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1089                         return CAM_DS_EXPAND;
1090                         
1091                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1092                         return ADT_NLA_EVAL_OFF;
1093                 
1094                 default: /* unsupported */
1095                         return 0;
1096         }
1097 }
1098
1099 /* get pointer to the setting */
1100 static void *acf_dscam_setting_ptr(bAnimListElem *ale, int setting, short *type)
1101 {
1102         Camera *ca= (Camera *)ale->data;
1103         
1104         /* clear extra return data first */
1105         *type= 0;
1106         
1107         switch (setting) {
1108                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1109                         GET_ACF_FLAG_PTR(ca->flag);
1110                         
1111                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1112                         if (ca->adt)
1113                                 GET_ACF_FLAG_PTR(ca->adt->flag)
1114                         else
1115                                 return NULL;
1116                 
1117                 default: /* unsupported */
1118                         return NULL;
1119         }
1120 }
1121
1122 /* camera expander type define */
1123 static bAnimChannelType ACF_DSCAM= 
1124 {
1125         acf_generic_dataexpand_backdrop,/* backdrop */
1126         acf_generic_indention_1,                /* indent level */
1127         acf_generic_basic_offset,               /* offset */
1128         
1129         acf_generic_idblock_name,               /* name */
1130         acf_dscam_icon,                                 /* icon */
1131         
1132         acf_generic_dataexpand_setting_valid,   /* has setting */
1133         acf_dscam_setting_flag,                                 /* flag for setting */
1134         acf_dscam_setting_ptr                                   /* pointer for setting */
1135 };
1136
1137 /* Curve Expander  ------------------------------------------- */
1138
1139 // TODO: just get this from RNA?
1140 static int acf_dscur_icon(bAnimListElem *ale)
1141 {
1142         return ICON_CURVE_DATA;
1143 }
1144
1145 /* get the appropriate flag(s) for the setting when it is valid  */
1146 static int acf_dscur_setting_flag(int setting, short *neg)
1147 {
1148         /* clear extra return data first */
1149         *neg= 0;
1150         
1151         switch (setting) {
1152                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1153                         return CU_DS_EXPAND;
1154                         
1155                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1156                         return ADT_NLA_EVAL_OFF;
1157                 
1158                 default: /* unsupported */
1159                         return 0;
1160         }
1161 }
1162
1163 /* get pointer to the setting */
1164 static void *acf_dscur_setting_ptr(bAnimListElem *ale, int setting, short *type)
1165 {
1166         Curve *cu= (Curve *)ale->data;
1167         
1168         /* clear extra return data first */
1169         *type= 0;
1170         
1171         switch (setting) {
1172                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1173                         GET_ACF_FLAG_PTR(cu->flag);
1174                         
1175                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1176                         if (cu->adt)
1177                                 GET_ACF_FLAG_PTR(cu->adt->flag)
1178                         else
1179                                 return NULL;
1180                 
1181                 default: /* unsupported */
1182                         return NULL;
1183         }
1184 }
1185
1186 /* curve expander type define */
1187 static bAnimChannelType ACF_DSCUR= 
1188 {
1189         acf_generic_dataexpand_backdrop,/* backdrop */
1190         acf_generic_indention_1,                /* indent level */
1191         acf_generic_basic_offset,               /* offset */
1192         
1193         acf_generic_idblock_name,               /* name */
1194         acf_dscur_icon,                                 /* icon */
1195         
1196         acf_generic_dataexpand_setting_valid,   /* has setting */
1197         acf_dscur_setting_flag,                                 /* flag for setting */
1198         acf_dscur_setting_ptr                                   /* pointer for setting */
1199 };
1200
1201 /* Shape Key Expander  ------------------------------------------- */
1202
1203 // TODO: just get this from RNA?
1204 static int acf_dsskey_icon(bAnimListElem *ale)
1205 {
1206         return ICON_SHAPEKEY_DATA;
1207 }
1208
1209 /* get the appropriate flag(s) for the setting when it is valid  */
1210 static int acf_dsskey_setting_flag(int setting, short *neg)
1211 {
1212         /* clear extra return data first */
1213         *neg= 0;
1214         
1215         switch (setting) {
1216                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1217                         return KEYBLOCK_DS_EXPAND;
1218                         
1219                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1220                         return ADT_NLA_EVAL_OFF;
1221                 
1222                 default: /* unsupported */
1223                         return 0;
1224         }
1225 }
1226
1227 /* get pointer to the setting */
1228 static void *acf_dsskey_setting_ptr(bAnimListElem *ale, int setting, short *type)
1229 {
1230         Key *key= (Key *)ale->data;
1231         
1232         /* clear extra return data first */
1233         *type= 0;
1234         
1235         switch (setting) {
1236                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1237                         GET_ACF_FLAG_PTR(key->flag);
1238                         
1239                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1240                         if (key->adt)
1241                                 GET_ACF_FLAG_PTR(key->adt->flag)
1242                         else
1243                                 return NULL;
1244                 
1245                 default: /* unsupported */
1246                         return NULL;
1247         }
1248 }
1249
1250 /* shapekey expander type define */
1251 static bAnimChannelType ACF_DSSKEY= 
1252 {
1253         acf_generic_dataexpand_backdrop,/* backdrop */
1254         acf_generic_indention_1,                /* indent level */
1255         acf_generic_basic_offset,               /* offset */
1256         
1257         acf_generic_idblock_name,               /* name */
1258         acf_dsskey_icon,                                /* icon */
1259         
1260         acf_generic_dataexpand_setting_valid,   /* has setting */
1261         acf_dsskey_setting_flag,                                /* flag for setting */
1262         acf_dsskey_setting_ptr                                  /* pointer for setting */
1263 };
1264
1265 /* World Expander  ------------------------------------------- */
1266
1267 // TODO: just get this from RNA?
1268 static int acf_dswor_icon(bAnimListElem *ale)
1269 {
1270         return ICON_WORLD_DATA;
1271 }
1272
1273 /* get the appropriate flag(s) for the setting when it is valid  */
1274 static int acf_dswor_setting_flag(int setting, short *neg)
1275 {
1276         /* clear extra return data first */
1277         *neg= 0;
1278         
1279         switch (setting) {
1280                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1281                         return WO_DS_EXPAND;
1282                         
1283                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1284                         return ADT_NLA_EVAL_OFF;
1285                 
1286                 default: /* unsupported */
1287                         return 0;
1288         }
1289 }
1290
1291 /* get pointer to the setting */
1292 static void *acf_dswor_setting_ptr(bAnimListElem *ale, int setting, short *type)
1293 {
1294         World *wo= (World *)ale->data;
1295         
1296         /* clear extra return data first */
1297         *type= 0;
1298         
1299         switch (setting) {
1300                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1301                         GET_ACF_FLAG_PTR(wo->flag);
1302                         
1303                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1304                         if (wo->adt)
1305                                 GET_ACF_FLAG_PTR(wo->adt->flag)
1306                         else
1307                                 return NULL;
1308                 
1309                 default: /* unsupported */
1310                         return NULL;
1311         }
1312 }
1313
1314 /* world expander type define */
1315 static bAnimChannelType ACF_DSWOR= 
1316 {
1317         acf_generic_dataexpand_backdrop,/* backdrop */
1318         acf_generic_indention_1,                /* indent level */
1319         acf_generic_basic_offset,               /* offset */
1320         
1321         acf_generic_idblock_name,               /* name */
1322         acf_dswor_icon,                                 /* icon */
1323         
1324         acf_generic_dataexpand_setting_valid,   /* has setting */
1325         acf_dswor_setting_flag,                                 /* flag for setting */
1326         acf_dswor_setting_ptr                                   /* pointer for setting */
1327 };
1328
1329 /* Particle Expander  ------------------------------------------- */
1330
1331 // TODO: just get this from RNA?
1332 static int acf_dspart_icon(bAnimListElem *ale)
1333 {
1334         return ICON_PARTICLE_DATA;
1335 }
1336
1337 /* get the appropriate flag(s) for the setting when it is valid  */
1338 static int acf_dspart_setting_flag(int setting, short *neg)
1339 {
1340         /* clear extra return data first */
1341         *neg= 0;
1342         
1343         switch (setting) {
1344                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1345                         return PART_DS_EXPAND;
1346                         
1347                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1348                         return ADT_NLA_EVAL_OFF;
1349                 
1350                 default: /* unsupported */
1351                         return 0;
1352         }
1353 }
1354
1355 /* get pointer to the setting */
1356 static void *acf_dspart_setting_ptr(bAnimListElem *ale, int setting, short *type)
1357 {
1358         ParticleSettings *part= (ParticleSettings *)ale->data;
1359         
1360         /* clear extra return data first */
1361         *type= 0;
1362         
1363         switch (setting) {
1364                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1365                         GET_ACF_FLAG_PTR(part->flag);
1366                         
1367                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1368                         if (part->adt)
1369                                 GET_ACF_FLAG_PTR(part->adt->flag)
1370                         else
1371                                 return NULL;
1372                 
1373                 default: /* unsupported */
1374                         return NULL;
1375         }
1376 }
1377
1378 /* particle expander type define */
1379 static bAnimChannelType ACF_DSPART= 
1380 {
1381         acf_generic_dataexpand_backdrop,/* backdrop */
1382         acf_generic_indention_1,                /* indent level */
1383         acf_generic_basic_offset,               /* offset */
1384         
1385         acf_generic_idblock_name,               /* name */
1386         acf_dspart_icon,                                /* icon */
1387         
1388         acf_generic_dataexpand_setting_valid,   /* has setting */
1389         acf_dspart_setting_flag,                                /* flag for setting */
1390         acf_dspart_setting_ptr                                  /* pointer for setting */
1391 };
1392
1393 /* MetaBall Expander  ------------------------------------------- */
1394
1395 // TODO: just get this from RNA?
1396 static int acf_dsmball_icon(bAnimListElem *ale)
1397 {
1398         return ICON_META_DATA;
1399 }
1400
1401 /* get the appropriate flag(s) for the setting when it is valid  */
1402 static int acf_dsmball_setting_flag(int setting, short *neg)
1403 {
1404         /* clear extra return data first */
1405         *neg= 0;
1406         
1407         switch (setting) {
1408                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1409                         return MB_DS_EXPAND;
1410                         
1411                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1412                         return ADT_NLA_EVAL_OFF;
1413                 
1414                 default: /* unsupported */
1415                         return 0;
1416         }
1417 }
1418
1419 /* get pointer to the setting */
1420 static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *type)
1421 {
1422         MetaBall *mb= (MetaBall *)ale->data;
1423         
1424         /* clear extra return data first */
1425         *type= 0;
1426         
1427         switch (setting) {
1428                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1429                         GET_ACF_FLAG_PTR(mb->flag);
1430                         
1431                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1432                         if (mb->adt)
1433                                 GET_ACF_FLAG_PTR(mb->adt->flag)
1434                         else
1435                                 return NULL;
1436                 
1437                 default: /* unsupported */
1438                         return NULL;
1439         }
1440 }
1441
1442 /* metaball expander type define */
1443 static bAnimChannelType ACF_DSMBALL= 
1444 {
1445         acf_generic_dataexpand_backdrop,/* backdrop */
1446         acf_generic_indention_1,                /* indent level */
1447         acf_generic_basic_offset,               /* offset */
1448         
1449         acf_generic_idblock_name,               /* name */
1450         acf_dsmball_icon,                               /* icon */
1451         
1452         acf_generic_dataexpand_setting_valid,   /* has setting */
1453         acf_dsmball_setting_flag,                               /* flag for setting */
1454         acf_dsmball_setting_ptr                                 /* pointer for setting */
1455 };
1456
1457 /* ShapeKey Entry  ------------------------------------------- */
1458 // XXX ... this is currently obsolete...
1459
1460 #if 0
1461 static void dummy_olddraw_shapekeys ()
1462 {
1463         case ANIMTYPE_SHAPEKEY: /* shapekey channel */
1464         {
1465                 KeyBlock *kb = (KeyBlock *)ale->data;
1466                 
1467                 indent = 0;
1468                 special = -1;
1469                 
1470                 offset= (ale->id) ? 21 : 0;
1471                 
1472                 if (kb->name[0] == '\0')
1473                         sprintf(name, "Key %d", ale->index);
1474                 else
1475                         strcpy(name, kb->name);
1476         }
1477                 break;
1478 }
1479 #endif
1480
1481 /* Grease Pencil entries  ------------------------------------------- */
1482 // XXX ... this is currently not restored yet
1483
1484 #if 0
1485 static void dummy_olddraw_gpencil ()
1486 {
1487         /* determine what needs to be drawn */
1488         switch (ale->type) {
1489                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
1490                 {
1491                         bGPdata *gpd = (bGPdata *)ale->data;
1492                         ScrArea *sa = (ScrArea *)ale->owner;
1493                         
1494                         indent = 0;
1495                         group= 3;
1496                         
1497                         /* only show expand if there are any channels */
1498                         if (gpd->layers.first) {
1499                                 if (gpd->flag & GP_DATA_EXPAND)
1500                                         expand = ICON_TRIA_DOWN;
1501                                 else
1502                                         expand = ICON_TRIA_RIGHT;
1503                         }
1504                         
1505                         switch (sa->spacetype) {
1506                                 case SPACE_VIEW3D:
1507                                 {
1508                                         /* this shouldn't cause any overflow... */
1509                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
1510                                         strcpy(name, "3dView");
1511                                         special= ICON_VIEW3D;
1512                                 }
1513                                         break;
1514                                 case SPACE_NODE:
1515                                 {
1516                                         SpaceNode *snode= sa->spacedata.first;
1517                                         char treetype[12];
1518                                         
1519                                         if (snode->treetype == 1)
1520                                                 strcpy(treetype, "Composite");
1521                                         else
1522                                                 strcpy(treetype, "Material");
1523                                         sprintf(name, "Nodes:%s", treetype);
1524                                         
1525                                         special= ICON_NODE;
1526                                 }
1527                                         break;
1528                                 case SPACE_SEQ:
1529                                 {
1530                                         SpaceSeq *sseq= sa->spacedata.first;
1531                                         char imgpreview[10];
1532                                         
1533                                         switch (sseq->mainb) {
1534                                                 case 1:         sprintf(imgpreview, "Image...");        break;
1535                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
1536                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
1537                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
1538                                                 
1539                                                 default:        sprintf(imgpreview, "Sequence");        break;
1540                                         }
1541                                         sprintf(name, "Sequencer:%s", imgpreview);
1542                                         
1543                                         special= ICON_SEQUENCE;
1544                                 }
1545                                         break;
1546                                 case SPACE_IMAGE:
1547                                 {
1548                                         SpaceImage *sima= sa->spacedata.first;
1549                                         
1550                                         if (sima->image)
1551                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
1552                                         else
1553                                                 strcpy(name, "Image:<None>");
1554                                                 
1555                                         special= ICON_IMAGE_COL;
1556                                 }
1557                                         break;
1558                                 
1559                                 default:
1560                                 {
1561                                         sprintf(name, "<Unknown GP-Data Source>");
1562                                         special= -1;
1563                                 }
1564                                         break;
1565                         }
1566                 }
1567                         break;
1568                 case ANIMTYPE_GPLAYER: /* gpencil layer */
1569                 {
1570                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
1571                         
1572                         indent = 0;
1573                         special = -1;
1574                         expand = -1;
1575                         group = 1;
1576                         
1577                         if (EDITABLE_GPL(gpl))
1578                                 protect = ICON_UNLOCKED;
1579                         else
1580                                 protect = ICON_LOCKED;
1581                                 
1582                         if (gpl->flag & GP_LAYER_HIDE)
1583                                 mute = ICON_MUTE_IPO_ON;
1584                         else
1585                                 mute = ICON_MUTE_IPO_OFF;
1586                         
1587                         sel = SEL_GPL(gpl);
1588                         BLI_snprintf(name, 32, gpl->info);
1589                 }
1590                         break;
1591         }       
1592         
1593         if (group == 3) {
1594                 /* only for gp-data channels */
1595                 UI_ThemeColorShade(TH_GROUP, 20);
1596                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
1597                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
1598         }
1599 }
1600 #endif
1601
1602 /* *********************************************** */
1603 /* Type Registration and General Access */
1604
1605 /* These globals only ever get directly accessed in this file */
1606 static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES];
1607 static short ACF_INIT= 1; /* when non-zero, the list needs to be updated */
1608
1609 /* Initialise type info definitions */
1610 void ANIM_init_channel_typeinfo_data (void)
1611 {
1612         int type= 0;
1613         
1614         /* start initialising if necessary... */
1615         if (ACF_INIT) {
1616                 ACF_INIT= 0;
1617                 
1618                 animchannelTypeInfo[type++]= NULL;                              /* None */
1619                 animchannelTypeInfo[type++]= NULL;                              /* AnimData */
1620                 animchannelTypeInfo[type++]= NULL;                              /* Special */
1621                 
1622                 animchannelTypeInfo[type++]= &ACF_SCENE;                /* Scene */
1623                 animchannelTypeInfo[type++]= &ACF_OBJECT;               /* Object */
1624                 animchannelTypeInfo[type++]= &ACF_GROUP;                /* Group */
1625                 animchannelTypeInfo[type++]= &ACF_FCURVE;               /* F-Curve */
1626                 
1627                 animchannelTypeInfo[type++]= &ACF_FILLACTD;     /* Object Action Expander */
1628                 animchannelTypeInfo[type++]= &ACF_FILLDRIVERS;  /* Drivers Expander */
1629                 animchannelTypeInfo[type++]= &ACF_FILLMATD;     /* Materials Expander */
1630                 animchannelTypeInfo[type++]= &ACF_FILLPARTD;    /* Particles Expander */
1631                 
1632                 animchannelTypeInfo[type++]= &ACF_DSMAT;                /* Material Channel */
1633                 animchannelTypeInfo[type++]= &ACF_DSLAM;                /* Lamp Channel */
1634                 animchannelTypeInfo[type++]= &ACF_DSCAM;                /* Camera Channel */
1635                 animchannelTypeInfo[type++]= &ACF_DSCUR;                /* Curve Channel */
1636                 animchannelTypeInfo[type++]= &ACF_DSSKEY;               /* ShapeKey Channel */
1637                 animchannelTypeInfo[type++]= &ACF_DSWOR;                /* World Channel */
1638                 animchannelTypeInfo[type++]= &ACF_DSPART;               /* Particle Channel */
1639                 animchannelTypeInfo[type++]= &ACF_DSMBALL;              /* MetaBall Channel */
1640                 
1641                 animchannelTypeInfo[type++]= NULL;                              /* ShapeKey */ // XXX this is no longer used for now...
1642                 
1643                         // XXX not restored yet
1644                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Datablock */ 
1645                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Layer */ 
1646                 
1647                         // TODO: these types still need to be implemented!!!
1648                         // probably need a few extra flags for these special cases...
1649                 animchannelTypeInfo[type++]= NULL;                              /* NLA Track */ 
1650                 animchannelTypeInfo[type++]= NULL;                              /* NLA Action */ 
1651         }
1652
1653
1654 /* Get type info from given channel type */
1655 bAnimChannelType *ANIM_channel_get_typeinfo (bAnimListElem *ale)
1656 {
1657         /* santiy checks */
1658         if (ale == NULL)
1659                 return NULL;
1660                 
1661         /* init the typeinfo if not available yet... */
1662         ANIM_init_channel_typeinfo_data();
1663         
1664         /* check if type is in bounds... */
1665         if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES))
1666                 return animchannelTypeInfo[ale->type];
1667         else
1668                 return NULL;
1669 }
1670
1671 /* --------------------------- */
1672
1673 /* Check if some setting for a channel is enabled 
1674  * Returns: 1 = On, 0 = Off, -1 = Invalid
1675  */
1676 short ANIM_channel_setting_get (bAnimContext *ac, bAnimListElem *ale, int setting)
1677 {
1678         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
1679         
1680         /* 1) check that the setting exists for the current context */
1681         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
1682         {
1683                 /* 2) get pointer to check for flag in, and the flag to check for */
1684                 short negflag, ptrsize;
1685                 int flag;
1686                 void *ptr;
1687                 
1688                 flag= acf->setting_flag(setting, &negflag);
1689                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
1690                 
1691                 /* check if flag is enabled */
1692                 if (ptr && flag) {
1693                         switch (ptrsize) {
1694                                 case sizeof(int):       /* integer pointer for setting */
1695                                 {
1696                                         int *val= (int *)ptr;
1697                                         
1698                                         if (negflag)
1699                                                 return ((*val) & flag) == 0;
1700                                         else
1701                                                 return ((*val) & flag) != 0;
1702                                 }
1703                                         break;
1704                                         
1705                                 case sizeof(short):     /* short pointer for setting */
1706                                 {
1707                                         short *val= (short *)ptr;
1708                                         
1709                                         if (negflag)
1710                                                 return ((*val) & flag) == 0;
1711                                         else
1712                                                 return ((*val) & flag) != 0;
1713                                 }
1714                                         break;
1715                                         
1716                                 case sizeof(char):      /* char pointer for setting */
1717                                 {
1718                                         char *val= (char *)ptr;
1719                                         
1720                                         if (negflag)
1721                                                 return ((*val) & flag) == 0;
1722                                         else
1723                                                 return ((*val) & flag) != 0;
1724                                 }
1725                                         break;
1726                         }
1727                 }
1728         }
1729         
1730         /* not found... */
1731         return -1;
1732 }       
1733
1734
1735 /* quick macro for use in ANIM_channel_setting_set - set flag for setting according the mode given */
1736 #define ACF_SETTING_SET(sval, sflag, smode) \
1737         {\
1738                 if (negflag) {\
1739                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
1740                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) &= ~(sflag); \
1741                         else                                                                    (sval) |= (sflag); \
1742                 } \
1743                 else {\
1744                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
1745                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) |= (sflag); \
1746                         else                                                                    (sval) &= ~(sflag); \
1747                 }\
1748         }
1749
1750 /* Change value of some setting for a channel 
1751  *      - setting: eAnimChannel_Settings
1752  *      - mode: eAnimChannels_SetFlag
1753  */
1754 void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting, short mode)
1755 {
1756         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
1757         
1758         /* 1) check that the setting exists for the current context */
1759         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
1760         {
1761                 /* 2) get pointer to check for flag in, and the flag to check for */
1762                 short negflag, ptrsize;
1763                 int flag;
1764                 void *ptr;
1765                 
1766                 flag= acf->setting_flag(setting, &negflag);
1767                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
1768                 
1769                 /* check if flag is enabled */
1770                 if (ptr && flag) {
1771                         switch (ptrsize) {
1772                                 case sizeof(int):       /* integer pointer for setting */
1773                                 {
1774                                         int *val= (int *)ptr;
1775                                         ACF_SETTING_SET(*val, flag, mode);
1776                                 }
1777                                         break;
1778                                         
1779                                 case sizeof(short):     /* short pointer for setting */
1780                                 {
1781                                         short *val= (short *)ptr;
1782                                         ACF_SETTING_SET(*val, flag, mode);
1783                                 }
1784                                         break;
1785                                         
1786                                 case sizeof(char):      /* char pointer for setting */
1787                                 {
1788                                         char *val= (char *)ptr;
1789                                         ACF_SETTING_SET(*val, flag, mode);
1790                                 }
1791                                         break;
1792                         }
1793                 }
1794         }
1795 }
1796
1797 /* --------------------------- */
1798
1799 // XXX hardcoded size of icons
1800 #define ICON_WIDTH              17
1801
1802 /* Draw the given channel */
1803 // TODO: make this use UI controls for the buttons
1804 void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
1805 {
1806         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
1807         View2D *v2d= &ac->ar->v2d;
1808         short selected, offset, enabled;
1809         float y, ymid, ytext;
1810         
1811         /* sanity checks - don't draw anything */
1812         if ELEM(NULL, acf, ale)
1813                 return;
1814         
1815         /* get initial offset */
1816         if (acf->get_offset)
1817                 offset= acf->get_offset(ac, ale);
1818         else if (acf->get_indent_level)
1819                 offset= acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
1820         else
1821                 offset= 0;
1822                 
1823         /* calculate appropriate y-coordinates for icon buttons 
1824          *      7 is hardcoded factor for half-height of icons
1825          */
1826         y= (ymaxc - yminc)/2 + yminc;
1827         ymid= y - 7;
1828         /* y-coordinates for text is only 4 down from middle */
1829         ytext= y - 4;
1830         
1831         /* check if channel is selected */
1832         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
1833                 selected= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
1834         else
1835                 selected= 0;
1836         
1837         /* enable correct blending mode for icons to work... */
1838         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1839         glEnable(GL_BLEND);
1840         
1841         /* step 1) draw backdrop ...........................................  */
1842         if (acf->draw_backdrop)
1843                 acf->draw_backdrop(ac, ale, yminc, ymaxc);
1844                 
1845         /* step 2) draw expand widget ....................................... */
1846         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
1847                 enabled= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND);
1848                 
1849                 UI_icon_draw(offset, ymid, ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT));
1850                 offset += ICON_WIDTH; 
1851         }
1852                 
1853         /* step 3) draw icon ............................................... */
1854         if (acf->icon) {
1855                 UI_icon_draw(offset, ymid, acf->icon(ale));
1856                 offset += ICON_WIDTH; 
1857         }
1858                 
1859         /* step 4) draw special toggles  .................................
1860          *      - in Graph Editor, checkboxes for visibility in curves area
1861          *      - in NLA Editor, glowing dots for solo/not solo...
1862          */
1863         if (ac->sa) {
1864                 if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
1865                         enabled= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_VISIBLE);
1866                         
1867                         /* for F-Curves, draw color-preview of curve behind checkbox */
1868                         if (ale->type == ANIMTYPE_FCURVE) {
1869                                 FCurve *fcu= (FCurve *)ale->data;
1870                                 
1871                                 /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever 
1872                                  * color the curve has stored 
1873                                  */
1874                                 glColor3fv(fcu->color);
1875                                 
1876                                 /* just a solid color rect
1877                                  *      hardcoded 17 pixels width is slightly wider than icon width, so that 
1878                                  *      there's a slight border around it 
1879                                  */
1880                                 glRectf(offset, yminc, offset+17, ymaxc);
1881                         }
1882                         
1883                         /* finally the icon itself */
1884                         UI_icon_draw(offset, ymid, ((enabled)? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT));
1885                         offset += ICON_WIDTH; 
1886                 }
1887                 else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
1888                         /* simply draw glowing dot in NLA for whether the track is enabled or not... */
1889                         // NOTE: assumed to be for NLA track only for now...
1890                         enabled= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SOLO);
1891                         
1892                         UI_icon_draw(offset, ymid, ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED));
1893                         offset += ICON_WIDTH; 
1894                 }
1895         }
1896         
1897         glDisable(GL_BLEND); /* End of blending with background (text now gets drawn) */
1898         
1899         /* step 5) draw name ............................................... */
1900         if (acf->name) {
1901                 char name[256]; /* hopefully this will be enough! */
1902                 
1903                 /* set text color */
1904                 if (selected)
1905                         UI_ThemeColor(TH_TEXT_HI);
1906                 else
1907                         UI_ThemeColor(TH_TEXT);
1908                         
1909                 /* get name */
1910                 acf->name(ale, name);
1911                 
1912                 offset += 3;
1913                 UI_DrawString(offset, ytext, name);
1914         }
1915         
1916         /* step 6) draw mute+protection toggles + (sliders) ....................... */
1917         /* reset offset - now goes from RHS of panel */
1918         offset = 0;
1919         
1920         // TODO: we need a mechanism of drawing over (and hiding) stuff from here...
1921         // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
1922         
1923         if (v2d) {
1924                 /* set blending again, as text drawing may clear it */
1925                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1926                 glEnable(GL_BLEND);
1927                 
1928                 /* protect... */
1929                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
1930                         enabled= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_PROTECT);
1931                         
1932                         offset += ICON_WIDTH;
1933                         UI_icon_draw(v2d->cur.xmax-(float)offset, ymid, ((enabled)? ICON_LOCKED : ICON_UNLOCKED));
1934                 }
1935                 /* mute... */
1936                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
1937                         enabled= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_MUTE);
1938                         
1939                         offset += ICON_WIDTH; 
1940                         UI_icon_draw(v2d->cur.xmax-(float)offset, ymid, ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF));
1941                 }
1942                 
1943                 glDisable(GL_BLEND); /* End of blending with background */
1944         }
1945 }
1946
1947 /* *********************************************** */