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