* Fix for camera+internal surface object inside ztransp volume
[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                 strcpy(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                  /* visible - only available in Graph Editor */
291                 case ACHANNEL_SETTING_VISIBLE: 
292                         return ((ac) && (ac->spacetype == SPACE_IPO));
293                         
294                 default:
295                         return 0;
296         }
297 }
298
299 /* get pointer to the setting (category only) */
300 static void *acf_generic_dsexpand_setting_ptr(bAnimListElem *ale, int setting, short *type)
301 {
302         Object *ob= (Object *)ale->data;
303         
304         /* clear extra return data first */
305         *type= 0;
306         
307         switch (setting) {
308                 case ACHANNEL_SETTING_EXPAND: /* expanded */
309                         GET_ACF_FLAG_PTR(ob->nlaflag); // XXX
310                 
311                 default: /* unsupported */
312                         return NULL;
313         }
314 }
315
316 /* check if some setting exists for this object-based data-expander (datablock only) */
317 static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
318 {
319         switch (setting) {
320                 /* expand is always supported */
321                 case ACHANNEL_SETTING_EXPAND:
322                         return 1;
323                         
324                 /* mute is only supported for NLA */
325                 case ACHANNEL_SETTING_MUTE:
326                         return ((ac) && (ac->spacetype == SPACE_NLA));
327                         
328                 /* other flags are never supported */
329                 default:
330                         return 0;
331         }
332 }
333
334 /* *********************************************** */
335 /* Type Specific Functions + Defines */
336
337 /* Scene ------------------------------------------- */
338
339 // TODO: just get this from RNA?
340 static int acf_scene_icon(bAnimListElem *ale)
341 {
342         return ICON_SCENE_DATA;
343 }
344
345 /* check if some setting exists for this channel */
346 static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
347 {
348         switch (setting) {
349                 /* muted only in NLA */
350                 case ACHANNEL_SETTING_MUTE: 
351                         return ((ac) && (ac->spacetype == SPACE_NLA));
352                         
353                 /* visible only in Graph Editor */
354                 case ACHANNEL_SETTING_VISIBLE: 
355                         return ((ac) && (ac->spacetype == SPACE_IPO));
356                 
357                 /* only select and expand supported otherwise */
358                 case ACHANNEL_SETTING_SELECT:
359                 case ACHANNEL_SETTING_EXPAND:
360                         return 1;
361                         
362                 default:
363                         return 0;
364         }
365 }
366
367 /* get the appropriate flag(s) for the setting when it is valid  */
368 static int acf_scene_setting_flag(int setting, short *neg)
369 {
370         /* clear extra return data first */
371         *neg= 0;
372         
373         switch (setting) {
374                 case ACHANNEL_SETTING_SELECT: /* selected */
375                         return SCE_DS_SELECTED;
376                         
377                 case ACHANNEL_SETTING_EXPAND: /* expanded */
378                         *neg= 1;
379                         return SCE_DS_COLLAPSED;
380                         
381                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
382                         return ADT_NLA_EVAL_OFF;
383                         
384                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
385                         *neg= 1;
386                         return ADT_CURVES_NOT_VISIBLE;
387                         
388                 default: /* unsupported */
389                         return 0;
390         }
391 }
392
393 /* get pointer to the setting */
394 static void *acf_scene_setting_ptr(bAnimListElem *ale, int setting, short *type)
395 {
396         Scene *scene= (Scene *)ale->data;
397         
398         /* clear extra return data first */
399         *type= 0;
400         
401         switch (setting) {
402                 case ACHANNEL_SETTING_SELECT: /* selected */
403                         GET_ACF_FLAG_PTR(scene->flag);
404                         
405                 case ACHANNEL_SETTING_EXPAND: /* expanded */
406                         GET_ACF_FLAG_PTR(scene->flag);
407                         
408                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
409                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
410                         if (scene->adt)
411                                 GET_ACF_FLAG_PTR(scene->adt->flag)
412                         else
413                                 return NULL;
414                         
415                 default: /* unsupported */
416                         return 0;
417         }
418 }
419
420 /* scene type define */
421 static bAnimChannelType ACF_SCENE = 
422 {
423         acf_generic_root_backdrop,              /* backdrop */
424         acf_generic_indention_0,                /* indent level */
425         NULL,                                                   /* offset */
426         
427         acf_generic_idblock_name,               /* name */
428         acf_scene_icon,                                 /* icon */
429         
430         acf_scene_setting_valid,                /* has setting */
431         acf_scene_setting_flag,                 /* flag for setting */
432         acf_scene_setting_ptr                   /* pointer for setting */
433 };
434
435 /* Object ------------------------------------------- */
436
437 static int acf_object_icon(bAnimListElem *ale)
438 {
439         Base *base= (Base *)ale->data;
440         Object *ob= base->object;
441         
442         /* icon depends on object-type */
443         if (ob->type == OB_ARMATURE)
444                 return ICON_ARMATURE_DATA;
445         else    
446                 return ICON_OBJECT_DATA;
447 }
448
449 /* name for object */
450 static void acf_object_name(bAnimListElem *ale, char *name)
451 {
452         Base *base= (Base *)ale->data;
453         Object *ob= base->object;
454         
455         /* just copy the name... */
456         if (ob && name)
457                 strcpy(name, ob->id.name+2);
458 }
459
460 /* check if some setting exists for this channel */
461 static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
462 {
463         switch (setting) {
464                 /* muted only in NLA */
465                 case ACHANNEL_SETTING_MUTE: 
466                         return ((ac) && (ac->spacetype == SPACE_NLA));
467                         
468                 /* visible only in Graph Editor */
469                 case ACHANNEL_SETTING_VISIBLE: 
470                         return ((ac) && (ac->spacetype == SPACE_IPO));
471                 
472                 /* only select and expand supported otherwise */
473                 case ACHANNEL_SETTING_SELECT:
474                 case ACHANNEL_SETTING_EXPAND:
475                         return 1;
476                         
477                 default:
478                         return 0;
479         }
480 }
481
482 /* get the appropriate flag(s) for the setting when it is valid  */
483 static int acf_object_setting_flag(int setting, short *neg)
484 {
485         /* clear extra return data first */
486         *neg= 0;
487         
488         switch (setting) {
489                 case ACHANNEL_SETTING_SELECT: /* selected */
490                         return SELECT;
491                         
492                 case ACHANNEL_SETTING_EXPAND: /* expanded */
493                         *neg= 1;
494                         return OB_ADS_COLLAPSED;
495                         
496                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
497                         return ADT_NLA_EVAL_OFF;
498                         
499                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
500                         *neg= 1;
501                         return ADT_CURVES_NOT_VISIBLE;
502                         
503                 default: /* unsupported */
504                         return 0;
505         }
506 }
507
508 /* get pointer to the setting */
509 static void *acf_object_setting_ptr(bAnimListElem *ale, int setting, short *type)
510 {
511         Base *base= (Base *)ale->data;
512         Object *ob= base->object;
513         
514         /* clear extra return data first */
515         *type= 0;
516         
517         switch (setting) {
518                 case ACHANNEL_SETTING_SELECT: /* selected */
519                         GET_ACF_FLAG_PTR(ob->flag);
520                         
521                 case ACHANNEL_SETTING_EXPAND: /* expanded */
522                         GET_ACF_FLAG_PTR(ob->nlaflag); // xxx
523                         
524                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
525                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
526                         if (ob->adt)
527                                 GET_ACF_FLAG_PTR(ob->adt->flag)
528                         else
529                                 return NULL;
530                         
531                 default: /* unsupported */
532                         return 0;
533         }
534 }
535
536 /* object type define */
537 static bAnimChannelType ACF_OBJECT = 
538 {
539         acf_generic_root_backdrop,              /* backdrop */
540         acf_generic_indention_0,                /* indent level */
541         NULL,                                                   /* offset */
542         
543         acf_object_name,                                /* name */
544         acf_object_icon,                                /* icon */
545         
546         acf_object_setting_valid,               /* has setting */
547         acf_object_setting_flag,                /* flag for setting */
548         acf_object_setting_ptr                  /* pointer for setting */
549 };
550
551 /* Group ------------------------------------------- */
552
553 /* backdrop for group widget */
554 static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
555 {
556         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
557         View2D *v2d= &ac->ar->v2d;
558         short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
559         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
560         
561         /* only for action group channels */
562         if (ale->flag & AGRP_ACTIVE)
563                 UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
564         else
565                 UI_ThemeColorShade(TH_GROUP, 20);
566         
567         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
568         uiSetRoundBox((expanded)? (1):(1|8));
569         gl_round_box(GL_POLYGON, offset,  yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8);
570 }
571
572 /* name for group entries */
573 static void acf_group_name(bAnimListElem *ale, char *name)
574 {
575         bActionGroup *agrp= (bActionGroup *)ale->data;
576         
577         /* just copy the name... */
578         if (agrp && name)
579                 strcpy(name, agrp->name);
580 }
581
582 /* check if some setting exists for this channel */
583 static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
584 {
585         /* for now, all settings are supported, though some are only conditionally */
586         switch (setting) {
587                 case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
588                         return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO));
589                         
590                 default: /* always supported */
591                         return 1;
592         }
593 }
594
595 /* get the appropriate flag(s) for the setting when it is valid  */
596 static int acf_group_setting_flag(int setting, short *neg)
597 {
598         /* clear extra return data first */
599         *neg= 0;
600         
601         switch (setting) {
602                 case ACHANNEL_SETTING_SELECT: /* selected */
603                         return AGRP_SELECTED;
604                         
605                 case ACHANNEL_SETTING_EXPAND: /* expanded */
606                         return AGRP_EXPANDED;
607                         
608                 case ACHANNEL_SETTING_MUTE: /* muted */
609                         return AGRP_MUTED;
610                         
611                 case ACHANNEL_SETTING_PROTECT: /* protected */
612                         //*neg= 1; - if we change this to edtiability
613                         return AGRP_PROTECTED;
614                         
615                 case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
616                         *neg= 1;
617                         return AGRP_NOTVISIBLE;
618         }
619         
620         /* this shouldn't happen */
621         return 0;
622 }
623
624 /* get pointer to the setting */
625 static void *acf_group_setting_ptr(bAnimListElem *ale, int setting, short *type)
626 {
627         bActionGroup *agrp= (bActionGroup *)ale->data;
628         
629         /* all flags are just in agrp->flag for now... */
630         GET_ACF_FLAG_PTR(agrp->flag);
631 }
632
633 /* group type define */
634 static bAnimChannelType ACF_GROUP = 
635 {
636         acf_group_backdrop,                             /* backdrop */
637         acf_generic_indention_0,                /* indent level */
638         acf_generic_group_offset,               /* offset */
639         
640         acf_group_name,                                 /* name */
641         NULL,                                                   /* icon */
642         
643         acf_group_setting_valid,                /* has setting */
644         acf_group_setting_flag,                 /* flag for setting */
645         acf_group_setting_ptr                   /* pointer for setting */
646 };
647
648 /* F-Curve ------------------------------------------- */
649
650 /* name for fcurve entries */
651 static void acf_fcurve_name(bAnimListElem *ale, char *name)
652 {
653         getname_anim_fcurve(name, ale->id, ale->data);
654 }
655
656 /* check if some setting exists for this channel */
657 static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
658 {
659         FCurve *fcu= (FCurve *)ale->data;
660         
661         switch (setting) {
662                 /* unsupported */
663                 case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
664                         return 0;
665                 
666                 /* conditionally available */
667                 case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
668                         if (fcu->bezt)
669                                 return 1;
670                         else
671                                 return 0; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
672                                 
673                 case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
674                         return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO));
675                         
676                 /* always available */
677                 default:
678                         return 1;
679         }
680 }
681
682 /* get the appropriate flag(s) for the setting when it is valid  */
683 static int acf_fcurve_setting_flag(int setting, short *neg)
684 {
685         /* clear extra return data first */
686         *neg= 0;
687         
688         switch (setting) {
689                 case ACHANNEL_SETTING_SELECT: /* selected */
690                         return FCURVE_SELECTED;
691                         
692                 case ACHANNEL_SETTING_MUTE: /* muted */
693                         return FCURVE_MUTED;
694                         
695                 case ACHANNEL_SETTING_PROTECT: /* protected */
696                         //*neg= 1; - if we change this to edtiability
697                         return FCURVE_PROTECTED;
698                         
699                 case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
700                         return FCURVE_VISIBLE;
701                         
702                 default: /* unsupported */
703                         return 0;
704         }
705 }
706
707 /* get pointer to the setting */
708 static void *acf_fcurve_setting_ptr(bAnimListElem *ale, int setting, short *type)
709 {
710         FCurve *fcu= (FCurve *)ale->data;
711         
712         /* all flags are just in agrp->flag for now... */
713         GET_ACF_FLAG_PTR(fcu->flag);
714 }
715
716 /* fcurve type define */
717 static bAnimChannelType ACF_FCURVE = 
718 {
719         acf_generic_channel_backdrop,   /* backdrop */
720         acf_generic_indention_flexible, /* indent level */              // xxx rename this to f-curves only?
721         acf_generic_group_offset,               /* offset */
722         
723         acf_fcurve_name,                                /* name */
724         NULL,                                                   /* icon */
725         
726         acf_fcurve_setting_valid,               /* has setting */
727         acf_fcurve_setting_flag,                /* flag for setting */
728         acf_fcurve_setting_ptr                  /* pointer for setting */
729 };
730
731 /* Object Action Expander  ------------------------------------------- */
732
733 // TODO: just get this from RNA?
734 static int acf_fillactd_icon(bAnimListElem *ale)
735 {
736         return ICON_ACTION;
737 }
738
739 /* check if some setting exists for this channel */
740 static short acf_fillactd_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
741 {
742         switch (setting) {
743                 /* only select and expand supported */
744                 case ACHANNEL_SETTING_SELECT:
745                 case ACHANNEL_SETTING_EXPAND:
746                         return 1;
747                         
748                 default:
749                         return 0;
750         }
751 }
752
753 /* get the appropriate flag(s) for the setting when it is valid  */
754 static int acf_fillactd_setting_flag(int setting, short *neg)
755 {
756         /* clear extra return data first */
757         *neg= 0;
758         
759         switch (setting) {
760                 case ACHANNEL_SETTING_SELECT: /* selected */
761                         return ACT_SELECTED;
762                         
763                 case ACHANNEL_SETTING_EXPAND: /* expanded */
764                         *neg= 1;
765                         return ACT_COLLAPSED;
766                 
767                 default: /* unsupported */
768                         return 0;
769         }
770 }
771
772 /* get pointer to the setting */
773 static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *type)
774 {
775         bAction *act= (bAction *)ale->data;
776         
777         /* clear extra return data first */
778         *type= 0;
779         
780         switch (setting) {
781                 case ACHANNEL_SETTING_SELECT: /* selected */
782                         GET_ACF_FLAG_PTR(act->flag);
783                         
784                 case ACHANNEL_SETTING_EXPAND: /* expanded */
785                         GET_ACF_FLAG_PTR(act->flag);
786                 
787                 default: /* unsupported */
788                         return 0;
789         }
790 }
791
792 /* object action expander type define */
793 static bAnimChannelType ACF_FILLACTD = 
794 {
795         acf_generic_dataexpand_backdrop,/* backdrop */
796         acf_generic_indention_1,                /* indent level */
797         acf_generic_basic_offset,               /* offset */
798         
799         acf_generic_idblock_name,               /* name */
800         acf_fillactd_icon,                              /* icon */
801         
802         acf_fillactd_setting_valid,             /* has setting */
803         acf_fillactd_setting_flag,              /* flag for setting */
804         acf_fillactd_setting_ptr                /* pointer for setting */
805 };
806
807 /* Drivers Expander  ------------------------------------------- */
808
809 // TODO: just get this from RNA?
810 static int acf_filldrivers_icon(bAnimListElem *ale)
811 {
812         return ICON_ANIM_DATA;
813 }
814
815 static void acf_filldrivers_name(bAnimListElem *ale, char *name)
816 {
817         strcpy(name, "Drivers");
818 }
819
820 /* check if some setting exists for this channel */
821 // TODO: this could be made more generic
822 static short acf_filldrivers_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
823 {
824         switch (setting) {
825                 /* only expand supported */
826                 case ACHANNEL_SETTING_EXPAND:
827                         return 1;
828                         
829                 default:
830                         return 0;
831         }
832 }
833
834 /* get the appropriate flag(s) for the setting when it is valid  */
835 static int acf_filldrivers_setting_flag(int setting, short *neg)
836 {
837         /* clear extra return data first */
838         *neg= 0;
839         
840         switch (setting) {
841                 case ACHANNEL_SETTING_EXPAND: /* expanded */
842                         *neg= 1;
843                         return ADT_DRIVERS_COLLAPSED;
844                 
845                 default: /* unsupported */
846                         return 0;
847         }
848 }
849
850 /* get pointer to the setting */
851 static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, int setting, short *type)
852 {
853         AnimData *adt= (AnimData *)ale->data;
854         
855         /* clear extra return data first */
856         *type= 0;
857         
858         switch (setting) {
859                 case ACHANNEL_SETTING_EXPAND: /* expanded */
860                         GET_ACF_FLAG_PTR(adt->flag);
861                 
862                 default: /* unsupported */
863                         return 0;
864         }
865 }
866
867 /* drivers expander type define */
868 static bAnimChannelType ACF_FILLDRIVERS = 
869 {
870         acf_generic_dataexpand_backdrop,/* backdrop */
871         acf_generic_indention_1,                /* indent level */
872         acf_generic_basic_offset,               /* offset */
873         
874         acf_filldrivers_name,                   /* name */
875         acf_filldrivers_icon,                   /* icon */
876         
877         acf_filldrivers_setting_valid,  /* has setting */
878         acf_filldrivers_setting_flag,   /* flag for setting */
879         acf_filldrivers_setting_ptr             /* pointer for setting */
880 };
881
882 /* Materials Expander  ------------------------------------------- */
883
884 // TODO: just get this from RNA?
885 static int acf_fillmatd_icon(bAnimListElem *ale)
886 {
887         return ICON_MATERIAL_DATA;
888 }
889
890 static void acf_fillmatd_name(bAnimListElem *ale, char *name)
891 {
892         strcpy(name, "Materials");
893 }
894
895 /* get the appropriate flag(s) for the setting when it is valid  */
896 static int acf_fillmatd_setting_flag(int setting, short *neg)
897 {
898         /* clear extra return data first */
899         *neg= 0;
900         
901         switch (setting) {
902                 case ACHANNEL_SETTING_EXPAND: /* expanded */
903                         *neg= 1;
904                         return OB_ADS_SHOWMATS;
905                 
906                 default: /* unsupported */
907                         return 0;
908         }
909 }
910
911 /* materials expander type define */
912 static bAnimChannelType ACF_FILLMATD= 
913 {
914         acf_generic_dataexpand_backdrop,/* backdrop */
915         acf_generic_indention_1,                /* indent level */
916         acf_generic_basic_offset,               /* offset */
917         
918         acf_fillmatd_name,                              /* name */
919         acf_fillmatd_icon,                              /* icon */
920         
921         acf_generic_dsexpand_setting_valid,     /* has setting */
922         acf_fillmatd_setting_flag,                              /* flag for setting */
923         acf_generic_dsexpand_setting_ptr                /* pointer for setting */
924 };
925
926 /* Particles Expander  ------------------------------------------- */
927
928 // TODO: just get this from RNA?
929 static int acf_fillpartd_icon(bAnimListElem *ale)
930 {
931         return ICON_PARTICLE_DATA;
932 }
933
934 static void acf_fillpartd_name(bAnimListElem *ale, char *name)
935 {
936         strcpy(name, "Particles");
937 }
938
939 /* get the appropriate flag(s) for the setting when it is valid  */
940 static int acf_fillpartd_setting_flag(int setting, short *neg)
941 {
942         /* clear extra return data first */
943         *neg= 0;
944         
945         switch (setting) {
946                 case ACHANNEL_SETTING_EXPAND: /* expanded */
947                         *neg= 1;
948                         return OB_ADS_SHOWPARTS;
949                 
950                 default: /* unsupported */
951                         return 0;
952         }
953 }
954
955 /* particles expander type define */
956 static bAnimChannelType ACF_FILLPARTD= 
957 {
958         acf_generic_dataexpand_backdrop,/* backdrop */
959         acf_generic_indention_1,                /* indent level */
960         acf_generic_basic_offset,               /* offset */
961         
962         acf_fillpartd_name,                             /* name */
963         acf_fillpartd_icon,                             /* icon */
964         
965         acf_generic_dsexpand_setting_valid,     /* has setting */
966         acf_fillpartd_setting_flag,                             /* flag for setting */
967         acf_generic_dsexpand_setting_ptr                /* pointer for setting */
968 };
969
970 /* Material Expander  ------------------------------------------- */
971
972 // TODO: just get this from RNA?
973 static int acf_dsmat_icon(bAnimListElem *ale)
974 {
975         return ICON_MATERIAL_DATA;
976 }
977
978 /* offset for material expanders */
979 static short acf_dsmat_offset(bAnimContext *ac, bAnimListElem *ale)
980 {
981         return 21;
982 }
983
984 /* get the appropriate flag(s) for the setting when it is valid  */
985 static int acf_dsmat_setting_flag(int setting, short *neg)
986 {
987         /* clear extra return data first */
988         *neg= 0;
989         
990         switch (setting) {
991                 case ACHANNEL_SETTING_EXPAND: /* expanded */
992                         return MA_DS_EXPAND;
993                         
994                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
995                         return ADT_NLA_EVAL_OFF;
996                         
997                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
998                         *neg= 1;
999                         return ADT_CURVES_NOT_VISIBLE;
1000                 
1001                 default: /* unsupported */
1002                         return 0;
1003         }
1004 }
1005
1006 /* get pointer to the setting */
1007 static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type)
1008 {
1009         Material *ma= (Material *)ale->data;
1010         
1011         /* clear extra return data first */
1012         *type= 0;
1013         
1014         switch (setting) {
1015                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1016                         GET_ACF_FLAG_PTR(ma->flag);
1017                         
1018                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1019                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1020                         if (ma->adt)
1021                                 GET_ACF_FLAG_PTR(ma->adt->flag)
1022                         else
1023                                 return NULL;    
1024                 
1025                 default: /* unsupported */
1026                         return NULL;
1027         }
1028 }
1029
1030 /* material expander type define */
1031 static bAnimChannelType ACF_DSMAT= 
1032 {
1033         acf_generic_channel_backdrop,   /* backdrop */
1034         acf_generic_indention_0,                /* indent level */
1035         acf_dsmat_offset,                               /* offset */
1036         
1037         acf_generic_idblock_name,               /* name */
1038         acf_dsmat_icon,                                 /* icon */
1039         
1040         acf_generic_dataexpand_setting_valid,   /* has setting */
1041         acf_dsmat_setting_flag,                                 /* flag for setting */
1042         acf_dsmat_setting_ptr                                   /* pointer for setting */
1043 };
1044
1045 /* Lamp Expander  ------------------------------------------- */
1046
1047 // TODO: just get this from RNA?
1048 static int acf_dslam_icon(bAnimListElem *ale)
1049 {
1050         return ICON_LAMP_DATA;
1051 }
1052
1053 /* get the appropriate flag(s) for the setting when it is valid  */
1054 static int acf_dslam_setting_flag(int setting, short *neg)
1055 {
1056         /* clear extra return data first */
1057         *neg= 0;
1058         
1059         switch (setting) {
1060                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1061                         return LA_DS_EXPAND;
1062                         
1063                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1064                         return ADT_NLA_EVAL_OFF;
1065                         
1066                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1067                         *neg= 1;
1068                         return ADT_CURVES_NOT_VISIBLE;
1069                 
1070                 default: /* unsupported */
1071                         return 0;
1072         }
1073 }
1074
1075 /* get pointer to the setting */
1076 static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type)
1077 {
1078         Lamp *la= (Lamp *)ale->data;
1079         
1080         /* clear extra return data first */
1081         *type= 0;
1082         
1083         switch (setting) {
1084                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1085                         GET_ACF_FLAG_PTR(la->flag);
1086                         
1087                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1088                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1089                         if (la->adt)
1090                                 GET_ACF_FLAG_PTR(la->adt->flag)
1091                         else
1092                                 return NULL;    
1093                 
1094                 default: /* unsupported */
1095                         return NULL;
1096         }
1097 }
1098
1099 /* lamp expander type define */
1100 static bAnimChannelType ACF_DSLAM= 
1101 {
1102         acf_generic_dataexpand_backdrop,/* backdrop */
1103         acf_generic_indention_1,                /* indent level */
1104         acf_generic_basic_offset,               /* offset */
1105         
1106         acf_generic_idblock_name,               /* name */
1107         acf_dslam_icon,                                 /* icon */
1108         
1109         acf_generic_dataexpand_setting_valid,   /* has setting */
1110         acf_dslam_setting_flag,                                 /* flag for setting */
1111         acf_dslam_setting_ptr                                   /* pointer for setting */
1112 };
1113
1114 /* Camera Expander  ------------------------------------------- */
1115
1116 // TODO: just get this from RNA?
1117 static int acf_dscam_icon(bAnimListElem *ale)
1118 {
1119         return ICON_CAMERA_DATA;
1120 }
1121
1122 /* get the appropriate flag(s) for the setting when it is valid  */
1123 static int acf_dscam_setting_flag(int setting, short *neg)
1124 {
1125         /* clear extra return data first */
1126         *neg= 0;
1127         
1128         switch (setting) {
1129                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1130                         return CAM_DS_EXPAND;
1131                         
1132                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1133                         return ADT_NLA_EVAL_OFF;
1134                         
1135                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1136                         *neg= 1;
1137                         return ADT_CURVES_NOT_VISIBLE;
1138                 
1139                 default: /* unsupported */
1140                         return 0;
1141         }
1142 }
1143
1144 /* get pointer to the setting */
1145 static void *acf_dscam_setting_ptr(bAnimListElem *ale, int setting, short *type)
1146 {
1147         Camera *ca= (Camera *)ale->data;
1148         
1149         /* clear extra return data first */
1150         *type= 0;
1151         
1152         switch (setting) {
1153                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1154                         GET_ACF_FLAG_PTR(ca->flag);
1155                         
1156                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1157                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1158                         if (ca->adt)
1159                                 GET_ACF_FLAG_PTR(ca->adt->flag)
1160                         else
1161                                 return NULL;
1162                 
1163                 default: /* unsupported */
1164                         return NULL;
1165         }
1166 }
1167
1168 /* camera expander type define */
1169 static bAnimChannelType ACF_DSCAM= 
1170 {
1171         acf_generic_dataexpand_backdrop,/* backdrop */
1172         acf_generic_indention_1,                /* indent level */
1173         acf_generic_basic_offset,               /* offset */
1174         
1175         acf_generic_idblock_name,               /* name */
1176         acf_dscam_icon,                                 /* icon */
1177         
1178         acf_generic_dataexpand_setting_valid,   /* has setting */
1179         acf_dscam_setting_flag,                                 /* flag for setting */
1180         acf_dscam_setting_ptr                                   /* pointer for setting */
1181 };
1182
1183 /* Curve Expander  ------------------------------------------- */
1184
1185 // TODO: just get this from RNA?
1186 static int acf_dscur_icon(bAnimListElem *ale)
1187 {
1188         return ICON_CURVE_DATA;
1189 }
1190
1191 /* get the appropriate flag(s) for the setting when it is valid  */
1192 static int acf_dscur_setting_flag(int setting, short *neg)
1193 {
1194         /* clear extra return data first */
1195         *neg= 0;
1196         
1197         switch (setting) {
1198                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1199                         return CU_DS_EXPAND;
1200                         
1201                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1202                         return ADT_NLA_EVAL_OFF;
1203                         
1204                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1205                         *neg= 1;
1206                         return ADT_CURVES_NOT_VISIBLE;
1207                 
1208                 default: /* unsupported */
1209                         return 0;
1210         }
1211 }
1212
1213 /* get pointer to the setting */
1214 static void *acf_dscur_setting_ptr(bAnimListElem *ale, int setting, short *type)
1215 {
1216         Curve *cu= (Curve *)ale->data;
1217         
1218         /* clear extra return data first */
1219         *type= 0;
1220         
1221         switch (setting) {
1222                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1223                         GET_ACF_FLAG_PTR(cu->flag);
1224                         
1225                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1226                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1227                         if (cu->adt)
1228                                 GET_ACF_FLAG_PTR(cu->adt->flag)
1229                         else
1230                                 return NULL;
1231                 
1232                 default: /* unsupported */
1233                         return NULL;
1234         }
1235 }
1236
1237 /* curve expander type define */
1238 static bAnimChannelType ACF_DSCUR= 
1239 {
1240         acf_generic_dataexpand_backdrop,/* backdrop */
1241         acf_generic_indention_1,                /* indent level */
1242         acf_generic_basic_offset,               /* offset */
1243         
1244         acf_generic_idblock_name,               /* name */
1245         acf_dscur_icon,                                 /* icon */
1246         
1247         acf_generic_dataexpand_setting_valid,   /* has setting */
1248         acf_dscur_setting_flag,                                 /* flag for setting */
1249         acf_dscur_setting_ptr                                   /* pointer for setting */
1250 };
1251
1252 /* Shape Key Expander  ------------------------------------------- */
1253
1254 // TODO: just get this from RNA?
1255 static int acf_dsskey_icon(bAnimListElem *ale)
1256 {
1257         return ICON_SHAPEKEY_DATA;
1258 }
1259
1260 /* get the appropriate flag(s) for the setting when it is valid  */
1261 static int acf_dsskey_setting_flag(int setting, short *neg)
1262 {
1263         /* clear extra return data first */
1264         *neg= 0;
1265         
1266         switch (setting) {
1267                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1268                         return KEYBLOCK_DS_EXPAND;
1269                         
1270                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1271                         return ADT_NLA_EVAL_OFF;
1272                         
1273                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1274                         *neg= 1;
1275                         return ADT_CURVES_NOT_VISIBLE;
1276                 
1277                 default: /* unsupported */
1278                         return 0;
1279         }
1280 }
1281
1282 /* get pointer to the setting */
1283 static void *acf_dsskey_setting_ptr(bAnimListElem *ale, int setting, short *type)
1284 {
1285         Key *key= (Key *)ale->data;
1286         
1287         /* clear extra return data first */
1288         *type= 0;
1289         
1290         switch (setting) {
1291                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1292                         GET_ACF_FLAG_PTR(key->flag);
1293                         
1294                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1295                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1296                         if (key->adt)
1297                                 GET_ACF_FLAG_PTR(key->adt->flag)
1298                         else
1299                                 return NULL;
1300                 
1301                 default: /* unsupported */
1302                         return NULL;
1303         }
1304 }
1305
1306 /* shapekey expander type define */
1307 static bAnimChannelType ACF_DSSKEY= 
1308 {
1309         acf_generic_dataexpand_backdrop,/* backdrop */
1310         acf_generic_indention_1,                /* indent level */
1311         acf_generic_basic_offset,               /* offset */
1312         
1313         acf_generic_idblock_name,               /* name */
1314         acf_dsskey_icon,                                /* icon */
1315         
1316         acf_generic_dataexpand_setting_valid,   /* has setting */
1317         acf_dsskey_setting_flag,                                /* flag for setting */
1318         acf_dsskey_setting_ptr                                  /* pointer for setting */
1319 };
1320
1321 /* World Expander  ------------------------------------------- */
1322
1323 // TODO: just get this from RNA?
1324 static int acf_dswor_icon(bAnimListElem *ale)
1325 {
1326         return ICON_WORLD_DATA;
1327 }
1328
1329 /* get the appropriate flag(s) for the setting when it is valid  */
1330 static int acf_dswor_setting_flag(int setting, short *neg)
1331 {
1332         /* clear extra return data first */
1333         *neg= 0;
1334         
1335         switch (setting) {
1336                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1337                         return WO_DS_EXPAND;
1338                         
1339                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1340                         return ADT_NLA_EVAL_OFF;
1341                         
1342                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1343                         *neg= 1;
1344                         return ADT_CURVES_NOT_VISIBLE;
1345                 
1346                 default: /* unsupported */
1347                         return 0;
1348         }
1349 }
1350
1351 /* get pointer to the setting */
1352 static void *acf_dswor_setting_ptr(bAnimListElem *ale, int setting, short *type)
1353 {
1354         World *wo= (World *)ale->data;
1355         
1356         /* clear extra return data first */
1357         *type= 0;
1358         
1359         switch (setting) {
1360                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1361                         GET_ACF_FLAG_PTR(wo->flag);
1362                         
1363                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1364                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1365                         if (wo->adt)
1366                                 GET_ACF_FLAG_PTR(wo->adt->flag)
1367                         else
1368                                 return NULL;
1369                 
1370                 default: /* unsupported */
1371                         return NULL;
1372         }
1373 }
1374
1375 /* world expander type define */
1376 static bAnimChannelType ACF_DSWOR= 
1377 {
1378         acf_generic_dataexpand_backdrop,/* backdrop */
1379         acf_generic_indention_1,                /* indent level */
1380         acf_generic_basic_offset,               /* offset */
1381         
1382         acf_generic_idblock_name,               /* name */
1383         acf_dswor_icon,                                 /* icon */
1384         
1385         acf_generic_dataexpand_setting_valid,   /* has setting */
1386         acf_dswor_setting_flag,                                 /* flag for setting */
1387         acf_dswor_setting_ptr                                   /* pointer for setting */
1388 };
1389
1390 /* Particle Expander  ------------------------------------------- */
1391
1392 // TODO: just get this from RNA?
1393 static int acf_dspart_icon(bAnimListElem *ale)
1394 {
1395         return ICON_PARTICLE_DATA;
1396 }
1397
1398 /* get the appropriate flag(s) for the setting when it is valid  */
1399 static int acf_dspart_setting_flag(int setting, short *neg)
1400 {
1401         /* clear extra return data first */
1402         *neg= 0;
1403         
1404         switch (setting) {
1405                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1406                         return PART_DS_EXPAND;
1407                         
1408                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1409                         return ADT_NLA_EVAL_OFF;
1410                         
1411                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1412                         *neg= 1;
1413                         return ADT_CURVES_NOT_VISIBLE;
1414                 
1415                 default: /* unsupported */
1416                         return 0;
1417         }
1418 }
1419
1420 /* get pointer to the setting */
1421 static void *acf_dspart_setting_ptr(bAnimListElem *ale, int setting, short *type)
1422 {
1423         ParticleSettings *part= (ParticleSettings *)ale->data;
1424         
1425         /* clear extra return data first */
1426         *type= 0;
1427         
1428         switch (setting) {
1429                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1430                         GET_ACF_FLAG_PTR(part->flag);
1431                         
1432                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1433                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1434                         if (part->adt)
1435                                 GET_ACF_FLAG_PTR(part->adt->flag)
1436                         else
1437                                 return NULL;
1438                 
1439                 default: /* unsupported */
1440                         return NULL;
1441         }
1442 }
1443
1444 /* particle expander type define */
1445 static bAnimChannelType ACF_DSPART= 
1446 {
1447         acf_generic_dataexpand_backdrop,/* backdrop */
1448         acf_generic_indention_1,                /* indent level */
1449         acf_generic_basic_offset,               /* offset */
1450         
1451         acf_generic_idblock_name,               /* name */
1452         acf_dspart_icon,                                /* icon */
1453         
1454         acf_generic_dataexpand_setting_valid,   /* has setting */
1455         acf_dspart_setting_flag,                                /* flag for setting */
1456         acf_dspart_setting_ptr                                  /* pointer for setting */
1457 };
1458
1459 /* MetaBall Expander  ------------------------------------------- */
1460
1461 // TODO: just get this from RNA?
1462 static int acf_dsmball_icon(bAnimListElem *ale)
1463 {
1464         return ICON_META_DATA;
1465 }
1466
1467 /* get the appropriate flag(s) for the setting when it is valid  */
1468 static int acf_dsmball_setting_flag(int setting, short *neg)
1469 {
1470         /* clear extra return data first */
1471         *neg= 0;
1472         
1473         switch (setting) {
1474                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1475                         return MB_DS_EXPAND;
1476                         
1477                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1478                         return ADT_NLA_EVAL_OFF;
1479                         
1480                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1481                         *neg= 1;
1482                         return ADT_CURVES_NOT_VISIBLE;
1483                 
1484                 default: /* unsupported */
1485                         return 0;
1486         }
1487 }
1488
1489 /* get pointer to the setting */
1490 static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *type)
1491 {
1492         MetaBall *mb= (MetaBall *)ale->data;
1493         
1494         /* clear extra return data first */
1495         *type= 0;
1496         
1497         switch (setting) {
1498                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1499                         GET_ACF_FLAG_PTR(mb->flag);
1500                         
1501                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1502                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1503                         if (mb->adt)
1504                                 GET_ACF_FLAG_PTR(mb->adt->flag)
1505                         else
1506                                 return NULL;
1507                 
1508                 default: /* unsupported */
1509                         return NULL;
1510         }
1511 }
1512
1513 /* metaball expander type define */
1514 static bAnimChannelType ACF_DSMBALL= 
1515 {
1516         acf_generic_dataexpand_backdrop,/* backdrop */
1517         acf_generic_indention_1,                /* indent level */
1518         acf_generic_basic_offset,               /* offset */
1519         
1520         acf_generic_idblock_name,               /* name */
1521         acf_dsmball_icon,                               /* icon */
1522         
1523         acf_generic_dataexpand_setting_valid,   /* has setting */
1524         acf_dsmball_setting_flag,                               /* flag for setting */
1525         acf_dsmball_setting_ptr                                 /* pointer for setting */
1526 };
1527
1528 /* ShapeKey Entry  ------------------------------------------- */
1529 // XXX ... this is currently obsolete...
1530
1531 #if 0
1532 static void dummy_olddraw_shapekeys ()
1533 {
1534         case ANIMTYPE_SHAPEKEY: /* shapekey channel */
1535         {
1536                 KeyBlock *kb = (KeyBlock *)ale->data;
1537                 
1538                 indent = 0;
1539                 special = -1;
1540                 
1541                 offset= (ale->id) ? 21 : 0;
1542                 
1543                 if (kb->name[0] == '\0')
1544                         sprintf(name, "Key %d", ale->index);
1545                 else
1546                         strcpy(name, kb->name);
1547         }
1548                 break;
1549 }
1550 #endif
1551
1552 /* Grease Pencil entries  ------------------------------------------- */
1553 // XXX ... this is currently not restored yet
1554
1555 #if 0
1556 static void dummy_olddraw_gpencil ()
1557 {
1558         /* determine what needs to be drawn */
1559         switch (ale->type) {
1560                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
1561                 {
1562                         bGPdata *gpd = (bGPdata *)ale->data;
1563                         ScrArea *sa = (ScrArea *)ale->owner;
1564                         
1565                         indent = 0;
1566                         group= 3;
1567                         
1568                         /* only show expand if there are any channels */
1569                         if (gpd->layers.first) {
1570                                 if (gpd->flag & GP_DATA_EXPAND)
1571                                         expand = ICON_TRIA_DOWN;
1572                                 else
1573                                         expand = ICON_TRIA_RIGHT;
1574                         }
1575                         
1576                         switch (sa->spacetype) {
1577                                 case SPACE_VIEW3D:
1578                                 {
1579                                         /* this shouldn't cause any overflow... */
1580                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
1581                                         strcpy(name, "3dView");
1582                                         special= ICON_VIEW3D;
1583                                 }
1584                                         break;
1585                                 case SPACE_NODE:
1586                                 {
1587                                         SpaceNode *snode= sa->spacedata.first;
1588                                         char treetype[12];
1589                                         
1590                                         if (snode->treetype == 1)
1591                                                 strcpy(treetype, "Composite");
1592                                         else
1593                                                 strcpy(treetype, "Material");
1594                                         sprintf(name, "Nodes:%s", treetype);
1595                                         
1596                                         special= ICON_NODE;
1597                                 }
1598                                         break;
1599                                 case SPACE_SEQ:
1600                                 {
1601                                         SpaceSeq *sseq= sa->spacedata.first;
1602                                         char imgpreview[10];
1603                                         
1604                                         switch (sseq->mainb) {
1605                                                 case 1:         sprintf(imgpreview, "Image...");        break;
1606                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
1607                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
1608                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
1609                                                 
1610                                                 default:        sprintf(imgpreview, "Sequence");        break;
1611                                         }
1612                                         sprintf(name, "Sequencer:%s", imgpreview);
1613                                         
1614                                         special= ICON_SEQUENCE;
1615                                 }
1616                                         break;
1617                                 case SPACE_IMAGE:
1618                                 {
1619                                         SpaceImage *sima= sa->spacedata.first;
1620                                         
1621                                         if (sima->image)
1622                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
1623                                         else
1624                                                 strcpy(name, "Image:<None>");
1625                                                 
1626                                         special= ICON_IMAGE_COL;
1627                                 }
1628                                         break;
1629                                 
1630                                 default:
1631                                 {
1632                                         sprintf(name, "<Unknown GP-Data Source>");
1633                                         special= -1;
1634                                 }
1635                                         break;
1636                         }
1637                 }
1638                         break;
1639                 case ANIMTYPE_GPLAYER: /* gpencil layer */
1640                 {
1641                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
1642                         
1643                         indent = 0;
1644                         special = -1;
1645                         expand = -1;
1646                         group = 1;
1647                         
1648                         if (EDITABLE_GPL(gpl))
1649                                 protect = ICON_UNLOCKED;
1650                         else
1651                                 protect = ICON_LOCKED;
1652                                 
1653                         if (gpl->flag & GP_LAYER_HIDE)
1654                                 mute = ICON_MUTE_IPO_ON;
1655                         else
1656                                 mute = ICON_MUTE_IPO_OFF;
1657                         
1658                         sel = SEL_GPL(gpl);
1659                         BLI_snprintf(name, 32, gpl->info);
1660                 }
1661                         break;
1662         }       
1663         
1664         if (group == 3) {
1665                 /* only for gp-data channels */
1666                 UI_ThemeColorShade(TH_GROUP, 20);
1667                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
1668                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
1669         }
1670 }
1671 #endif
1672
1673 /* *********************************************** */
1674 /* Type Registration and General Access */
1675
1676 /* These globals only ever get directly accessed in this file */
1677 static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES];
1678 static short ACF_INIT= 1; /* when non-zero, the list needs to be updated */
1679
1680 /* Initialise type info definitions */
1681 void ANIM_init_channel_typeinfo_data (void)
1682 {
1683         int type= 0;
1684         
1685         /* start initialising if necessary... */
1686         if (ACF_INIT) {
1687                 ACF_INIT= 0;
1688                 
1689                 animchannelTypeInfo[type++]= NULL;                              /* None */
1690                 animchannelTypeInfo[type++]= NULL;                              /* AnimData */
1691                 animchannelTypeInfo[type++]= NULL;                              /* Special */
1692                 
1693                 animchannelTypeInfo[type++]= &ACF_SCENE;                /* Scene */
1694                 animchannelTypeInfo[type++]= &ACF_OBJECT;               /* Object */
1695                 animchannelTypeInfo[type++]= &ACF_GROUP;                /* Group */
1696                 animchannelTypeInfo[type++]= &ACF_FCURVE;               /* F-Curve */
1697                 
1698                 animchannelTypeInfo[type++]= &ACF_FILLACTD;     /* Object Action Expander */
1699                 animchannelTypeInfo[type++]= &ACF_FILLDRIVERS;  /* Drivers Expander */
1700                 animchannelTypeInfo[type++]= &ACF_FILLMATD;     /* Materials Expander */
1701                 animchannelTypeInfo[type++]= &ACF_FILLPARTD;    /* Particles Expander */
1702                 
1703                 animchannelTypeInfo[type++]= &ACF_DSMAT;                /* Material Channel */
1704                 animchannelTypeInfo[type++]= &ACF_DSLAM;                /* Lamp Channel */
1705                 animchannelTypeInfo[type++]= &ACF_DSCAM;                /* Camera Channel */
1706                 animchannelTypeInfo[type++]= &ACF_DSCUR;                /* Curve Channel */
1707                 animchannelTypeInfo[type++]= &ACF_DSSKEY;               /* ShapeKey Channel */
1708                 animchannelTypeInfo[type++]= &ACF_DSWOR;                /* World Channel */
1709                 animchannelTypeInfo[type++]= &ACF_DSPART;               /* Particle Channel */
1710                 animchannelTypeInfo[type++]= &ACF_DSMBALL;              /* MetaBall Channel */
1711                 
1712                 animchannelTypeInfo[type++]= NULL;                              /* ShapeKey */ // XXX this is no longer used for now...
1713                 
1714                         // XXX not restored yet
1715                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Datablock */ 
1716                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Layer */ 
1717                 
1718                         // TODO: these types still need to be implemented!!!
1719                         // probably need a few extra flags for these special cases...
1720                 animchannelTypeInfo[type++]= NULL;                              /* NLA Track */ 
1721                 animchannelTypeInfo[type++]= NULL;                              /* NLA Action */ 
1722         }
1723
1724
1725 /* Get type info from given channel type */
1726 bAnimChannelType *ANIM_channel_get_typeinfo (bAnimListElem *ale)
1727 {
1728         /* santiy checks */
1729         if (ale == NULL)
1730                 return NULL;
1731                 
1732         /* init the typeinfo if not available yet... */
1733         ANIM_init_channel_typeinfo_data();
1734         
1735         /* check if type is in bounds... */
1736         if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES))
1737                 return animchannelTypeInfo[ale->type];
1738         else
1739                 return NULL;
1740 }
1741
1742 /* --------------------------- */
1743
1744 /* Check if some setting for a channel is enabled 
1745  * Returns: 1 = On, 0 = Off, -1 = Invalid
1746  */
1747 short ANIM_channel_setting_get (bAnimContext *ac, bAnimListElem *ale, int setting)
1748 {
1749         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
1750         
1751         /* 1) check that the setting exists for the current context */
1752         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
1753         {
1754                 /* 2) get pointer to check for flag in, and the flag to check for */
1755                 short negflag, ptrsize;
1756                 int flag;
1757                 void *ptr;
1758                 
1759                 flag= acf->setting_flag(setting, &negflag);
1760                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
1761                 
1762                 /* check if flag is enabled */
1763                 if (ptr && flag) {
1764                         switch (ptrsize) {
1765                                 case sizeof(int):       /* integer pointer for setting */
1766                                 {
1767                                         int *val= (int *)ptr;
1768                                         
1769                                         if (negflag)
1770                                                 return ((*val) & flag) == 0;
1771                                         else
1772                                                 return ((*val) & flag) != 0;
1773                                 }
1774                                         break;
1775                                         
1776                                 case sizeof(short):     /* short pointer for setting */
1777                                 {
1778                                         short *val= (short *)ptr;
1779                                         
1780                                         if (negflag)
1781                                                 return ((*val) & flag) == 0;
1782                                         else
1783                                                 return ((*val) & flag) != 0;
1784                                 }
1785                                         break;
1786                                         
1787                                 case sizeof(char):      /* char pointer for setting */
1788                                 {
1789                                         char *val= (char *)ptr;
1790                                         
1791                                         if (negflag)
1792                                                 return ((*val) & flag) == 0;
1793                                         else
1794                                                 return ((*val) & flag) != 0;
1795                                 }
1796                                         break;
1797                         }
1798                 }
1799         }
1800         
1801         /* not found... */
1802         return -1;
1803 }       
1804
1805
1806 /* quick macro for use in ANIM_channel_setting_set - set flag for setting according the mode given */
1807 #define ACF_SETTING_SET(sval, sflag, smode) \
1808         {\
1809                 if (negflag) {\
1810                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
1811                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) &= ~(sflag); \
1812                         else                                                                    (sval) |= (sflag); \
1813                 } \
1814                 else {\
1815                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
1816                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) |= (sflag); \
1817                         else                                                                    (sval) &= ~(sflag); \
1818                 }\
1819         }
1820
1821 /* Change value of some setting for a channel 
1822  *      - setting: eAnimChannel_Settings
1823  *      - mode: eAnimChannels_SetFlag
1824  */
1825 void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting, short mode)
1826 {
1827         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
1828         
1829         /* 1) check that the setting exists for the current context */
1830         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
1831         {
1832                 /* 2) get pointer to check for flag in, and the flag to check for */
1833                 short negflag, ptrsize;
1834                 int flag;
1835                 void *ptr;
1836                 
1837                 flag= acf->setting_flag(setting, &negflag);
1838                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
1839                 
1840                 /* check if flag is enabled */
1841                 if (ptr && flag) {
1842                         switch (ptrsize) {
1843                                 case sizeof(int):       /* integer pointer for setting */
1844                                 {
1845                                         int *val= (int *)ptr;
1846                                         ACF_SETTING_SET(*val, flag, mode);
1847                                 }
1848                                         break;
1849                                         
1850                                 case sizeof(short):     /* short pointer for setting */
1851                                 {
1852                                         short *val= (short *)ptr;
1853                                         ACF_SETTING_SET(*val, flag, mode);
1854                                 }
1855                                         break;
1856                                         
1857                                 case sizeof(char):      /* char pointer for setting */
1858                                 {
1859                                         char *val= (char *)ptr;
1860                                         ACF_SETTING_SET(*val, flag, mode);
1861                                 }
1862                                         break;
1863                         }
1864                 }
1865         }
1866 }
1867
1868 /* --------------------------- */
1869
1870 // XXX hardcoded size of icons
1871 #define ICON_WIDTH              17
1872
1873 /* Draw the given channel */
1874 // TODO: make this use UI controls for the buttons
1875 void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
1876 {
1877         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
1878         View2D *v2d= &ac->ar->v2d;
1879         short selected, offset;
1880         float y, ymid, ytext;
1881         
1882         /* sanity checks - don't draw anything */
1883         if ELEM(NULL, acf, ale)
1884                 return;
1885         
1886         /* get initial offset */
1887         if (acf->get_offset)
1888                 offset= acf->get_offset(ac, ale);
1889         else
1890                 offset= 0;
1891                 
1892         /* calculate appropriate y-coordinates for icon buttons 
1893          *      7 is hardcoded factor for half-height of icons
1894          */
1895         y= (ymaxc - yminc)/2 + yminc;
1896         ymid= y - 7;
1897         /* y-coordinates for text is only 4 down from middle */
1898         ytext= y - 4;
1899         
1900         /* check if channel is selected */
1901         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
1902                 selected= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
1903         else
1904                 selected= 0;
1905                 
1906         /* set blending again, as may not be set in previous step */
1907         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1908         glEnable(GL_BLEND);
1909         
1910         /* step 1) draw backdrop ...........................................  */
1911         if (acf->draw_backdrop)
1912                 acf->draw_backdrop(ac, ale, yminc, ymaxc);
1913                 
1914         /* step 2) draw expand widget ....................................... */
1915         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
1916                 /* just skip - drawn as widget now */
1917                 offset += ICON_WIDTH; 
1918         }
1919                 
1920         /* step 3) draw icon ............................................... */
1921         if (acf->icon) {
1922                 UI_icon_draw(offset, ymid, acf->icon(ale));
1923                 offset += ICON_WIDTH; 
1924         }
1925                 
1926         /* step 4) draw special toggles  .................................
1927          *      - in Graph Editor, checkboxes for visibility in curves area
1928          *      - in NLA Editor, glowing dots for solo/not solo...
1929          */
1930         if (ac->sa) {
1931                 if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
1932                         /* for F-Curves, draw color-preview of curve behind checkbox */
1933                         if (ale->type == ANIMTYPE_FCURVE) {
1934                                 FCurve *fcu= (FCurve *)ale->data;
1935                                 
1936                                 /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever 
1937                                  * color the curve has stored 
1938                                  */
1939                                 glColor3fv(fcu->color);
1940                                 
1941                                 /* just a solid color rect
1942                                  *      hardcoded 17 pixels width is slightly wider than icon width, so that 
1943                                  *      there's a slight border around it 
1944                                  */
1945                                 glRectf(offset, yminc, offset+17, ymaxc);
1946                         }
1947                         
1948                         /* icon is drawn as widget now... */
1949                         offset += ICON_WIDTH; 
1950                 }
1951                 else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
1952                         /* just skip - drawn as widget now */
1953                         offset += ICON_WIDTH; 
1954                 }
1955         }
1956         
1957         /* step 5) draw name ............................................... */
1958         if (acf->name) {
1959                 char name[256]; /* hopefully this will be enough! */
1960                 
1961                 /* set text color */
1962                 if (selected)
1963                         UI_ThemeColor(TH_TEXT_HI);
1964                 else
1965                         UI_ThemeColor(TH_TEXT);
1966                         
1967                 /* get name */
1968                 acf->name(ale, name);
1969                 
1970                 offset += 3;
1971                 UI_DrawString(offset, ytext, name);
1972         }
1973         
1974         /* step 6) draw mute+protection toggles + (sliders) ....................... */
1975         /* reset offset - now goes from RHS of panel */
1976         offset = 0;
1977         
1978         // TODO: we need a mechanism of drawing over (and hiding) stuff from here...
1979         // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
1980         
1981         if (v2d) {
1982                 /* protect... */
1983                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
1984                         /* just skip - drawn as widget now */
1985                         offset += ICON_WIDTH;
1986                 }
1987                 /* mute... */
1988                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
1989                         /* just skip - drawn as widget now */
1990                         offset += ICON_WIDTH;
1991                 }
1992         }
1993 }
1994
1995 /* ------------------ */
1996
1997 /* callback for widget settings - send notifiers */
1998 static void achannel_setting_widget_cb(bContext *C, void *poin, void *poin2)
1999 {
2000         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2001 }
2002
2003 /* Draw a widget for some setting */
2004 static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting)
2005 {
2006         short negflag, ptrsize, enabled, butType;
2007         int flag, icon;
2008         void *ptr;
2009         char *tooltip;
2010         uiBut *but = NULL;
2011         
2012         /* get the flag and the pointer to that flag */
2013         flag= acf->setting_flag(setting, &negflag);
2014         ptr= acf->setting_ptr(ale, setting, &ptrsize);
2015         enabled= ANIM_channel_setting_get(ac, ale, setting);
2016         
2017         /* get the base icon for the setting */
2018         switch (setting) {
2019                 case ACHANNEL_SETTING_VISIBLE:  /* visibility checkboxes */
2020                         //icon= ((enabled)? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT);
2021                         icon= ICON_CHECKBOX_DEHLT;
2022                         
2023                         if (ale->type == ANIMTYPE_FCURVE)
2024                                 tooltip= "F-Curve is visible in Graph Editor for editing.";
2025                         else
2026                                 tooltip= "F-Curve(s) are visible in Graph Editor for editing.";
2027                         break;
2028                         
2029                 case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
2030                         //icon= ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
2031                         icon= ICON_TRIA_RIGHT;
2032                         tooltip= "Make channels grouped under this channel visible.";
2033                         break;
2034                         
2035                 case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */
2036                         //icon= ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED);
2037                         icon= ICON_LAYER_USED;
2038                         tooltip= "NLA Track is the only one evaluated for the AnimData block it belongs to.";
2039                         break;
2040                 
2041                 /* --- */
2042                 
2043                 case ACHANNEL_SETTING_PROTECT: /* protected lock */
2044                         // TODO: what about when there's no protect needed?
2045                         //icon= ((enabled)? ICON_LOCKED : ICON_UNLOCKED);
2046                         icon= ICON_UNLOCKED;
2047                         tooltip= "Editability of keyframes for this channel.";
2048                         break;
2049                         
2050                 case ACHANNEL_SETTING_MUTE: /* muted eye */
2051                         //icon= ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
2052                         icon= ICON_MUTE_IPO_OFF;
2053                         
2054                         if (ale->type == ALE_FCURVE) 
2055                                 tooltip= "Does F-Curve contribute to result.";
2056                         else
2057                                 tooltip= "Do channels contribute to result.";
2058                         break;
2059                         
2060                 default:
2061                         tooltip= NULL;
2062                         icon= 0;
2063                         break;
2064         }
2065         
2066         /* type of button */
2067         if (negflag)
2068                 butType= ICONTOGN;
2069         else
2070                 butType= ICONTOG;
2071         
2072         /* draw button for setting */
2073         if (ptr && flag) {
2074                 switch (ptrsize) {
2075                         case sizeof(int):       /* integer pointer for setting */
2076                                 but= uiDefIconButBitI(block, butType, flag, 0, icon, 
2077                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2078                                 break;
2079                                 
2080                         case sizeof(short):     /* short pointer for setting */
2081                                 but= uiDefIconButBitS(block, butType, flag, 0, icon, 
2082                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2083                                 break;
2084                                 
2085                         case sizeof(char):      /* char pointer for setting */
2086                                 but= uiDefIconButBitC(block, butType, flag, 0, icon, 
2087                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2088                                 break;
2089                 }
2090                 
2091                 /* set call to send relevant notifiers */
2092                 // NOTE: for now, we only need to send 'edited' 
2093                 if (but)
2094                         uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
2095         }
2096 }
2097
2098 /* Draw UI widgets the given channel */
2099 // TODO: make this use UI controls for the buttons
2100 void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc)
2101 {
2102         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2103         View2D *v2d= &ac->ar->v2d;
2104         float y, ymid, ytext;
2105         short offset;
2106         
2107         /* sanity checks - don't draw anything */
2108         if ELEM3(NULL, acf, ale, block)
2109                 return;
2110         
2111         /* get initial offset */
2112         if (acf->get_offset)
2113                 offset= acf->get_offset(ac, ale);
2114         else
2115                 offset= 0;
2116                 
2117         /* calculate appropriate y-coordinates for icon buttons 
2118          *      7 is hardcoded factor for half-height of icons
2119          */
2120         y= (ymaxc - yminc)/2 + yminc;
2121         ymid= y - 7;
2122         /* y-coordinates for text is only 4 down from middle */
2123         ytext= y - 4;
2124         
2125         /* no button backdrop behind icons */
2126         uiBlockSetEmboss(block, UI_EMBOSSN);
2127         
2128         /* step 1) draw expand widget ....................................... */
2129         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
2130                 draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_EXPAND);
2131                 offset += ICON_WIDTH; 
2132         }
2133                 
2134         /* step 2) draw icon ............................................... */
2135         if (acf->icon) {
2136                 /* icon is not drawn here (not a widget) */
2137                 offset += ICON_WIDTH; 
2138         }
2139                 
2140         /* step 3) draw special toggles  .................................
2141          *      - in Graph Editor, checkboxes for visibility in curves area
2142          *      - in NLA Editor, glowing dots for solo/not solo...
2143          */
2144         if (ac->sa) {
2145                 if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
2146                         /* visibility toggle  */
2147                         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
2148                         offset += ICON_WIDTH; 
2149                 }
2150                 else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
2151                         /* 'solo' setting for NLA Tracks */
2152                         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
2153                         offset += ICON_WIDTH; 
2154                 }
2155         }
2156         
2157         /* step 4) draw text... */
2158         /* NOTE: this is not done here, since nothing to be clicked on... */
2159         
2160         /* step 5) draw mute+protection toggles + (sliders) ....................... */
2161         /* reset offset - now goes from RHS of panel */
2162         offset = 0;
2163         
2164         // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
2165         
2166         if (v2d) {
2167                 /* protect... */
2168                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
2169                         offset += ICON_WIDTH; 
2170                         draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_PROTECT);
2171                 }
2172                 /* mute... */
2173                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
2174                         offset += ICON_WIDTH;
2175                         draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_MUTE);
2176                 }
2177         }
2178 }
2179
2180 /* *********************************************** */