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