ShapeKey Editor (sub-mode of DopeSheet Editor)
[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 KEY_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
1741 /* name for ShapeKey */
1742 static void acf_shapekey_name(bAnimListElem *ale, char *name)
1743 {
1744         KeyBlock *kb= (KeyBlock *)ale->data;
1745         
1746         /* just copy the name... */
1747         if (kb && name) {
1748                 /* if the KeyBlock had a name, use it, otherwise use the index */
1749                 if (kb->name[0])
1750                         strcpy(name, kb->name);
1751                 else
1752                         sprintf(name, "Key %d", ale->index);
1753         }
1754 }
1755
1756 /* check if some setting exists for this channel */
1757 static short acf_shapekey_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
1758 {
1759         switch (setting) {
1760                 case ACHANNEL_SETTING_SELECT: /* selected */
1761                 case ACHANNEL_SETTING_MUTE: /* muted */
1762                 case ACHANNEL_SETTING_PROTECT: /* protected */
1763                         return 1;
1764                         
1765                 /* nothing else is supported */
1766                 default:
1767                         return 0;
1768         }
1769 }
1770
1771 /* get the appropriate flag(s) for the setting when it is valid  */
1772 static int acf_shapekey_setting_flag(int setting, short *neg)
1773 {
1774         /* clear extra return data first */
1775         *neg= 0;
1776         
1777         switch (setting) {
1778                 case ACHANNEL_SETTING_MUTE: /* mute */
1779                         return KEYBLOCK_MUTE;
1780                 
1781                 case ACHANNEL_SETTING_SELECT: /* selected */
1782                         return KEYBLOCK_SEL;
1783                 
1784                 case ACHANNEL_SETTING_PROTECT: /* locked */
1785                         return KEYBLOCK_LOCKED;
1786                 
1787                 default: /* unsupported */
1788                         return 0;
1789         }
1790 }
1791
1792 /* get pointer to the setting */
1793 static void *acf_shapekey_setting_ptr(bAnimListElem *ale, int setting, short *type)
1794 {
1795         KeyBlock *kb= (KeyBlock *)ale->data;
1796         
1797         /* clear extra return data first */
1798         *type= 0;
1799         
1800         switch (setting) {
1801                 case ACHANNEL_SETTING_SELECT: /* selected */
1802                 case ACHANNEL_SETTING_MUTE: /* muted */
1803                 case ACHANNEL_SETTING_PROTECT: /* protected */
1804                         GET_ACF_FLAG_PTR(kb->flag)
1805                 
1806                 default: /* unsupported */
1807                         return NULL;
1808         }
1809 }
1810
1811 /* shapekey expander type define */
1812 static bAnimChannelType ACF_SHAPEKEY= 
1813 {
1814         acf_generic_channel_backdrop,   /* backdrop */
1815         acf_generic_indention_0,                /* indent level */
1816         acf_generic_basic_offset,               /* offset */
1817         
1818         acf_shapekey_name,                              /* name */
1819         NULL,                                                   /* icon */
1820         
1821         acf_shapekey_setting_valid,             /* has setting */
1822         acf_shapekey_setting_flag,              /* flag for setting */
1823         acf_shapekey_setting_ptr                /* pointer for setting */
1824 };
1825
1826 /* Grease Pencil entries  ------------------------------------------- */
1827 // XXX ... this is currently not restored yet
1828
1829 #if 0
1830 static void dummy_olddraw_gpencil ()
1831 {
1832         /* determine what needs to be drawn */
1833         switch (ale->type) {
1834                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
1835                 {
1836                         bGPdata *gpd = (bGPdata *)ale->data;
1837                         ScrArea *sa = (ScrArea *)ale->owner;
1838                         
1839                         indent = 0;
1840                         group= 3;
1841                         
1842                         /* only show expand if there are any channels */
1843                         if (gpd->layers.first) {
1844                                 if (gpd->flag & GP_DATA_EXPAND)
1845                                         expand = ICON_TRIA_DOWN;
1846                                 else
1847                                         expand = ICON_TRIA_RIGHT;
1848                         }
1849                         
1850                         switch (sa->spacetype) {
1851                                 case SPACE_VIEW3D:
1852                                 {
1853                                         /* this shouldn't cause any overflow... */
1854                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
1855                                         strcpy(name, "3dView");
1856                                         special= ICON_VIEW3D;
1857                                 }
1858                                         break;
1859                                 case SPACE_NODE:
1860                                 {
1861                                         SpaceNode *snode= sa->spacedata.first;
1862                                         char treetype[12];
1863                                         
1864                                         if (snode->treetype == 1)
1865                                                 strcpy(treetype, "Composite");
1866                                         else
1867                                                 strcpy(treetype, "Material");
1868                                         sprintf(name, "Nodes:%s", treetype);
1869                                         
1870                                         special= ICON_NODE;
1871                                 }
1872                                         break;
1873                                 case SPACE_SEQ:
1874                                 {
1875                                         SpaceSeq *sseq= sa->spacedata.first;
1876                                         char imgpreview[10];
1877                                         
1878                                         switch (sseq->mainb) {
1879                                                 case 1:         sprintf(imgpreview, "Image...");        break;
1880                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
1881                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
1882                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
1883                                                 
1884                                                 default:        sprintf(imgpreview, "Sequence");        break;
1885                                         }
1886                                         sprintf(name, "Sequencer:%s", imgpreview);
1887                                         
1888                                         special= ICON_SEQUENCE;
1889                                 }
1890                                         break;
1891                                 case SPACE_IMAGE:
1892                                 {
1893                                         SpaceImage *sima= sa->spacedata.first;
1894                                         
1895                                         if (sima->image)
1896                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
1897                                         else
1898                                                 strcpy(name, "Image:<None>");
1899                                                 
1900                                         special= ICON_IMAGE_COL;
1901                                 }
1902                                         break;
1903                                 
1904                                 default:
1905                                 {
1906                                         sprintf(name, "<Unknown GP-Data Source>");
1907                                         special= -1;
1908                                 }
1909                                         break;
1910                         }
1911                 }
1912                         break;
1913                 case ANIMTYPE_GPLAYER: /* gpencil layer */
1914                 {
1915                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
1916                         
1917                         indent = 0;
1918                         special = -1;
1919                         expand = -1;
1920                         group = 1;
1921                         
1922                         if (EDITABLE_GPL(gpl))
1923                                 protect = ICON_UNLOCKED;
1924                         else
1925                                 protect = ICON_LOCKED;
1926                                 
1927                         if (gpl->flag & GP_LAYER_HIDE)
1928                                 mute = ICON_MUTE_IPO_ON;
1929                         else
1930                                 mute = ICON_MUTE_IPO_OFF;
1931                         
1932                         sel = SEL_GPL(gpl);
1933                         BLI_snprintf(name, 32, gpl->info);
1934                 }
1935                         break;
1936         }       
1937         
1938         if (group == 3) {
1939                 /* only for gp-data channels */
1940                 UI_ThemeColorShade(TH_GROUP, 20);
1941                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
1942                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
1943         }
1944 }
1945 #endif
1946
1947 /* *********************************************** */
1948 /* Type Registration and General Access */
1949
1950 /* These globals only ever get directly accessed in this file */
1951 static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES];
1952 static short ACF_INIT= 1; /* when non-zero, the list needs to be updated */
1953
1954 /* Initialise type info definitions */
1955 void ANIM_init_channel_typeinfo_data (void)
1956 {
1957         int type= 0;
1958         
1959         /* start initialising if necessary... */
1960         if (ACF_INIT) {
1961                 ACF_INIT= 0;
1962                 
1963                 animchannelTypeInfo[type++]= NULL;                              /* None */
1964                 animchannelTypeInfo[type++]= NULL;                              /* AnimData */
1965                 animchannelTypeInfo[type++]= NULL;                              /* Special */
1966                 
1967                 animchannelTypeInfo[type++]= &ACF_SUMMARY;              /* Motion Summary */
1968                 
1969                 animchannelTypeInfo[type++]= &ACF_SCENE;                /* Scene */
1970                 animchannelTypeInfo[type++]= &ACF_OBJECT;               /* Object */
1971                 animchannelTypeInfo[type++]= &ACF_GROUP;                /* Group */
1972                 animchannelTypeInfo[type++]= &ACF_FCURVE;               /* F-Curve */
1973                 
1974                 animchannelTypeInfo[type++]= &ACF_FILLACTD;     /* Object Action Expander */
1975                 animchannelTypeInfo[type++]= &ACF_FILLDRIVERS;  /* Drivers Expander */
1976                 animchannelTypeInfo[type++]= &ACF_FILLMATD;     /* Materials Expander */
1977                 animchannelTypeInfo[type++]= &ACF_FILLPARTD;    /* Particles Expander */
1978                 
1979                 animchannelTypeInfo[type++]= &ACF_DSMAT;                /* Material Channel */
1980                 animchannelTypeInfo[type++]= &ACF_DSLAM;                /* Lamp Channel */
1981                 animchannelTypeInfo[type++]= &ACF_DSCAM;                /* Camera Channel */
1982                 animchannelTypeInfo[type++]= &ACF_DSCUR;                /* Curve Channel */
1983                 animchannelTypeInfo[type++]= &ACF_DSSKEY;               /* ShapeKey Channel */
1984                 animchannelTypeInfo[type++]= &ACF_DSWOR;                /* World Channel */
1985                 animchannelTypeInfo[type++]= &ACF_DSPART;               /* Particle Channel */
1986                 animchannelTypeInfo[type++]= &ACF_DSMBALL;              /* MetaBall Channel */
1987                 animchannelTypeInfo[type++]= &ACF_DSARM;                /* Armature Channel */
1988                 
1989                 animchannelTypeInfo[type++]= &ACF_SHAPEKEY;             /* ShapeKey */
1990                 
1991                         // XXX not restored yet
1992                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Datablock */ 
1993                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Layer */ 
1994                 
1995                         // TODO: these types still need to be implemented!!!
1996                         // probably need a few extra flags for these special cases...
1997                 animchannelTypeInfo[type++]= NULL;                              /* NLA Track */ 
1998                 animchannelTypeInfo[type++]= NULL;                              /* NLA Action */ 
1999         }
2000
2001
2002 /* Get type info from given channel type */
2003 bAnimChannelType *ANIM_channel_get_typeinfo (bAnimListElem *ale)
2004 {
2005         /* santiy checks */
2006         if (ale == NULL)
2007                 return NULL;
2008                 
2009         /* init the typeinfo if not available yet... */
2010         ANIM_init_channel_typeinfo_data();
2011         
2012         /* check if type is in bounds... */
2013         if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES))
2014                 return animchannelTypeInfo[ale->type];
2015         else
2016                 return NULL;
2017 }
2018
2019 /* --------------------------- */
2020
2021 /* Check if some setting for a channel is enabled 
2022  * Returns: 1 = On, 0 = Off, -1 = Invalid
2023  */
2024 short ANIM_channel_setting_get (bAnimContext *ac, bAnimListElem *ale, int setting)
2025 {
2026         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2027         
2028         /* 1) check that the setting exists for the current context */
2029         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
2030         {
2031                 /* 2) get pointer to check for flag in, and the flag to check for */
2032                 short negflag, ptrsize;
2033                 int flag;
2034                 void *ptr;
2035                 
2036                 flag= acf->setting_flag(setting, &negflag);
2037                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
2038                 
2039                 /* check if flag is enabled */
2040                 if (ptr && flag) {
2041                         switch (ptrsize) {
2042                                 case sizeof(int):       /* integer pointer for setting */
2043                                 {
2044                                         int *val= (int *)ptr;
2045                                         
2046                                         if (negflag)
2047                                                 return ((*val) & flag) == 0;
2048                                         else
2049                                                 return ((*val) & flag) != 0;
2050                                 }
2051                                         break;
2052                                         
2053                                 case sizeof(short):     /* short pointer for setting */
2054                                 {
2055                                         short *val= (short *)ptr;
2056                                         
2057                                         if (negflag)
2058                                                 return ((*val) & flag) == 0;
2059                                         else
2060                                                 return ((*val) & flag) != 0;
2061                                 }
2062                                         break;
2063                                         
2064                                 case sizeof(char):      /* char pointer for setting */
2065                                 {
2066                                         char *val= (char *)ptr;
2067                                         
2068                                         if (negflag)
2069                                                 return ((*val) & flag) == 0;
2070                                         else
2071                                                 return ((*val) & flag) != 0;
2072                                 }
2073                                         break;
2074                         }
2075                 }
2076         }
2077         
2078         /* not found... */
2079         return -1;
2080 }       
2081
2082
2083 /* quick macro for use in ANIM_channel_setting_set - set flag for setting according the mode given */
2084 #define ACF_SETTING_SET(sval, sflag, smode) \
2085         {\
2086                 if (negflag) {\
2087                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
2088                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) &= ~(sflag); \
2089                         else                                                                    (sval) |= (sflag); \
2090                 } \
2091                 else {\
2092                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
2093                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) |= (sflag); \
2094                         else                                                                    (sval) &= ~(sflag); \
2095                 }\
2096         }
2097
2098 /* Change value of some setting for a channel 
2099  *      - setting: eAnimChannel_Settings
2100  *      - mode: eAnimChannels_SetFlag
2101  */
2102 void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting, short mode)
2103 {
2104         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2105         
2106         /* 1) check that the setting exists for the current context */
2107         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
2108         {
2109                 /* 2) get pointer to check for flag in, and the flag to check for */
2110                 short negflag, ptrsize;
2111                 int flag;
2112                 void *ptr;
2113                 
2114                 flag= acf->setting_flag(setting, &negflag);
2115                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
2116                 
2117                 /* check if flag is enabled */
2118                 if (ptr && flag) {
2119                         switch (ptrsize) {
2120                                 case sizeof(int):       /* integer pointer for setting */
2121                                 {
2122                                         int *val= (int *)ptr;
2123                                         ACF_SETTING_SET(*val, flag, mode);
2124                                 }
2125                                         break;
2126                                         
2127                                 case sizeof(short):     /* short pointer for setting */
2128                                 {
2129                                         short *val= (short *)ptr;
2130                                         ACF_SETTING_SET(*val, flag, mode);
2131                                 }
2132                                         break;
2133                                         
2134                                 case sizeof(char):      /* char pointer for setting */
2135                                 {
2136                                         char *val= (char *)ptr;
2137                                         ACF_SETTING_SET(*val, flag, mode);
2138                                 }
2139                                         break;
2140                         }
2141                 }
2142         }
2143 }
2144
2145 /* --------------------------- */
2146
2147 // XXX hardcoded size of icons
2148 #define ICON_WIDTH              17
2149 // XXX hardcoded width of sliders
2150 #define SLIDER_WIDTH    70
2151
2152 /* Draw the given channel */
2153 // TODO: make this use UI controls for the buttons
2154 void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
2155 {
2156         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2157         short selected, offset;
2158         float y, ymid, ytext;
2159         
2160         /* sanity checks - don't draw anything */
2161         if ELEM(NULL, acf, ale)
2162                 return;
2163         
2164         /* get initial offset */
2165         if (acf->get_offset)
2166                 offset= acf->get_offset(ac, ale);
2167         else
2168                 offset= 0;
2169                 
2170         /* calculate appropriate y-coordinates for icon buttons 
2171          *      7 is hardcoded factor for half-height of icons
2172          */
2173         y= (ymaxc - yminc)/2 + yminc;
2174         ymid= y - 7;
2175         /* y-coordinates for text is only 4 down from middle */
2176         ytext= y - 4;
2177         
2178         /* check if channel is selected */
2179         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
2180                 selected= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
2181         else
2182                 selected= 0;
2183                 
2184         /* set blending again, as may not be set in previous step */
2185         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2186         glEnable(GL_BLEND);
2187         
2188         /* step 1) draw backdrop ...........................................  */
2189         if (acf->draw_backdrop)
2190                 acf->draw_backdrop(ac, ale, yminc, ymaxc);
2191                 
2192         /* step 2) draw expand widget ....................................... */
2193         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
2194                 /* just skip - drawn as widget now */
2195                 offset += ICON_WIDTH; 
2196         }
2197                 
2198         /* step 3) draw icon ............................................... */
2199         if (acf->icon) {
2200                 UI_icon_draw(offset, ymid, acf->icon(ale));
2201                 offset += ICON_WIDTH; 
2202         }
2203                 
2204         /* step 4) draw special toggles  .................................
2205          *      - in Graph Editor, checkboxes for visibility in curves area
2206          *      - in NLA Editor, glowing dots for solo/not solo...
2207          */
2208         if (ac->sa) {
2209                 if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
2210                         /* for F-Curves, draw color-preview of curve behind checkbox */
2211                         if (ale->type == ANIMTYPE_FCURVE) {
2212                                 FCurve *fcu= (FCurve *)ale->data;
2213                                 
2214                                 /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever 
2215                                  * color the curve has stored 
2216                                  */
2217                                 glColor3fv(fcu->color);
2218                                 
2219                                 /* just a solid color rect
2220                                  *      hardcoded 17 pixels width is slightly wider than icon width, so that 
2221                                  *      there's a slight border around it 
2222                                  */
2223                                 glRectf(offset, yminc, offset+17, ymaxc);
2224                         }
2225                         
2226                         /* icon is drawn as widget now... */
2227                         offset += ICON_WIDTH; 
2228                 }
2229                 else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
2230                         /* just skip - drawn as widget now */
2231                         offset += ICON_WIDTH; 
2232                 }
2233         }
2234         
2235         /* step 5) draw name ............................................... */
2236         if (acf->name) {
2237                 char name[256]; /* hopefully this will be enough! */
2238                 
2239                 /* set text color */
2240                 if (selected)
2241                         UI_ThemeColor(TH_TEXT_HI);
2242                 else
2243                         UI_ThemeColor(TH_TEXT);
2244                         
2245                 /* get name */
2246                 acf->name(ale, name);
2247                 
2248                 offset += 3;
2249                 UI_DrawString(offset, ytext, name);
2250         }
2251 }
2252
2253 /* ------------------ */
2254
2255 /* callback for (normal) widget settings - send notifiers */
2256 static void achannel_setting_widget_cb(bContext *C, void *poin, void *poin2)
2257 {
2258         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2259 }
2260
2261 /* callback for widget sliders - insert keyframes */
2262 static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
2263 {
2264         ID *id= (ID *)id_poin;
2265         FCurve *fcu= (FCurve *)fcu_poin;
2266         
2267         Scene *scene= CTX_data_scene(C);
2268         PointerRNA id_ptr, ptr;
2269         PropertyRNA *prop;
2270         short flag=0, done=0;
2271         float cfra;
2272         
2273         /* get current frame */
2274         // NOTE: this will do for now...
2275         cfra= (float)CFRA;
2276         
2277         /* get flags for keyframing */
2278         if (IS_AUTOKEY_FLAG(INSERTNEEDED))
2279                 flag |= INSERTKEY_NEEDED;
2280         if (IS_AUTOKEY_FLAG(AUTOMATKEY))
2281                 flag |= INSERTKEY_MATRIX;
2282         if (IS_AUTOKEY_MODE(scene, EDITKEYS))
2283                 flag |= INSERTKEY_REPLACE;
2284         
2285         
2286         /* get RNA pointer, and resolve the path */
2287         RNA_id_pointer_create(id, &id_ptr);
2288         
2289         /* try to resolve the path stored in the F-Curve */
2290         if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) {
2291                 /* set the special 'replace' flag if on a keyframe */
2292                 if (fcurve_frame_has_keyframe(fcu, cfra, 0))
2293                         flag |= INSERTKEY_REPLACE;
2294                 
2295                 /* insert a keyframe for this F-Curve */
2296                 done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
2297                 
2298                 if (done)
2299                         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2300         }
2301 }
2302
2303 /* callback for shapekey widget sliders - insert keyframes */
2304 static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin)
2305 {
2306         Key *key= (Key *)key_poin;
2307         KeyBlock *kb= (KeyBlock *)kb_poin;
2308         char *rna_path= key_get_curValue_rnaPath(key, kb);
2309         
2310         Scene *scene= CTX_data_scene(C);
2311         PointerRNA id_ptr, ptr;
2312         PropertyRNA *prop;
2313         short flag=0, done=0;
2314         float cfra;
2315         
2316         /* get current frame */
2317         // NOTE: this will do for now...
2318         cfra= (float)CFRA;
2319         
2320         /* get flags for keyframing */
2321         if (IS_AUTOKEY_FLAG(INSERTNEEDED))
2322                 flag |= INSERTKEY_NEEDED;
2323         if (IS_AUTOKEY_FLAG(AUTOMATKEY))
2324                 flag |= INSERTKEY_MATRIX;
2325         if (IS_AUTOKEY_MODE(scene, EDITKEYS))
2326                 flag |= INSERTKEY_REPLACE;
2327         
2328         
2329         /* get RNA pointer, and resolve the path */
2330         RNA_id_pointer_create((ID *)key, &id_ptr);
2331         
2332         /* try to resolve the path stored in the F-Curve */
2333         if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
2334                 /* find or create new F-Curve */
2335                 // XXX is the group name for this ok?
2336                 bAction *act= verify_adt_action((ID *)key, 1);
2337                 FCurve *fcu= verify_fcurve(act, NULL, rna_path, 0, 1);
2338                 
2339                 /* set the special 'replace' flag if on a keyframe */
2340                 if (fcurve_frame_has_keyframe(fcu, cfra, 0))
2341                         flag |= INSERTKEY_REPLACE;
2342                 
2343                 /* insert a keyframe for this F-Curve */
2344                 done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
2345                 
2346                 if (done)
2347                         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2348         }
2349         
2350         /* free the path */
2351         if (rna_path)
2352                 MEM_freeN(rna_path);
2353 }
2354
2355 /* Draw a widget for some setting */
2356 static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting)
2357 {
2358         short negflag, ptrsize, enabled, butType;
2359         int flag, icon;
2360         void *ptr;
2361         char *tooltip;
2362         uiBut *but = NULL;
2363         
2364         /* get the flag and the pointer to that flag */
2365         flag= acf->setting_flag(setting, &negflag);
2366         ptr= acf->setting_ptr(ale, setting, &ptrsize);
2367         enabled= ANIM_channel_setting_get(ac, ale, setting);
2368         
2369         /* get the base icon for the setting */
2370         switch (setting) {
2371                 case ACHANNEL_SETTING_VISIBLE:  /* visibility checkboxes */
2372                         //icon= ((enabled)? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT);
2373                         icon= ICON_CHECKBOX_DEHLT;
2374                         
2375                         if (ale->type == ANIMTYPE_FCURVE)
2376                                 tooltip= "F-Curve is visible in Graph Editor for editing.";
2377                         else
2378                                 tooltip= "F-Curve(s) are visible in Graph Editor for editing.";
2379                         break;
2380                         
2381                 case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
2382                         //icon= ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
2383                         icon= ICON_TRIA_RIGHT;
2384                         tooltip= "Make channels grouped under this channel visible.";
2385                         break;
2386                         
2387                 case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */
2388                         //icon= ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED);
2389                         icon= ICON_LAYER_USED;
2390                         tooltip= "NLA Track is the only one evaluated for the AnimData block it belongs to.";
2391                         break;
2392                 
2393                 /* --- */
2394                 
2395                 case ACHANNEL_SETTING_PROTECT: /* protected lock */
2396                         // TODO: what about when there's no protect needed?
2397                         //icon= ((enabled)? ICON_LOCKED : ICON_UNLOCKED);
2398                         icon= ICON_UNLOCKED;
2399                         tooltip= "Editability of keyframes for this channel.";
2400                         break;
2401                         
2402                 case ACHANNEL_SETTING_MUTE: /* muted eye */
2403                         //icon= ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
2404                         icon= ICON_MUTE_IPO_OFF;
2405                         
2406                         if (ale->type == ALE_FCURVE) 
2407                                 tooltip= "Does F-Curve contribute to result.";
2408                         else
2409                                 tooltip= "Do channels contribute to result.";
2410                         break;
2411                         
2412                 default:
2413                         tooltip= NULL;
2414                         icon= 0;
2415                         break;
2416         }
2417         
2418         /* type of button */
2419         if (negflag)
2420                 butType= ICONTOGN;
2421         else
2422                 butType= ICONTOG;
2423         
2424         /* draw button for setting */
2425         if (ptr && flag) {
2426                 switch (ptrsize) {
2427                         case sizeof(int):       /* integer pointer for setting */
2428                                 but= uiDefIconButBitI(block, butType, flag, 0, icon, 
2429                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2430                                 break;
2431                                 
2432                         case sizeof(short):     /* short pointer for setting */
2433                                 but= uiDefIconButBitS(block, butType, flag, 0, icon, 
2434                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2435                                 break;
2436                                 
2437                         case sizeof(char):      /* char pointer for setting */
2438                                 but= uiDefIconButBitC(block, butType, flag, 0, icon, 
2439                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2440                                 break;
2441                 }
2442                 
2443                 /* set call to send relevant notifiers */
2444                 // NOTE: for now, we only need to send 'edited' 
2445                 if (but)
2446                         uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
2447         }
2448 }
2449
2450 /* Draw UI widgets the given channel */
2451 // TODO: make this use UI controls for the buttons
2452 void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc)
2453 {
2454         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2455         View2D *v2d= &ac->ar->v2d;
2456         float y, ymid, ytext;
2457         short offset;
2458         
2459         /* sanity checks - don't draw anything */
2460         if ELEM3(NULL, acf, ale, block)
2461                 return;
2462         
2463         /* get initial offset */
2464         if (acf->get_offset)
2465                 offset= acf->get_offset(ac, ale);
2466         else
2467                 offset= 0;
2468                 
2469         /* calculate appropriate y-coordinates for icon buttons 
2470          *      7 is hardcoded factor for half-height of icons
2471          */
2472         y= (ymaxc - yminc)/2 + yminc;
2473         ymid= y - 7;
2474         /* y-coordinates for text is only 4 down from middle */
2475         ytext= y - 4;
2476         
2477         /* no button backdrop behind icons */
2478         uiBlockSetEmboss(block, UI_EMBOSSN);
2479         
2480         /* step 1) draw expand widget ....................................... */
2481         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
2482                 draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_EXPAND);
2483                 offset += ICON_WIDTH; 
2484         }
2485                 
2486         /* step 2) draw icon ............................................... */
2487         if (acf->icon) {
2488                 /* icon is not drawn here (not a widget) */
2489                 offset += ICON_WIDTH; 
2490         }
2491                 
2492         /* step 3) draw special toggles  .................................
2493          *      - in Graph Editor, checkboxes for visibility in curves area
2494          *      - in NLA Editor, glowing dots for solo/not solo...
2495          */
2496         if (ac->sa) {
2497                 if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
2498                         /* visibility toggle  */
2499                         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
2500                         offset += ICON_WIDTH; 
2501                 }
2502                 else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
2503                         /* 'solo' setting for NLA Tracks */
2504                         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
2505                         offset += ICON_WIDTH; 
2506                 }
2507         }
2508         
2509         /* step 4) draw text... */
2510         /* NOTE: this is not done here, since nothing to be clicked on... */
2511         
2512         /* step 5) draw mute+protection toggles + (sliders) ....................... */
2513         /* reset offset - now goes from RHS of panel */
2514         offset = 0;
2515         
2516         // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
2517         
2518         if (v2d) {
2519                 short draw_sliders = 0;
2520                 
2521                 /* check if we need to show the sliders */
2522                 if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
2523                         switch (ac->spacetype) {
2524                                 case SPACE_ACTION:
2525                                 {
2526                                         SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
2527                                         draw_sliders= (saction->flag & SACTION_SLIDERS);
2528                                 }
2529                                         break;
2530                                 case SPACE_IPO:
2531                                 {
2532                                         SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
2533                                         draw_sliders= (sipo->flag & SIPO_SLIDERS);
2534                                 }
2535                                         break;
2536                         }
2537                 }
2538                 
2539                 /* check if there's enough space for the toggles if the sliders are drawn too */
2540                 if ( !(draw_sliders) || ((v2d->mask.xmax-v2d->mask.xmin) > ACHANNEL_BUTTON_WIDTH/2) ) {
2541                         /* protect... */
2542                         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
2543                                 offset += ICON_WIDTH; 
2544                                 draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_PROTECT);
2545                         }
2546                         /* mute... */
2547                         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
2548                                 offset += ICON_WIDTH;
2549                                 draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_MUTE);
2550                         }
2551                 }
2552                 
2553                 /* draw slider
2554                  *      - even if we can draw sliders for this view, we must also check that the channel-type supports them
2555                  *        (only only F-Curves really can support them for now)
2556                  *      - to make things easier, we use RNA-autobuts for this so that changes are reflected immediately, 
2557                  *        whereever they occurred. BUT, we don't use the layout engine, otherwise we'd get wrong alignment,
2558                  *        and wouldn't be able to auto-keyframe...
2559                  *      - slider should start before the toggles (if they're visible) to keep a clean line down the side
2560                  */
2561                 if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) {
2562                         /* adjust offset */
2563                         offset += SLIDER_WIDTH;
2564                         
2565                         /* need backdrop behind sliders... */
2566                         uiBlockSetEmboss(block, UI_EMBOSS);
2567                         
2568                         if (ale->id) { /* Slider using RNA Access -------------------- */
2569                                 PointerRNA id_ptr, ptr;
2570                                 PropertyRNA *prop;
2571                                 char *rna_path = NULL;
2572                                 int array_index = 0;
2573                                 short free_path = 0;
2574                                 
2575                                 /* get destination info */
2576                                 if (ale->type == ANIMTYPE_FCURVE) {
2577                                         FCurve *fcu= (FCurve *)ale->data;
2578                                         
2579                                         rna_path= fcu->rna_path;
2580                                         array_index= fcu->array_index;
2581                                 }
2582                                 else if (ale->type == ANIMTYPE_SHAPEKEY) {
2583                                         KeyBlock *kb= (KeyBlock *)ale->data;
2584                                         Key *key= (Key *)ale->id;
2585                                         
2586                                         rna_path= key_get_curValue_rnaPath(key, kb);
2587                                         free_path= 1;
2588                                 }
2589                                 
2590                                 /* only if RNA-Path found */
2591                                 if (rna_path) {
2592                                         /* get RNA pointer, and resolve the path */
2593                                         RNA_id_pointer_create(ale->id, &id_ptr);
2594                                         
2595                                         /* try to resolve the path */
2596                                         if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
2597                                                 uiBut *but;
2598                                                 
2599                                                 /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
2600                                                 but= uiDefAutoButR(block, &ptr, prop, array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
2601                                                 
2602                                                 /* assign keyframing function according to slider type */
2603                                                 if (ale->type == ANIMTYPE_SHAPEKEY)
2604                                                         uiButSetFunc(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
2605                                                 else
2606                                                         uiButSetFunc(but, achannel_setting_slider_cb, ale->id, ale->data);
2607                                         }
2608                                         
2609                                         /* free the path if necessary */
2610                                         if (free_path)
2611                                                 MEM_freeN(rna_path);
2612                                 }
2613                         }
2614                         else { /* Special Slider for stuff without RNA Access ---------- */
2615                                 // TODO: only implement this case when we really need it...
2616                         }
2617                 }
2618         }
2619 }
2620
2621 /* *********************************************** */