Animation Channels - Protect + Mute toggles flushing:
[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_math.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_mesh_types.h"
57 #include "DNA_material_types.h"
58 #include "DNA_meta_types.h"
59 #include "DNA_node_types.h"
60 #include "DNA_userdef_types.h"
61 #include "DNA_gpencil_types.h"
62 #include "DNA_windowmanager_types.h"
63 #include "DNA_world_types.h"
64
65 #include "RNA_access.h"
66 #include "RNA_define.h"
67
68 #include "BKE_animsys.h"
69 #include "BKE_action.h"
70 #include "BKE_curve.h"
71 #include "BKE_depsgraph.h"
72 #include "BKE_fcurve.h"
73 #include "BKE_key.h"
74 #include "BKE_material.h"
75 #include "BKE_object.h"
76 #include "BKE_context.h"
77 #include "BKE_utildefines.h"
78
79 #include "UI_interface.h"
80 #include "UI_interface_icons.h"
81 #include "UI_resources.h"
82 #include "UI_view2d.h"
83
84 #include "ED_anim_api.h"
85 #include "ED_keyframing.h"
86 #include "ED_keyframes_edit.h" // XXX move the select modes out of there!
87 #include "ED_screen.h"
88 #include "ED_space_api.h"
89
90 #include "BIF_gl.h"
91
92 #include "WM_api.h"
93 #include "WM_types.h"
94
95 /* *********************************************** */
96 // XXX constant defines to be moved elsewhere?
97
98 /* extra padding for lengths (to go under scrollers) */
99 #define EXTRA_SCROLL_PAD        100.0f
100
101 /* size of indent steps */
102 #define INDENT_STEP_SIZE        7
103
104 /* macros used for type defines */
105         /* get the pointer used for some flag */
106 #define GET_ACF_FLAG_PTR(ptr) \
107         { \
108                 *type= sizeof((ptr)); \
109                 return &(ptr); \
110         } 
111
112
113 /* XXX */
114 extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
115 extern void gl_round_box_shade(int mode, float minx, float miny, float maxx, float maxy, float rad, float shadetop, float shadedown);
116
117
118 /* *********************************************** */
119 /* Generic Functions (Type independent) */
120
121 /* Draw Backdrop ---------------------------------- */
122
123 /* get backdrop color for top-level widgets (Scene and Object only) */
124 static void acf_generic_root_color(bAnimContext *ac, bAnimListElem *ale, float *color)
125 {
126         /* darker blue for top-level widgets */
127         UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, color);
128 }
129
130 /* backdrop for top-level widgets (Scene and Object only) */
131 static void acf_generic_root_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
132 {
133         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
134         View2D *v2d= &ac->ar->v2d;
135         short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
136         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
137         float color[3];
138         
139         /* set backdrop drawing color */
140         acf->get_backdrop_color(ac, ale, color);
141         glColor3fv(color);
142         
143         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
144         uiSetRoundBox((expanded)? (1):(1|8));
145         gl_round_box(GL_POLYGON, offset,  yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8);
146 }
147
148
149 /* get backdrop color for data expanders under top-level Scene/Object */
150 static void acf_generic_dataexpand_color(bAnimContext *ac, bAnimListElem *ale, float *color)
151 {
152         /* lighter color than top-level widget */
153         UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, color);
154 }
155
156 /* backdrop for data expanders under top-level Scene/Object */
157 static void acf_generic_dataexpand_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
158 {
159         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
160         View2D *v2d= &ac->ar->v2d;
161         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
162         float color[3];
163         
164         /* set backdrop drawing color */
165         acf->get_backdrop_color(ac, ale, color);
166         glColor3fv(color);
167         
168         /* no rounded corner - just rectangular box */
169         glRectf(offset, yminc,  v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc);
170 }
171
172 /* get backdrop color for generic channels */
173 static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float *color)
174 {
175         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
176         SpaceAction *saction = NULL;
177         bActionGroup *grp = NULL;
178         short indent= (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
179         
180         /* get context info needed... */
181         if ((ac->sa) && (ac->sa->spacetype == SPACE_ACTION))
182                 saction= (SpaceAction *)ac->sa->spacedata.first;
183                 
184         if (ale->type == ANIMTYPE_FCURVE) {
185                 FCurve *fcu= (FCurve *)ale->data;
186                 grp= fcu->grp;
187         }
188         
189         /* set color for normal channels 
190          *      - use 3 shades of color group/standard color for 3 indention level
191          *      - only use group colors if allowed to, and if actually feasible
192          */
193         if ( (saction && !(saction->flag & SACTION_NODRAWGCOLORS)) && 
194                  ((grp) && (grp->customCol)) ) 
195         {
196                 char cp[3];
197                 
198                 if (indent == 2) {
199                         VECCOPY(cp, grp->cs.solid);
200                 }
201                 else if (indent == 1) {
202                         VECCOPY(cp, grp->cs.select);
203                 }
204                 else {
205                         VECCOPY(cp, grp->cs.active);
206                 }
207                 
208                 /* copy the colors over, transforming from bytes to floats */
209                 rgb_byte_to_float(cp, color);
210         }
211         else {
212                 // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)?
213                 int colOfs= 20 - 20*indent;
214                 UI_GetThemeColorShade3fv(TH_HEADER, colOfs, color);
215         }
216 }
217
218 /* backdrop for generic channels */
219 static void acf_generic_channel_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
220 {
221         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
222         View2D *v2d= &ac->ar->v2d;
223         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
224         float color[3];
225         
226         /* set backdrop drawing color */
227         acf->get_backdrop_color(ac, ale, color);
228         glColor3fv(color);
229         
230         /* no rounded corners - just rectangular box */
231         glRectf(offset, yminc,  v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc);
232 }
233
234 /* Indention + Offset ------------------------------------------- */
235
236 /* indention level is always the value in the name */
237 static short acf_generic_indention_0(bAnimContext *ac, bAnimListElem *ale)
238 {
239         return 0;
240 }
241 static short acf_generic_indention_1(bAnimContext *ac, bAnimListElem *ale)
242 {
243         return 1;
244 }
245 #if 0 // XXX not used
246 static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
247 {
248         return 2;
249 }
250 #endif
251
252 /* indention which varies with the grouping status */
253 static short acf_generic_indention_flexible(bAnimContext *ac, bAnimListElem *ale)
254 {
255         short indent= 0;
256         
257         if (ale->id) {
258                 /* special exception for materials and particles */
259                 if (ELEM(GS(ale->id->name),ID_MA,ID_PA))
260                         indent++;
261         }
262         
263         /* grouped F-Curves need extra level of indention */
264         if (ale->type == ANIMTYPE_FCURVE) {
265                 FCurve *fcu= (FCurve *)ale->data;
266                 
267                 // TODO: we need some way of specifying that the indention color should be one less...
268                 if (fcu->grp)
269                         indent++;
270         }
271         
272         /* no indention */
273         return indent;
274 }
275
276 /* basic offset for channels derived from indention */
277 static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
278 {
279         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
280         
281         if (acf && acf->get_indent_level)
282                 return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
283         else
284                 return 0;
285 }
286
287 /* offset for groups + grouped entities */
288 static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
289 {
290         short offset= acf_generic_basic_offset(ac, ale);
291         
292         if (ale->id) {
293                 /* special exception for materials and particles */
294                 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) 
295                         offset += 21;
296                         
297                 /* if not in Action Editor mode, groupings must carry some offset too... */
298                 else if (ac->datatype != ANIMCONT_ACTION)
299                         offset += 14;
300         }
301         
302         /* offset is just the normal type - i.e. based on indention */
303         return offset;
304 }
305
306 /* Name ------------------------------------------- */
307
308 /* name for ID block entries */
309 static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
310 {
311         ID *id= (ID *)ale->data;        /* data pointed to should be an ID block */
312         
313         /* just copy the name... */
314         if (id && name)
315                 strcpy(name, id->name+2);
316 }
317
318 /* Settings ------------------------------------------- */
319
320 #if 0
321 /* channel type has no settings */
322 static short acf_generic_none_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
323 {
324         return 0;
325 }
326 #endif
327
328 /* check if some setting exists for this object-based data-expander (category only) */
329 static short acf_generic_dsexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
330 {
331         switch (setting) {
332                 /* only expand supported */
333                 case ACHANNEL_SETTING_EXPAND:
334                         return 1;
335                         
336                  /* visible - only available in Graph Editor */
337                 case ACHANNEL_SETTING_VISIBLE: 
338                         return ((ac) && (ac->spacetype == SPACE_IPO));
339                         
340                 default:
341                         return 0;
342         }
343 }
344
345 /* get pointer to the setting (category only) */
346 static void *acf_generic_dsexpand_setting_ptr(bAnimListElem *ale, int setting, short *type)
347 {
348         Object *ob= (Object *)ale->data;
349         
350         /* clear extra return data first */
351         *type= 0;
352         
353         switch (setting) {
354                 case ACHANNEL_SETTING_EXPAND: /* expanded */
355                         GET_ACF_FLAG_PTR(ob->nlaflag); // XXX
356                 
357                 default: /* unsupported */
358                         return NULL;
359         }
360 }
361
362 /* check if some setting exists for this object-based data-expander (datablock only) */
363 static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
364 {
365         switch (setting) {
366                 /* expand is always supported */
367                 case ACHANNEL_SETTING_EXPAND:
368                         return 1;
369                         
370                 /* mute is only supported for NLA */
371                 case ACHANNEL_SETTING_MUTE:
372                         return ((ac) && (ac->spacetype == SPACE_NLA));
373                         
374                 /* other flags are never supported */
375                 default:
376                         return 0;
377         }
378 }
379
380 /* *********************************************** */
381 /* Type Specific Functions + Defines */
382
383 /* Animation Summary ----------------------------------- */
384
385 /* get backdrop color for summary widget */
386 static void acf_summary_color(bAnimContext *ac, bAnimListElem *ale, float *color)
387 {
388         // FIXME: hardcoded color - same as the 'action' line in NLA
389         glColor3f(0.8f, 0.2f, 0.0f);    // reddish color 
390 }
391
392 /* backdrop for summary widget */
393 static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
394 {
395         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
396         View2D *v2d= &ac->ar->v2d;
397         float color[3];
398         
399         /* set backdrop drawing color */
400         acf->get_backdrop_color(ac, ale, color);
401         glColor3fv(color);
402         
403         /* rounded corners on LHS only 
404          *      - top and bottom 
405          *      - special hack: make the top a bit higher, since we are first... 
406          */
407         uiSetRoundBox((1|8));
408         gl_round_box(GL_POLYGON, 0,  yminc-2, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8);
409 }
410
411 /* name for summary entries */
412 static void acf_summary_name(bAnimListElem *ale, char *name)
413 {
414         if (name)
415                 strcpy(name, "DopeSheet Summary");
416 }
417
418 // TODO: this is really a temp icon I think
419 static int acf_summary_icon(bAnimListElem *ale)
420 {
421         return ICON_BORDERMOVE;
422 }
423
424 /* check if some setting exists for this channel */
425 static short acf_summary_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
426 {
427         /* only expanded is supported, as it is used for hiding all stuff which the summary covers */
428         return (setting == ACHANNEL_SETTING_EXPAND);
429 }
430
431 /* get the appropriate flag(s) for the setting when it is valid  */
432 static int acf_summary_setting_flag(int setting, short *neg)
433 {
434         if (setting == ACHANNEL_SETTING_EXPAND) {
435                 /* expanded */
436                 *neg= 1;
437                 return ADS_FLAG_SUMMARY_COLLAPSED;
438         }
439         else {
440                 /* unsupported */
441                 *neg= 0;
442                 return 0;
443         }
444 }
445
446 /* get pointer to the setting */
447 static void *acf_summary_setting_ptr(bAnimListElem *ale, int setting, short *type)
448 {
449         bAnimContext *ac= (bAnimContext *)ale->data;
450         
451         /* if data is valid, return pointer to active dopesheet's relevant flag 
452          *      - this is restricted to DopeSheet/Action Editor only
453          */
454         if ((ac->sa) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
455                 SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
456                 bDopeSheet *ads= &saction->ads;
457                 
458                 /* return pointer to DopeSheet's flag */
459                 GET_ACF_FLAG_PTR(ads->flag);
460         }
461         else {
462                 /* can't return anything useful - unsupported */
463                 *type= 0;
464                 return 0;
465         }
466 }
467
468 /* all animation summary (DopeSheet only) type define */
469 static bAnimChannelType ACF_SUMMARY = 
470 {
471         acf_summary_color,                                      /* backdrop color */
472         acf_summary_backdrop,                           /* backdrop */
473         acf_generic_indention_0,                        /* indent level */
474         NULL,                                                           /* offset */
475         
476         acf_summary_name,                                       /* name */
477         acf_summary_icon,                                       /* icon */
478         
479         acf_summary_setting_valid,                      /* has setting */
480         acf_summary_setting_flag,                       /* flag for setting */
481         acf_summary_setting_ptr                         /* pointer for setting */
482 };
483
484 /* Scene ------------------------------------------- */
485
486 // TODO: just get this from RNA?
487 static int acf_scene_icon(bAnimListElem *ale)
488 {
489         return ICON_SCENE_DATA;
490 }
491
492 /* check if some setting exists for this channel */
493 static short acf_scene_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
494 {
495         switch (setting) {
496                 /* muted only in NLA */
497                 case ACHANNEL_SETTING_MUTE: 
498                         return ((ac) && (ac->spacetype == SPACE_NLA));
499                         
500                 /* visible only in Graph Editor */
501                 case ACHANNEL_SETTING_VISIBLE: 
502                         return ((ac) && (ac->spacetype == SPACE_IPO));
503                 
504                 /* only select and expand supported otherwise */
505                 case ACHANNEL_SETTING_SELECT:
506                 case ACHANNEL_SETTING_EXPAND:
507                         return 1;
508                         
509                 default:
510                         return 0;
511         }
512 }
513
514 /* get the appropriate flag(s) for the setting when it is valid  */
515 static int acf_scene_setting_flag(int setting, short *neg)
516 {
517         /* clear extra return data first */
518         *neg= 0;
519         
520         switch (setting) {
521                 case ACHANNEL_SETTING_SELECT: /* selected */
522                         return SCE_DS_SELECTED;
523                         
524                 case ACHANNEL_SETTING_EXPAND: /* expanded */
525                         *neg= 1;
526                         return SCE_DS_COLLAPSED;
527                         
528                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
529                         return ADT_NLA_EVAL_OFF;
530                         
531                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
532                         *neg= 1;
533                         return ADT_CURVES_NOT_VISIBLE;
534                         
535                 default: /* unsupported */
536                         return 0;
537         }
538 }
539
540 /* get pointer to the setting */
541 static void *acf_scene_setting_ptr(bAnimListElem *ale, int setting, short *type)
542 {
543         Scene *scene= (Scene *)ale->data;
544         
545         /* clear extra return data first */
546         *type= 0;
547         
548         switch (setting) {
549                 case ACHANNEL_SETTING_SELECT: /* selected */
550                         GET_ACF_FLAG_PTR(scene->flag);
551                         
552                 case ACHANNEL_SETTING_EXPAND: /* expanded */
553                         GET_ACF_FLAG_PTR(scene->flag);
554                         
555                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
556                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
557                         if (scene->adt)
558                                 GET_ACF_FLAG_PTR(scene->adt->flag)
559                         else
560                                 return NULL;
561                         
562                 default: /* unsupported */
563                         return 0;
564         }
565 }
566
567 /* scene type define */
568 static bAnimChannelType ACF_SCENE = 
569 {
570         acf_generic_root_color,                 /* backdrop color */
571         acf_generic_root_backdrop,              /* backdrop */
572         acf_generic_indention_0,                /* indent level */
573         NULL,                                                   /* offset */
574         
575         acf_generic_idblock_name,               /* name */
576         acf_scene_icon,                                 /* icon */
577         
578         acf_scene_setting_valid,                /* has setting */
579         acf_scene_setting_flag,                 /* flag for setting */
580         acf_scene_setting_ptr                   /* pointer for setting */
581 };
582
583 /* Object ------------------------------------------- */
584
585 static int acf_object_icon(bAnimListElem *ale)
586 {
587         Base *base= (Base *)ale->data;
588         Object *ob= base->object;
589         
590         /* icon depends on object-type */
591         if (ob->type == OB_ARMATURE)
592                 return ICON_ARMATURE_DATA;
593         else    
594                 return ICON_OBJECT_DATA;
595 }
596
597 /* name for object */
598 static void acf_object_name(bAnimListElem *ale, char *name)
599 {
600         Base *base= (Base *)ale->data;
601         Object *ob= base->object;
602         
603         /* just copy the name... */
604         if (ob && name)
605                 strcpy(name, ob->id.name+2);
606 }
607
608 /* check if some setting exists for this channel */
609 static short acf_object_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
610 {
611         Base *base= (Base *)ale->data;
612         Object *ob= base->object;
613         
614         switch (setting) {
615                 /* muted only in NLA */
616                 case ACHANNEL_SETTING_MUTE: 
617                         return ((ac) && (ac->spacetype == SPACE_NLA));
618                         
619                 /* visible only in Graph Editor */
620                 case ACHANNEL_SETTING_VISIBLE: 
621                         return ((ac) && (ac->spacetype == SPACE_IPO) && (ob->adt));
622                 
623                 /* only select and expand supported otherwise */
624                 case ACHANNEL_SETTING_SELECT:
625                 case ACHANNEL_SETTING_EXPAND:
626                         return 1;
627                         
628                 default:
629                         return 0;
630         }
631 }
632
633 /* get the appropriate flag(s) for the setting when it is valid  */
634 static int acf_object_setting_flag(int setting, short *neg)
635 {
636         /* clear extra return data first */
637         *neg= 0;
638         
639         switch (setting) {
640                 case ACHANNEL_SETTING_SELECT: /* selected */
641                         return SELECT;
642                         
643                 case ACHANNEL_SETTING_EXPAND: /* expanded */
644                         *neg= 1;
645                         return OB_ADS_COLLAPSED;
646                         
647                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
648                         return ADT_NLA_EVAL_OFF;
649                         
650                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
651                         *neg= 1;
652                         return ADT_CURVES_NOT_VISIBLE;
653                         
654                 default: /* unsupported */
655                         return 0;
656         }
657 }
658
659 /* get pointer to the setting */
660 static void *acf_object_setting_ptr(bAnimListElem *ale, int setting, short *type)
661 {
662         Base *base= (Base *)ale->data;
663         Object *ob= base->object;
664         
665         /* clear extra return data first */
666         *type= 0;
667         
668         switch (setting) {
669                 case ACHANNEL_SETTING_SELECT: /* selected */
670                         GET_ACF_FLAG_PTR(ob->flag);
671                         
672                 case ACHANNEL_SETTING_EXPAND: /* expanded */
673                         GET_ACF_FLAG_PTR(ob->nlaflag); // xxx
674                         
675                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
676                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
677                         if (ob->adt)
678                                 GET_ACF_FLAG_PTR(ob->adt->flag)
679                         else
680                                 return NULL;
681                         
682                 default: /* unsupported */
683                         return 0;
684         }
685 }
686
687 /* object type define */
688 static bAnimChannelType ACF_OBJECT = 
689 {
690         acf_generic_root_color,                 /* backdrop color */
691         acf_generic_root_backdrop,              /* backdrop */
692         acf_generic_indention_0,                /* indent level */
693         NULL,                                                   /* offset */
694         
695         acf_object_name,                                /* name */
696         acf_object_icon,                                /* icon */
697         
698         acf_object_setting_valid,               /* has setting */
699         acf_object_setting_flag,                /* flag for setting */
700         acf_object_setting_ptr                  /* pointer for setting */
701 };
702
703 /* Group ------------------------------------------- */
704
705 /* get backdrop color for group widget */
706 static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float *color)
707 {
708         /* highlight only for action group channels */
709         if (ale->flag & AGRP_ACTIVE)
710                 UI_GetThemeColorShade3fv(TH_GROUP_ACTIVE, 10, color);
711         else
712                 UI_GetThemeColorShade3fv(TH_GROUP, 20, color);
713 }
714
715 /* backdrop for group widget */
716 static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
717 {
718         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
719         View2D *v2d= &ac->ar->v2d;
720         short expanded= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
721         short offset= (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
722         float color[3];
723         
724         /* set backdrop drawing color */
725         acf->get_backdrop_color(ac, ale, color);
726         glColor3fv(color);
727         
728         /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
729         uiSetRoundBox((expanded)? (1):(1|8));
730         gl_round_box(GL_POLYGON, offset,  yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc, 8);
731 }
732
733 /* name for group entries */
734 static void acf_group_name(bAnimListElem *ale, char *name)
735 {
736         bActionGroup *agrp= (bActionGroup *)ale->data;
737         
738         /* just copy the name... */
739         if (agrp && name)
740                 strcpy(name, agrp->name);
741 }
742
743 /* check if some setting exists for this channel */
744 static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
745 {
746         /* for now, all settings are supported, though some are only conditionally */
747         switch (setting) {
748                 case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
749                         return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO));
750                         
751                 default: /* always supported */
752                         return 1;
753         }
754 }
755
756 /* get the appropriate flag(s) for the setting when it is valid  */
757 static int acf_group_setting_flag(int setting, short *neg)
758 {
759         /* clear extra return data first */
760         *neg= 0;
761         
762         switch (setting) {
763                 case ACHANNEL_SETTING_SELECT: /* selected */
764                         return AGRP_SELECTED;
765                         
766                 case ACHANNEL_SETTING_EXPAND: /* expanded */
767                         return AGRP_EXPANDED;
768                         
769                 case ACHANNEL_SETTING_MUTE: /* muted */
770                         return AGRP_MUTED;
771                         
772                 case ACHANNEL_SETTING_PROTECT: /* protected */
773                         //*neg= 1; - if we change this to edtiability
774                         return AGRP_PROTECTED;
775                         
776                 case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
777                         *neg= 1;
778                         return AGRP_NOTVISIBLE;
779         }
780         
781         /* this shouldn't happen */
782         return 0;
783 }
784
785 /* get pointer to the setting */
786 static void *acf_group_setting_ptr(bAnimListElem *ale, int setting, short *type)
787 {
788         bActionGroup *agrp= (bActionGroup *)ale->data;
789         
790         /* all flags are just in agrp->flag for now... */
791         GET_ACF_FLAG_PTR(agrp->flag);
792 }
793
794 /* group type define */
795 static bAnimChannelType ACF_GROUP = 
796 {
797         acf_group_color,                                /* backdrop color */
798         acf_group_backdrop,                             /* backdrop */
799         acf_generic_indention_0,                /* indent level */
800         acf_generic_group_offset,               /* offset */
801         
802         acf_group_name,                                 /* name */
803         NULL,                                                   /* icon */
804         
805         acf_group_setting_valid,                /* has setting */
806         acf_group_setting_flag,                 /* flag for setting */
807         acf_group_setting_ptr                   /* pointer for setting */
808 };
809
810 /* F-Curve ------------------------------------------- */
811
812 /* name for fcurve entries */
813 static void acf_fcurve_name(bAnimListElem *ale, char *name)
814 {
815         getname_anim_fcurve(name, ale->id, ale->data);
816 }
817
818 /* check if some setting exists for this channel */
819 static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
820 {
821         FCurve *fcu= (FCurve *)ale->data;
822         
823         switch (setting) {
824                 /* unsupported */
825                 case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
826                         return 0;
827                 
828                 /* conditionally available */
829                 case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
830                         if (fcu->bezt)
831                                 return 1;
832                         else
833                                 return 0; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
834                                 
835                 case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
836                         return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO));
837                         
838                 /* always available */
839                 default:
840                         return 1;
841         }
842 }
843
844 /* get the appropriate flag(s) for the setting when it is valid  */
845 static int acf_fcurve_setting_flag(int setting, short *neg)
846 {
847         /* clear extra return data first */
848         *neg= 0;
849         
850         switch (setting) {
851                 case ACHANNEL_SETTING_SELECT: /* selected */
852                         return FCURVE_SELECTED;
853                         
854                 case ACHANNEL_SETTING_MUTE: /* muted */
855                         return FCURVE_MUTED;
856                         
857                 case ACHANNEL_SETTING_PROTECT: /* protected */
858                         //*neg= 1; - if we change this to edtiability
859                         return FCURVE_PROTECTED;
860                         
861                 case ACHANNEL_SETTING_VISIBLE: /* visiblity - graph editor */
862                         return FCURVE_VISIBLE;
863                         
864                 default: /* unsupported */
865                         return 0;
866         }
867 }
868
869 /* get pointer to the setting */
870 static void *acf_fcurve_setting_ptr(bAnimListElem *ale, int setting, short *type)
871 {
872         FCurve *fcu= (FCurve *)ale->data;
873         
874         /* all flags are just in agrp->flag for now... */
875         GET_ACF_FLAG_PTR(fcu->flag);
876 }
877
878 /* fcurve type define */
879 static bAnimChannelType ACF_FCURVE = 
880 {
881         acf_generic_channel_color,              /* backdrop color */
882         acf_generic_channel_backdrop,   /* backdrop */
883         acf_generic_indention_flexible, /* indent level */              // xxx rename this to f-curves only?
884         acf_generic_group_offset,               /* offset */
885         
886         acf_fcurve_name,                                /* name */
887         NULL,                                                   /* icon */
888         
889         acf_fcurve_setting_valid,               /* has setting */
890         acf_fcurve_setting_flag,                /* flag for setting */
891         acf_fcurve_setting_ptr                  /* pointer for setting */
892 };
893
894 /* Object Action Expander  ------------------------------------------- */
895
896 // TODO: just get this from RNA?
897 static int acf_fillactd_icon(bAnimListElem *ale)
898 {
899         return ICON_ACTION;
900 }
901
902 /* check if some setting exists for this channel */
903 static short acf_fillactd_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
904 {
905         switch (setting) {
906                 /* only select and expand supported */
907                 case ACHANNEL_SETTING_SELECT:
908                 case ACHANNEL_SETTING_EXPAND:
909                         return 1;
910                         
911                 default:
912                         return 0;
913         }
914 }
915
916 /* get the appropriate flag(s) for the setting when it is valid  */
917 static int acf_fillactd_setting_flag(int setting, short *neg)
918 {
919         /* clear extra return data first */
920         *neg= 0;
921         
922         switch (setting) {
923                 case ACHANNEL_SETTING_SELECT: /* selected */
924                         return ADT_UI_SELECTED;
925                         
926                 case ACHANNEL_SETTING_EXPAND: /* expanded */
927                         *neg= 1;
928                         return ACT_COLLAPSED;
929                 
930                 default: /* unsupported */
931                         return 0;
932         }
933 }
934
935 /* get pointer to the setting */
936 static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *type)
937 {
938         bAction *act= (bAction *)ale->data;
939         AnimData *adt= ale->adt;
940         
941         /* clear extra return data first */
942         *type= 0;
943         
944         switch (setting) {
945                 case ACHANNEL_SETTING_SELECT: /* selected */
946                         if (adt) {
947                                 GET_ACF_FLAG_PTR(adt->flag);
948                         }
949                         else
950                                 return 0;
951                         
952                 case ACHANNEL_SETTING_EXPAND: /* expanded */
953                         GET_ACF_FLAG_PTR(act->flag);
954                 
955                 default: /* unsupported */
956                         return 0;
957         }
958 }
959
960 /* object action expander type define */
961 static bAnimChannelType ACF_FILLACTD = 
962 {
963         acf_generic_dataexpand_color,   /* backdrop color */
964         acf_generic_dataexpand_backdrop,/* backdrop */
965         acf_generic_indention_1,                /* indent level */
966         acf_generic_basic_offset,               /* offset */
967         
968         acf_generic_idblock_name,               /* name */
969         acf_fillactd_icon,                              /* icon */
970         
971         acf_fillactd_setting_valid,             /* has setting */
972         acf_fillactd_setting_flag,              /* flag for setting */
973         acf_fillactd_setting_ptr                /* pointer for setting */
974 };
975
976 /* Drivers Expander  ------------------------------------------- */
977
978 // TODO: just get this from RNA?
979 static int acf_filldrivers_icon(bAnimListElem *ale)
980 {
981         return ICON_ANIM_DATA;
982 }
983
984 static void acf_filldrivers_name(bAnimListElem *ale, char *name)
985 {
986         strcpy(name, "Drivers");
987 }
988
989 /* check if some setting exists for this channel */
990 // TODO: this could be made more generic
991 static short acf_filldrivers_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
992 {
993         switch (setting) {
994                 /* only expand supported */
995                 case ACHANNEL_SETTING_EXPAND:
996                         return 1;
997                         
998                 default:
999                         return 0;
1000         }
1001 }
1002
1003 /* get the appropriate flag(s) for the setting when it is valid  */
1004 static int acf_filldrivers_setting_flag(int setting, short *neg)
1005 {
1006         /* clear extra return data first */
1007         *neg= 0;
1008         
1009         switch (setting) {
1010                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1011                         *neg= 1;
1012                         return ADT_DRIVERS_COLLAPSED;
1013                 
1014                 default: /* unsupported */
1015                         return 0;
1016         }
1017 }
1018
1019 /* get pointer to the setting */
1020 static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, int setting, short *type)
1021 {
1022         AnimData *adt= (AnimData *)ale->data;
1023         
1024         /* clear extra return data first */
1025         *type= 0;
1026         
1027         switch (setting) {
1028                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1029                         GET_ACF_FLAG_PTR(adt->flag);
1030                 
1031                 default: /* unsupported */
1032                         return 0;
1033         }
1034 }
1035
1036 /* drivers expander type define */
1037 static bAnimChannelType ACF_FILLDRIVERS = 
1038 {
1039         acf_generic_dataexpand_color,   /* backdrop color */
1040         acf_generic_dataexpand_backdrop,/* backdrop */
1041         acf_generic_indention_1,                /* indent level */
1042         acf_generic_basic_offset,               /* offset */
1043         
1044         acf_filldrivers_name,                   /* name */
1045         acf_filldrivers_icon,                   /* icon */
1046         
1047         acf_filldrivers_setting_valid,  /* has setting */
1048         acf_filldrivers_setting_flag,   /* flag for setting */
1049         acf_filldrivers_setting_ptr             /* pointer for setting */
1050 };
1051
1052 /* Materials Expander  ------------------------------------------- */
1053
1054 // TODO: just get this from RNA?
1055 static int acf_fillmatd_icon(bAnimListElem *ale)
1056 {
1057         return ICON_MATERIAL_DATA;
1058 }
1059
1060 static void acf_fillmatd_name(bAnimListElem *ale, char *name)
1061 {
1062         strcpy(name, "Materials");
1063 }
1064
1065 /* get the appropriate flag(s) for the setting when it is valid  */
1066 static int acf_fillmatd_setting_flag(int setting, short *neg)
1067 {
1068         /* clear extra return data first */
1069         *neg= 0;
1070         
1071         switch (setting) {
1072                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1073                         return OB_ADS_SHOWMATS;
1074                 
1075                 default: /* unsupported */
1076                         return 0;
1077         }
1078 }
1079
1080 /* materials expander type define */
1081 static bAnimChannelType ACF_FILLMATD= 
1082 {
1083         acf_generic_dataexpand_color,   /* backdrop color */
1084         acf_generic_dataexpand_backdrop,/* backdrop */
1085         acf_generic_indention_1,                /* indent level */
1086         acf_generic_basic_offset,               /* offset */
1087         
1088         acf_fillmatd_name,                              /* name */
1089         acf_fillmatd_icon,                              /* icon */
1090         
1091         acf_generic_dsexpand_setting_valid,     /* has setting */
1092         acf_fillmatd_setting_flag,                              /* flag for setting */
1093         acf_generic_dsexpand_setting_ptr                /* pointer for setting */
1094 };
1095
1096 /* Particles Expander  ------------------------------------------- */
1097
1098 // TODO: just get this from RNA?
1099 static int acf_fillpartd_icon(bAnimListElem *ale)
1100 {
1101         return ICON_PARTICLE_DATA;
1102 }
1103
1104 static void acf_fillpartd_name(bAnimListElem *ale, char *name)
1105 {
1106         strcpy(name, "Particles");
1107 }
1108
1109 /* get the appropriate flag(s) for the setting when it is valid  */
1110 static int acf_fillpartd_setting_flag(int setting, short *neg)
1111 {
1112         /* clear extra return data first */
1113         *neg= 0;
1114         
1115         switch (setting) {
1116                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1117                         return OB_ADS_SHOWPARTS;
1118                 
1119                 default: /* unsupported */
1120                         return 0;
1121         }
1122 }
1123
1124 /* particles expander type define */
1125 static bAnimChannelType ACF_FILLPARTD= 
1126 {
1127         acf_generic_dataexpand_color,   /* backdrop color */
1128         acf_generic_dataexpand_backdrop,/* backdrop */
1129         acf_generic_indention_1,                /* indent level */
1130         acf_generic_basic_offset,               /* offset */
1131         
1132         acf_fillpartd_name,                             /* name */
1133         acf_fillpartd_icon,                             /* icon */
1134         
1135         acf_generic_dsexpand_setting_valid,     /* has setting */
1136         acf_fillpartd_setting_flag,                             /* flag for setting */
1137         acf_generic_dsexpand_setting_ptr                /* pointer for setting */
1138 };
1139
1140 /* Material Expander  ------------------------------------------- */
1141
1142 // TODO: just get this from RNA?
1143 static int acf_dsmat_icon(bAnimListElem *ale)
1144 {
1145         return ICON_MATERIAL_DATA;
1146 }
1147
1148 /* offset for material expanders */
1149 static short acf_dsmat_offset(bAnimContext *ac, bAnimListElem *ale)
1150 {
1151         return 21;
1152 }
1153
1154 /* get the appropriate flag(s) for the setting when it is valid  */
1155 static int acf_dsmat_setting_flag(int setting, short *neg)
1156 {
1157         /* clear extra return data first */
1158         *neg= 0;
1159         
1160         switch (setting) {
1161                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1162                         return MA_DS_EXPAND;
1163                         
1164                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1165                         return ADT_NLA_EVAL_OFF;
1166                         
1167                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1168                         *neg= 1;
1169                         return ADT_CURVES_NOT_VISIBLE;
1170                         
1171                 case ACHANNEL_SETTING_SELECT: /* selected */
1172                         return ADT_UI_SELECTED;
1173                 
1174                 default: /* unsupported */
1175                         return 0;
1176         }
1177 }
1178
1179 /* get pointer to the setting */
1180 static void *acf_dsmat_setting_ptr(bAnimListElem *ale, int setting, short *type)
1181 {
1182         Material *ma= (Material *)ale->data;
1183         
1184         /* clear extra return data first */
1185         *type= 0;
1186         
1187         switch (setting) {
1188                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1189                         GET_ACF_FLAG_PTR(ma->flag);
1190                         
1191                 case ACHANNEL_SETTING_SELECT: /* selected */
1192                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1193                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1194                         if (ma->adt)
1195                                 GET_ACF_FLAG_PTR(ma->adt->flag)
1196                         else
1197                                 return NULL;    
1198                 
1199                 default: /* unsupported */
1200                         return NULL;
1201         }
1202 }
1203
1204 /* material expander type define */
1205 static bAnimChannelType ACF_DSMAT= 
1206 {
1207         acf_generic_channel_color,              /* backdrop color */
1208         acf_generic_channel_backdrop,   /* backdrop */
1209         acf_generic_indention_0,                /* indent level */
1210         acf_dsmat_offset,                               /* offset */
1211         
1212         acf_generic_idblock_name,               /* name */
1213         acf_dsmat_icon,                                 /* icon */
1214         
1215         acf_generic_dataexpand_setting_valid,   /* has setting */
1216         acf_dsmat_setting_flag,                                 /* flag for setting */
1217         acf_dsmat_setting_ptr                                   /* pointer for setting */
1218 };
1219
1220 /* Lamp Expander  ------------------------------------------- */
1221
1222 // TODO: just get this from RNA?
1223 static int acf_dslam_icon(bAnimListElem *ale)
1224 {
1225         return ICON_LAMP_DATA;
1226 }
1227
1228 /* get the appropriate flag(s) for the setting when it is valid  */
1229 static int acf_dslam_setting_flag(int setting, short *neg)
1230 {
1231         /* clear extra return data first */
1232         *neg= 0;
1233         
1234         switch (setting) {
1235                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1236                         return LA_DS_EXPAND;
1237                         
1238                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1239                         return ADT_NLA_EVAL_OFF;
1240                         
1241                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1242                         *neg= 1;
1243                         return ADT_CURVES_NOT_VISIBLE;
1244                         
1245                 case ACHANNEL_SETTING_SELECT: /* selected */
1246                         return ADT_UI_SELECTED;
1247                 
1248                 default: /* unsupported */
1249                         return 0;
1250         }
1251 }
1252
1253 /* get pointer to the setting */
1254 static void *acf_dslam_setting_ptr(bAnimListElem *ale, int setting, short *type)
1255 {
1256         Lamp *la= (Lamp *)ale->data;
1257         
1258         /* clear extra return data first */
1259         *type= 0;
1260         
1261         switch (setting) {
1262                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1263                         GET_ACF_FLAG_PTR(la->flag);
1264                         
1265                 case ACHANNEL_SETTING_SELECT: /* selected */
1266                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1267                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1268                         if (la->adt)
1269                                 GET_ACF_FLAG_PTR(la->adt->flag)
1270                         else
1271                                 return NULL;    
1272                 
1273                 default: /* unsupported */
1274                         return NULL;
1275         }
1276 }
1277
1278 /* lamp expander type define */
1279 static bAnimChannelType ACF_DSLAM= 
1280 {
1281         acf_generic_dataexpand_color,   /* backdrop color */
1282         acf_generic_dataexpand_backdrop,/* backdrop */
1283         acf_generic_indention_1,                /* indent level */
1284         acf_generic_basic_offset,               /* offset */
1285         
1286         acf_generic_idblock_name,               /* name */
1287         acf_dslam_icon,                                 /* icon */
1288         
1289         acf_generic_dataexpand_setting_valid,   /* has setting */
1290         acf_dslam_setting_flag,                                 /* flag for setting */
1291         acf_dslam_setting_ptr                                   /* pointer for setting */
1292 };
1293
1294 /* Camera Expander  ------------------------------------------- */
1295
1296 // TODO: just get this from RNA?
1297 static int acf_dscam_icon(bAnimListElem *ale)
1298 {
1299         return ICON_CAMERA_DATA;
1300 }
1301
1302 /* get the appropriate flag(s) for the setting when it is valid  */
1303 static int acf_dscam_setting_flag(int setting, short *neg)
1304 {
1305         /* clear extra return data first */
1306         *neg= 0;
1307         
1308         switch (setting) {
1309                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1310                         return CAM_DS_EXPAND;
1311                         
1312                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1313                         return ADT_NLA_EVAL_OFF;
1314                         
1315                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1316                         *neg= 1;
1317                         return ADT_CURVES_NOT_VISIBLE;
1318                         
1319                 case ACHANNEL_SETTING_SELECT: /* selected */
1320                         return ADT_UI_SELECTED;
1321                 
1322                 default: /* unsupported */
1323                         return 0;
1324         }
1325 }
1326
1327 /* get pointer to the setting */
1328 static void *acf_dscam_setting_ptr(bAnimListElem *ale, int setting, short *type)
1329 {
1330         Camera *ca= (Camera *)ale->data;
1331         
1332         /* clear extra return data first */
1333         *type= 0;
1334         
1335         switch (setting) {
1336                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1337                         GET_ACF_FLAG_PTR(ca->flag);
1338                         
1339                 case ACHANNEL_SETTING_SELECT: /* selected */
1340                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1341                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1342                         if (ca->adt)
1343                                 GET_ACF_FLAG_PTR(ca->adt->flag)
1344                         else
1345                                 return NULL;
1346                 
1347                 default: /* unsupported */
1348                         return NULL;
1349         }
1350 }
1351
1352 /* camera expander type define */
1353 static bAnimChannelType ACF_DSCAM= 
1354 {
1355         acf_generic_dataexpand_color,   /* backdrop color */
1356         acf_generic_dataexpand_backdrop,/* backdrop */
1357         acf_generic_indention_1,                /* indent level */
1358         acf_generic_basic_offset,               /* offset */
1359         
1360         acf_generic_idblock_name,               /* name */
1361         acf_dscam_icon,                                 /* icon */
1362         
1363         acf_generic_dataexpand_setting_valid,   /* has setting */
1364         acf_dscam_setting_flag,                                 /* flag for setting */
1365         acf_dscam_setting_ptr                                   /* pointer for setting */
1366 };
1367
1368 /* Curve Expander  ------------------------------------------- */
1369
1370 // TODO: just get this from RNA?
1371 static int acf_dscur_icon(bAnimListElem *ale)
1372 {
1373         Curve *cu= (Curve *)ale->data;
1374         short obtype= curve_type(cu);
1375         
1376         switch (obtype) {
1377                 case OB_FONT:
1378                         return ICON_FONT_DATA;
1379                 case OB_SURF:
1380                         return ICON_SURFACE_DATA;
1381                 default:
1382                         return ICON_CURVE_DATA;
1383         }
1384 }
1385
1386 /* get the appropriate flag(s) for the setting when it is valid  */
1387 static int acf_dscur_setting_flag(int setting, short *neg)
1388 {
1389         /* clear extra return data first */
1390         *neg= 0;
1391         
1392         switch (setting) {
1393                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1394                         return CU_DS_EXPAND;
1395                         
1396                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1397                         return ADT_NLA_EVAL_OFF;
1398                         
1399                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1400                         *neg= 1;
1401                         return ADT_CURVES_NOT_VISIBLE;
1402                         
1403                 case ACHANNEL_SETTING_SELECT: /* selected */
1404                         return ADT_UI_SELECTED;
1405                 
1406                 default: /* unsupported */
1407                         return 0;
1408         }
1409 }
1410
1411 /* get pointer to the setting */
1412 static void *acf_dscur_setting_ptr(bAnimListElem *ale, int setting, short *type)
1413 {
1414         Curve *cu= (Curve *)ale->data;
1415         
1416         /* clear extra return data first */
1417         *type= 0;
1418         
1419         switch (setting) {
1420                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1421                         GET_ACF_FLAG_PTR(cu->flag);
1422                         
1423                 case ACHANNEL_SETTING_SELECT: /* selected */
1424                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1425                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1426                         if (cu->adt)
1427                                 GET_ACF_FLAG_PTR(cu->adt->flag)
1428                         else
1429                                 return NULL;
1430                 
1431                 default: /* unsupported */
1432                         return NULL;
1433         }
1434 }
1435
1436 /* curve expander type define */
1437 static bAnimChannelType ACF_DSCUR= 
1438 {
1439         acf_generic_dataexpand_color,   /* backdrop color */
1440         acf_generic_dataexpand_backdrop,/* backdrop */
1441         acf_generic_indention_1,                /* indent level */
1442         acf_generic_basic_offset,               /* offset */
1443         
1444         acf_generic_idblock_name,               /* name */
1445         acf_dscur_icon,                                 /* icon */
1446         
1447         acf_generic_dataexpand_setting_valid,   /* has setting */
1448         acf_dscur_setting_flag,                                 /* flag for setting */
1449         acf_dscur_setting_ptr                                   /* pointer for setting */
1450 };
1451
1452 /* Shape Key Expander  ------------------------------------------- */
1453
1454 // TODO: just get this from RNA?
1455 static int acf_dsskey_icon(bAnimListElem *ale)
1456 {
1457         return ICON_SHAPEKEY_DATA;
1458 }
1459
1460 /* get the appropriate flag(s) for the setting when it is valid  */
1461 static int acf_dsskey_setting_flag(int setting, short *neg)
1462 {
1463         /* clear extra return data first */
1464         *neg= 0;
1465         
1466         switch (setting) {
1467                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1468                         return KEY_DS_EXPAND;
1469                         
1470                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1471                         return ADT_NLA_EVAL_OFF;
1472                         
1473                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1474                         *neg= 1;
1475                         return ADT_CURVES_NOT_VISIBLE;
1476                         
1477                 case ACHANNEL_SETTING_SELECT: /* selected */
1478                         return ADT_UI_SELECTED;
1479                 
1480                 default: /* unsupported */
1481                         return 0;
1482         }
1483 }
1484
1485 /* get pointer to the setting */
1486 static void *acf_dsskey_setting_ptr(bAnimListElem *ale, int setting, short *type)
1487 {
1488         Key *key= (Key *)ale->data;
1489         
1490         /* clear extra return data first */
1491         *type= 0;
1492         
1493         switch (setting) {
1494                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1495                         GET_ACF_FLAG_PTR(key->flag);
1496                         
1497                 case ACHANNEL_SETTING_SELECT: /* selected */
1498                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1499                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1500                         if (key->adt)
1501                                 GET_ACF_FLAG_PTR(key->adt->flag)
1502                         else
1503                                 return NULL;
1504                 
1505                 default: /* unsupported */
1506                         return NULL;
1507         }
1508 }
1509
1510 /* shapekey expander type define */
1511 static bAnimChannelType ACF_DSSKEY= 
1512 {
1513         acf_generic_dataexpand_color,   /* backdrop color */
1514         acf_generic_dataexpand_backdrop,/* backdrop */
1515         acf_generic_indention_1,                /* indent level */
1516         acf_generic_basic_offset,               /* offset */
1517         
1518         acf_generic_idblock_name,               /* name */
1519         acf_dsskey_icon,                                /* icon */
1520         
1521         acf_generic_dataexpand_setting_valid,   /* has setting */
1522         acf_dsskey_setting_flag,                                /* flag for setting */
1523         acf_dsskey_setting_ptr                                  /* pointer for setting */
1524 };
1525
1526 /* World Expander  ------------------------------------------- */
1527
1528 // TODO: just get this from RNA?
1529 static int acf_dswor_icon(bAnimListElem *ale)
1530 {
1531         return ICON_WORLD_DATA;
1532 }
1533
1534 /* get the appropriate flag(s) for the setting when it is valid  */
1535 static int acf_dswor_setting_flag(int setting, short *neg)
1536 {
1537         /* clear extra return data first */
1538         *neg= 0;
1539         
1540         switch (setting) {
1541                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1542                         return WO_DS_EXPAND;
1543                         
1544                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1545                         return ADT_NLA_EVAL_OFF;
1546                         
1547                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1548                         *neg= 1;
1549                         return ADT_CURVES_NOT_VISIBLE;
1550                         
1551                 case ACHANNEL_SETTING_SELECT: /* selected */
1552                         return ADT_UI_SELECTED;
1553                 
1554                 default: /* unsupported */
1555                         return 0;
1556         }
1557 }
1558
1559 /* get pointer to the setting */
1560 static void *acf_dswor_setting_ptr(bAnimListElem *ale, int setting, short *type)
1561 {
1562         World *wo= (World *)ale->data;
1563         
1564         /* clear extra return data first */
1565         *type= 0;
1566         
1567         switch (setting) {
1568                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1569                         GET_ACF_FLAG_PTR(wo->flag);
1570                         
1571                 case ACHANNEL_SETTING_SELECT: /* selected */
1572                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1573                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1574                         if (wo->adt)
1575                                 GET_ACF_FLAG_PTR(wo->adt->flag)
1576                         else
1577                                 return NULL;
1578                 
1579                 default: /* unsupported */
1580                         return NULL;
1581         }
1582 }
1583
1584 /* world expander type define */
1585 static bAnimChannelType ACF_DSWOR= 
1586 {
1587         acf_generic_dataexpand_color,   /* backdrop color */
1588         acf_generic_dataexpand_backdrop,/* backdrop */
1589         acf_generic_indention_1,                /* indent level */
1590         acf_generic_basic_offset,               /* offset */
1591         
1592         acf_generic_idblock_name,               /* name */
1593         acf_dswor_icon,                                 /* icon */
1594         
1595         acf_generic_dataexpand_setting_valid,   /* has setting */
1596         acf_dswor_setting_flag,                                 /* flag for setting */
1597         acf_dswor_setting_ptr                                   /* pointer for setting */
1598 };
1599
1600 /* Particle Expander  ------------------------------------------- */
1601
1602 // TODO: just get this from RNA?
1603 static int acf_dspart_icon(bAnimListElem *ale)
1604 {
1605         return ICON_PARTICLE_DATA;
1606 }
1607
1608 /* get the appropriate flag(s) for the setting when it is valid  */
1609 static int acf_dspart_setting_flag(int setting, short *neg)
1610 {
1611         /* clear extra return data first */
1612         *neg= 0;
1613         
1614         switch (setting) {
1615                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1616                         return PART_DS_EXPAND;
1617                         
1618                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1619                         return ADT_NLA_EVAL_OFF;
1620                         
1621                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1622                         *neg= 1;
1623                         return ADT_CURVES_NOT_VISIBLE;
1624                         
1625                 case ACHANNEL_SETTING_SELECT: /* selected */
1626                         return ADT_UI_SELECTED;
1627                 
1628                 default: /* unsupported */
1629                         return 0;
1630         }
1631 }
1632
1633 /* get pointer to the setting */
1634 static void *acf_dspart_setting_ptr(bAnimListElem *ale, int setting, short *type)
1635 {
1636         ParticleSettings *part= (ParticleSettings *)ale->data;
1637         
1638         /* clear extra return data first */
1639         *type= 0;
1640         
1641         switch (setting) {
1642                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1643                         GET_ACF_FLAG_PTR(part->flag);
1644                         
1645                 case ACHANNEL_SETTING_SELECT: /* selected */
1646                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1647                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1648                         if (part->adt)
1649                                 GET_ACF_FLAG_PTR(part->adt->flag)
1650                         else
1651                                 return NULL;
1652                 
1653                 default: /* unsupported */
1654                         return NULL;
1655         }
1656 }
1657
1658 /* particle expander type define */
1659 static bAnimChannelType ACF_DSPART= 
1660 {
1661         acf_generic_dataexpand_color,   /* backdrop color */
1662         acf_generic_dataexpand_backdrop,/* backdrop */
1663         acf_generic_indention_1,                /* indent level */
1664         acf_generic_basic_offset,               /* offset */
1665         
1666         acf_generic_idblock_name,               /* name */
1667         acf_dspart_icon,                                /* icon */
1668         
1669         acf_generic_dataexpand_setting_valid,   /* has setting */
1670         acf_dspart_setting_flag,                                /* flag for setting */
1671         acf_dspart_setting_ptr                                  /* pointer for setting */
1672 };
1673
1674 /* MetaBall Expander  ------------------------------------------- */
1675
1676 // TODO: just get this from RNA?
1677 static int acf_dsmball_icon(bAnimListElem *ale)
1678 {
1679         return ICON_META_DATA;
1680 }
1681
1682 /* get the appropriate flag(s) for the setting when it is valid  */
1683 static int acf_dsmball_setting_flag(int setting, short *neg)
1684 {
1685         /* clear extra return data first */
1686         *neg= 0;
1687         
1688         switch (setting) {
1689                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1690                         return MB_DS_EXPAND;
1691                         
1692                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1693                         return ADT_NLA_EVAL_OFF;
1694                         
1695                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1696                         *neg= 1;
1697                         return ADT_CURVES_NOT_VISIBLE;
1698                 
1699                 case ACHANNEL_SETTING_SELECT: /* selected */
1700                         return ADT_UI_SELECTED;
1701                 
1702                 default: /* unsupported */
1703                         return 0;
1704         }
1705 }
1706
1707 /* get pointer to the setting */
1708 static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *type)
1709 {
1710         MetaBall *mb= (MetaBall *)ale->data;
1711         
1712         /* clear extra return data first */
1713         *type= 0;
1714         
1715         switch (setting) {
1716                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1717                         GET_ACF_FLAG_PTR(mb->flag);
1718                         
1719                 case ACHANNEL_SETTING_SELECT: /* selected */
1720                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1721                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1722                         if (mb->adt)
1723                                 GET_ACF_FLAG_PTR(mb->adt->flag)
1724                         else
1725                                 return NULL;
1726                 
1727                 default: /* unsupported */
1728                         return NULL;
1729         }
1730 }
1731
1732 /* metaball expander type define */
1733 static bAnimChannelType ACF_DSMBALL= 
1734 {
1735         acf_generic_dataexpand_color,   /* backdrop color */
1736         acf_generic_dataexpand_backdrop,/* backdrop */
1737         acf_generic_indention_1,                /* indent level */
1738         acf_generic_basic_offset,               /* offset */
1739         
1740         acf_generic_idblock_name,               /* name */
1741         acf_dsmball_icon,                               /* icon */
1742         
1743         acf_generic_dataexpand_setting_valid,   /* has setting */
1744         acf_dsmball_setting_flag,                               /* flag for setting */
1745         acf_dsmball_setting_ptr                                 /* pointer for setting */
1746 };
1747
1748 /* Armature Expander  ------------------------------------------- */
1749
1750 // TODO: just get this from RNA?
1751 static int acf_dsarm_icon(bAnimListElem *ale)
1752 {
1753         return ICON_ARMATURE_DATA;
1754 }
1755
1756 /* get the appropriate flag(s) for the setting when it is valid  */
1757 static int acf_dsarm_setting_flag(int setting, short *neg)
1758 {
1759         /* clear extra return data first */
1760         *neg= 0;
1761         
1762         switch (setting) {
1763                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1764                         return ARM_DS_EXPAND;
1765                         
1766                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1767                         return ADT_NLA_EVAL_OFF;
1768                         
1769                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1770                         *neg= 1;
1771                         return ADT_CURVES_NOT_VISIBLE;
1772                         
1773                 case ACHANNEL_SETTING_SELECT: /* selected */
1774                         return ADT_UI_SELECTED;
1775                 
1776                 default: /* unsupported */
1777                         return 0;
1778         }
1779 }
1780
1781 /* get pointer to the setting */
1782 static void *acf_dsarm_setting_ptr(bAnimListElem *ale, int setting, short *type)
1783 {
1784         bArmature *arm= (bArmature *)ale->data;
1785         
1786         /* clear extra return data first */
1787         *type= 0;
1788         
1789         switch (setting) {
1790                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1791                         GET_ACF_FLAG_PTR(arm->flag);
1792                         
1793                 case ACHANNEL_SETTING_SELECT: /* selected */
1794                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1795                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1796                         if (arm->adt)
1797                                 GET_ACF_FLAG_PTR(arm->adt->flag)
1798                         else
1799                                 return NULL;
1800                 
1801                 default: /* unsupported */
1802                         return NULL;
1803         }
1804 }
1805
1806 /* metaball expander type define */
1807 static bAnimChannelType ACF_DSARM= 
1808 {
1809         acf_generic_dataexpand_color,   /* backdrop color */
1810         acf_generic_dataexpand_backdrop,/* backdrop */
1811         acf_generic_indention_1,                /* indent level */
1812         acf_generic_basic_offset,               /* offset */
1813         
1814         acf_generic_idblock_name,               /* name */
1815         acf_dsarm_icon,                         /* icon */
1816         
1817         acf_generic_dataexpand_setting_valid,   /* has setting */
1818         acf_dsarm_setting_flag,                                 /* flag for setting */
1819         acf_dsarm_setting_ptr                                   /* pointer for setting */
1820 };
1821
1822 /* NodeTree Expander  ------------------------------------------- */
1823
1824 // TODO: just get this from RNA?
1825 static int acf_dsntree_icon(bAnimListElem *ale)
1826 {
1827         return ICON_NODETREE;
1828 }
1829
1830 /* get the appropriate flag(s) for the setting when it is valid  */
1831 static int acf_dsntree_setting_flag(int setting, short *neg)
1832 {
1833         /* clear extra return data first */
1834         *neg= 0;
1835         
1836         switch (setting) {
1837                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1838                         return NTREE_DS_EXPAND;
1839                         
1840                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1841                         return ADT_NLA_EVAL_OFF;
1842                         
1843                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1844                         *neg= 1;
1845                         return ADT_CURVES_NOT_VISIBLE;
1846                         
1847                 case ACHANNEL_SETTING_SELECT: /* selected */
1848                         return ADT_UI_SELECTED;
1849                         
1850                 default: /* unsupported */
1851                         return 0;
1852         }
1853 }
1854
1855 /* get pointer to the setting */
1856 static void *acf_dsntree_setting_ptr(bAnimListElem *ale, int setting, short *type)
1857 {
1858         bNodeTree *ntree= (bNodeTree *)ale->data;
1859         
1860         /* clear extra return data first */
1861         *type= 0;
1862         
1863         switch (setting) {
1864                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1865                         GET_ACF_FLAG_PTR(ntree->flag);
1866                         
1867                 case ACHANNEL_SETTING_SELECT: /* selected */
1868                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1869                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1870                         if (ntree->adt)
1871                                 GET_ACF_FLAG_PTR(ntree->adt->flag)
1872                                 else
1873                                         return NULL;
1874                         
1875                 default: /* unsupported */
1876                         return NULL;
1877         }
1878 }
1879
1880 /* node tree expander type define */
1881 static bAnimChannelType ACF_DSNTREE= 
1882 {
1883         acf_generic_dataexpand_color,   /* backdrop color */
1884         acf_generic_dataexpand_backdrop,/* backdrop */
1885         acf_generic_indention_1,                /* indent level */              // XXX this only works for compositing
1886         acf_generic_basic_offset,               /* offset */
1887         
1888         acf_generic_idblock_name,               /* name */
1889         acf_dsntree_icon,                               /* icon */
1890         
1891         acf_generic_dataexpand_setting_valid,   /* has setting */
1892         acf_dsntree_setting_flag,                               /* flag for setting */
1893         acf_dsntree_setting_ptr                                 /* pointer for setting */
1894 };
1895
1896 /* Mesh Expander  ------------------------------------------- */
1897
1898 // TODO: just get this from RNA?
1899 static int acf_dsmesh_icon(bAnimListElem *ale)
1900 {
1901         return ICON_MESH_DATA;
1902 }
1903
1904 /* get the appropriate flag(s) for the setting when it is valid  */
1905 static int acf_dsmesh_setting_flag(int setting, short *neg)
1906 {
1907         /* clear extra return data first */
1908         *neg= 0;
1909         
1910         switch (setting) {
1911                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1912                         return ME_DS_EXPAND;
1913                         
1914                 case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1915                         return ADT_NLA_EVAL_OFF;
1916                         
1917                 case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1918                         *neg= 1;
1919                         return ADT_CURVES_NOT_VISIBLE;
1920                         
1921                 case ACHANNEL_SETTING_SELECT: /* selected */
1922                         return ADT_UI_SELECTED;
1923                         
1924                 default: /* unsupported */
1925                         return 0;
1926         }
1927 }
1928
1929 /* get pointer to the setting */
1930 static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, int setting, short *type)
1931 {
1932         Mesh *me= (Mesh *)ale->data;
1933         
1934         /* clear extra return data first */
1935         *type= 0;
1936         
1937         switch (setting) {
1938                 case ACHANNEL_SETTING_EXPAND: /* expanded */
1939                         GET_ACF_FLAG_PTR(me->flag);
1940                         
1941                 case ACHANNEL_SETTING_SELECT: /* selected */
1942                 case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
1943                 case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1944                         if (me->adt)
1945                                 GET_ACF_FLAG_PTR(me->adt->flag)
1946                                 else
1947                                         return NULL;
1948                         
1949                 default: /* unsupported */
1950                         return NULL;
1951         }
1952 }
1953
1954 /* node tree expander type define */
1955 static bAnimChannelType ACF_DSMESH= 
1956 {
1957         acf_generic_dataexpand_color,   /* backdrop color */
1958         acf_generic_dataexpand_backdrop,/* backdrop */
1959         acf_generic_indention_1,                /* indent level */              // XXX this only works for compositing
1960         acf_generic_basic_offset,               /* offset */
1961         
1962         acf_generic_idblock_name,               /* name */
1963         acf_dsmesh_icon,                                /* icon */
1964         
1965         acf_generic_dataexpand_setting_valid,   /* has setting */
1966         acf_dsmesh_setting_flag,                                /* flag for setting */
1967         acf_dsmesh_setting_ptr                                  /* pointer for setting */
1968 };
1969
1970 /* ShapeKey Entry  ------------------------------------------- */
1971
1972 /* name for ShapeKey */
1973 static void acf_shapekey_name(bAnimListElem *ale, char *name)
1974 {
1975         KeyBlock *kb= (KeyBlock *)ale->data;
1976         
1977         /* just copy the name... */
1978         if (kb && name) {
1979                 /* if the KeyBlock had a name, use it, otherwise use the index */
1980                 if (kb->name[0])
1981                         strcpy(name, kb->name);
1982                 else
1983                         sprintf(name, "Key %d", ale->index);
1984         }
1985 }
1986
1987 /* check if some setting exists for this channel */
1988 static short acf_shapekey_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
1989 {
1990         switch (setting) {
1991                 case ACHANNEL_SETTING_SELECT: /* selected */
1992                 case ACHANNEL_SETTING_MUTE: /* muted */
1993                 case ACHANNEL_SETTING_PROTECT: /* protected */
1994                         return 1;
1995                         
1996                 /* nothing else is supported */
1997                 default:
1998                         return 0;
1999         }
2000 }
2001
2002 /* get the appropriate flag(s) for the setting when it is valid  */
2003 static int acf_shapekey_setting_flag(int setting, short *neg)
2004 {
2005         /* clear extra return data first */
2006         *neg= 0;
2007         
2008         switch (setting) {
2009                 case ACHANNEL_SETTING_MUTE: /* mute */
2010                         return KEYBLOCK_MUTE;
2011                 
2012                 case ACHANNEL_SETTING_SELECT: /* selected */
2013                         return KEYBLOCK_SEL;
2014                 
2015                 case ACHANNEL_SETTING_PROTECT: /* locked */
2016                         return KEYBLOCK_LOCKED;
2017                 
2018                 default: /* unsupported */
2019                         return 0;
2020         }
2021 }
2022
2023 /* get pointer to the setting */
2024 static void *acf_shapekey_setting_ptr(bAnimListElem *ale, int setting, short *type)
2025 {
2026         KeyBlock *kb= (KeyBlock *)ale->data;
2027         
2028         /* clear extra return data first */
2029         *type= 0;
2030         
2031         switch (setting) {
2032                 case ACHANNEL_SETTING_SELECT: /* selected */
2033                 case ACHANNEL_SETTING_MUTE: /* muted */
2034                 case ACHANNEL_SETTING_PROTECT: /* protected */
2035                         GET_ACF_FLAG_PTR(kb->flag)
2036                 
2037                 default: /* unsupported */
2038                         return NULL;
2039         }
2040 }
2041
2042 /* shapekey expander type define */
2043 static bAnimChannelType ACF_SHAPEKEY= 
2044 {
2045         acf_generic_channel_color,              /* backdrop color */
2046         acf_generic_channel_backdrop,   /* backdrop */
2047         acf_generic_indention_0,                /* indent level */
2048         acf_generic_basic_offset,               /* offset */
2049         
2050         acf_shapekey_name,                              /* name */
2051         NULL,                                                   /* icon */
2052         
2053         acf_shapekey_setting_valid,             /* has setting */
2054         acf_shapekey_setting_flag,              /* flag for setting */
2055         acf_shapekey_setting_ptr                /* pointer for setting */
2056 };
2057
2058 /* Grease Pencil entries  ------------------------------------------- */
2059 // XXX ... this is currently not restored yet
2060
2061 #if 0
2062 static void dummy_olddraw_gpencil ()
2063 {
2064         /* determine what needs to be drawn */
2065         switch (ale->type) {
2066                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
2067                 {
2068                         bGPdata *gpd = (bGPdata *)ale->data;
2069                         ScrArea *sa = (ScrArea *)ale->owner;
2070                         
2071                         indent = 0;
2072                         group= 3;
2073                         
2074                         /* only show expand if there are any channels */
2075                         if (gpd->layers.first) {
2076                                 if (gpd->flag & GP_DATA_EXPAND)
2077                                         expand = ICON_TRIA_DOWN;
2078                                 else
2079                                         expand = ICON_TRIA_RIGHT;
2080                         }
2081                         
2082                         switch (sa->spacetype) {
2083                                 case SPACE_VIEW3D:
2084                                 {
2085                                         /* this shouldn't cause any overflow... */
2086                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
2087                                         strcpy(name, "3dView");
2088                                         special= ICON_VIEW3D;
2089                                 }
2090                                         break;
2091                                 case SPACE_NODE:
2092                                 {
2093                                         SpaceNode *snode= sa->spacedata.first;
2094                                         char treetype[12];
2095                                         
2096                                         if (snode->treetype == 1)
2097                                                 strcpy(treetype, "Composite");
2098                                         else
2099                                                 strcpy(treetype, "Material");
2100                                         sprintf(name, "Nodes:%s", treetype);
2101                                         
2102                                         special= ICON_NODETREE;
2103                                 }
2104                                         break;
2105                                 case SPACE_SEQ:
2106                                 {
2107                                         SpaceSeq *sseq= sa->spacedata.first;
2108                                         char imgpreview[10];
2109                                         
2110                                         switch (sseq->mainb) {
2111                                                 case 1:         sprintf(imgpreview, "Image...");        break;
2112                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
2113                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
2114                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
2115                                                 
2116                                                 default:        sprintf(imgpreview, "Sequence");        break;
2117                                         }
2118                                         sprintf(name, "Sequencer:%s", imgpreview);
2119                                         
2120                                         special= ICON_SEQUENCE;
2121                                 }
2122                                         break;
2123                                 case SPACE_IMAGE:
2124                                 {
2125                                         SpaceImage *sima= sa->spacedata.first;
2126                                         
2127                                         if (sima->image)
2128                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
2129                                         else
2130                                                 strcpy(name, "Image:<None>");
2131                                                 
2132                                         special= ICON_IMAGE_COL;
2133                                 }
2134                                         break;
2135                                 
2136                                 default:
2137                                 {
2138                                         sprintf(name, "<Unknown GP-Data Source>");
2139                                         special= -1;
2140                                 }
2141                                         break;
2142                         }
2143                 }
2144                         break;
2145                 case ANIMTYPE_GPLAYER: /* gpencil layer */
2146                 {
2147                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
2148                         
2149                         indent = 0;
2150                         special = -1;
2151                         expand = -1;
2152                         group = 1;
2153                         
2154                         if (EDITABLE_GPL(gpl))
2155                                 protect = ICON_UNLOCKED;
2156                         else
2157                                 protect = ICON_LOCKED;
2158                                 
2159                         if (gpl->flag & GP_LAYER_HIDE)
2160                                 mute = ICON_MUTE_IPO_ON;
2161                         else
2162                                 mute = ICON_MUTE_IPO_OFF;
2163                         
2164                         sel = SEL_GPL(gpl);
2165                         BLI_snprintf(name, 32, gpl->info);
2166                 }
2167                         break;
2168         }       
2169         
2170         if (group == 3) {
2171                 /* only for gp-data channels */
2172                 UI_ThemeColorShade(TH_GROUP, 20);
2173                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
2174                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
2175         }
2176 }
2177 #endif
2178
2179 /* *********************************************** */
2180 /* Type Registration and General Access */
2181
2182 /* These globals only ever get directly accessed in this file */
2183 static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES];
2184 static short ACF_INIT= 1; /* when non-zero, the list needs to be updated */
2185
2186 /* Initialise type info definitions */
2187 void ANIM_init_channel_typeinfo_data (void)
2188 {
2189         int type= 0;
2190         
2191         /* start initialising if necessary... */
2192         if (ACF_INIT) {
2193                 ACF_INIT= 0;
2194                 
2195                 animchannelTypeInfo[type++]= NULL;                              /* None */
2196                 animchannelTypeInfo[type++]= NULL;                              /* AnimData */
2197                 animchannelTypeInfo[type++]= NULL;                              /* Special */
2198                 
2199                 animchannelTypeInfo[type++]= &ACF_SUMMARY;              /* Motion Summary */
2200                 
2201                 animchannelTypeInfo[type++]= &ACF_SCENE;                /* Scene */
2202                 animchannelTypeInfo[type++]= &ACF_OBJECT;               /* Object */
2203                 animchannelTypeInfo[type++]= &ACF_GROUP;                /* Group */
2204                 animchannelTypeInfo[type++]= &ACF_FCURVE;               /* F-Curve */
2205                 
2206                 animchannelTypeInfo[type++]= &ACF_FILLACTD;     /* Object Action Expander */
2207                 animchannelTypeInfo[type++]= &ACF_FILLDRIVERS;  /* Drivers Expander */
2208                 animchannelTypeInfo[type++]= &ACF_FILLMATD;     /* Materials Expander */
2209                 animchannelTypeInfo[type++]= &ACF_FILLPARTD;    /* Particles Expander */
2210                 
2211                 animchannelTypeInfo[type++]= &ACF_DSMAT;                /* Material Channel */
2212                 animchannelTypeInfo[type++]= &ACF_DSLAM;                /* Lamp Channel */
2213                 animchannelTypeInfo[type++]= &ACF_DSCAM;                /* Camera Channel */
2214                 animchannelTypeInfo[type++]= &ACF_DSCUR;                /* Curve Channel */
2215                 animchannelTypeInfo[type++]= &ACF_DSSKEY;               /* ShapeKey Channel */
2216                 animchannelTypeInfo[type++]= &ACF_DSWOR;                /* World Channel */
2217                 animchannelTypeInfo[type++]= &ACF_DSNTREE;              /* NodeTree Channel */
2218                 animchannelTypeInfo[type++]= &ACF_DSPART;               /* Particle Channel */
2219                 animchannelTypeInfo[type++]= &ACF_DSMBALL;              /* MetaBall Channel */
2220                 animchannelTypeInfo[type++]= &ACF_DSARM;                /* Armature Channel */
2221                 animchannelTypeInfo[type++]= &ACF_DSMESH;               /* Mesh Channel */
2222                 
2223                 animchannelTypeInfo[type++]= &ACF_SHAPEKEY;             /* ShapeKey */
2224                 
2225                         // XXX not restored yet
2226                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Datablock */ 
2227                 animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Layer */ 
2228                 
2229                         // TODO: these types still need to be implemented!!!
2230                         // probably need a few extra flags for these special cases...
2231                 animchannelTypeInfo[type++]= NULL;                              /* NLA Track */ 
2232                 animchannelTypeInfo[type++]= NULL;                              /* NLA Action */ 
2233         }
2234
2235
2236 /* Get type info from given channel type */
2237 bAnimChannelType *ANIM_channel_get_typeinfo (bAnimListElem *ale)
2238 {
2239         /* santiy checks */
2240         if (ale == NULL)
2241                 return NULL;
2242                 
2243         /* init the typeinfo if not available yet... */
2244         ANIM_init_channel_typeinfo_data();
2245         
2246         /* check if type is in bounds... */
2247         if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES))
2248                 return animchannelTypeInfo[ale->type];
2249         else
2250                 return NULL;
2251 }
2252
2253 /* --------------------------- */
2254
2255 /* Check if some setting for a channel is enabled 
2256  * Returns: 1 = On, 0 = Off, -1 = Invalid
2257  */
2258 short ANIM_channel_setting_get (bAnimContext *ac, bAnimListElem *ale, int setting)
2259 {
2260         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2261         
2262         /* 1) check that the setting exists for the current context */
2263         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
2264         {
2265                 /* 2) get pointer to check for flag in, and the flag to check for */
2266                 short negflag, ptrsize;
2267                 int flag;
2268                 void *ptr;
2269                 
2270                 flag= acf->setting_flag(setting, &negflag);
2271                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
2272                 
2273                 /* check if flag is enabled */
2274                 if (ptr && flag) {
2275                         switch (ptrsize) {
2276                                 case sizeof(int):       /* integer pointer for setting */
2277                                 {
2278                                         int *val= (int *)ptr;
2279                                         
2280                                         if (negflag)
2281                                                 return ((*val) & flag) == 0;
2282                                         else
2283                                                 return ((*val) & flag) != 0;
2284                                 }
2285                                         break;
2286                                         
2287                                 case sizeof(short):     /* short pointer for setting */
2288                                 {
2289                                         short *val= (short *)ptr;
2290                                         
2291                                         if (negflag)
2292                                                 return ((*val) & flag) == 0;
2293                                         else
2294                                                 return ((*val) & flag) != 0;
2295                                 }
2296                                         break;
2297                                         
2298                                 case sizeof(char):      /* char pointer for setting */
2299                                 {
2300                                         char *val= (char *)ptr;
2301                                         
2302                                         if (negflag)
2303                                                 return ((*val) & flag) == 0;
2304                                         else
2305                                                 return ((*val) & flag) != 0;
2306                                 }
2307                                         break;
2308                         }
2309                 }
2310         }
2311         
2312         /* not found... */
2313         return -1;
2314 }       
2315
2316
2317 /* quick macro for use in ANIM_channel_setting_set - set flag for setting according the mode given */
2318 #define ACF_SETTING_SET(sval, sflag, smode) \
2319         {\
2320                 if (negflag) {\
2321                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
2322                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) &= ~(sflag); \
2323                         else                                                                    (sval) |= (sflag); \
2324                 } \
2325                 else {\
2326                         if (smode == ACHANNEL_SETFLAG_TOGGLE)   (sval) ^= (sflag); \
2327                         else if (smode == ACHANNEL_SETFLAG_ADD) (sval) |= (sflag); \
2328                         else                                                                    (sval) &= ~(sflag); \
2329                 }\
2330         }
2331
2332 /* Change value of some setting for a channel 
2333  *      - setting: eAnimChannel_Settings
2334  *      - mode: eAnimChannels_SetFlag
2335  */
2336 void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting, short mode)
2337 {
2338         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2339         
2340         /* 1) check that the setting exists for the current context */
2341         if ( (acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting)) ) 
2342         {
2343                 /* 2) get pointer to check for flag in, and the flag to check for */
2344                 short negflag, ptrsize;
2345                 int flag;
2346                 void *ptr;
2347                 
2348                 flag= acf->setting_flag(setting, &negflag);
2349                 ptr= acf->setting_ptr(ale, setting, &ptrsize);
2350                 
2351                 /* check if flag is enabled */
2352                 if (ptr && flag) {
2353                         switch (ptrsize) {
2354                                 case sizeof(int):       /* integer pointer for setting */
2355                                 {
2356                                         int *val= (int *)ptr;
2357                                         ACF_SETTING_SET(*val, flag, mode);
2358                                 }
2359                                         break;
2360                                         
2361                                 case sizeof(short):     /* short pointer for setting */
2362                                 {
2363                                         short *val= (short *)ptr;
2364                                         ACF_SETTING_SET(*val, flag, mode);
2365                                 }
2366                                         break;
2367                                         
2368                                 case sizeof(char):      /* char pointer for setting */
2369                                 {
2370                                         char *val= (char *)ptr;
2371                                         ACF_SETTING_SET(*val, flag, mode);
2372                                 }
2373                                         break;
2374                         }
2375                 }
2376         }
2377 }
2378
2379 /* --------------------------- */
2380
2381 // XXX hardcoded size of icons
2382 #define ICON_WIDTH              17
2383 // XXX hardcoded width of sliders
2384 #define SLIDER_WIDTH    80
2385
2386 /* Draw the given channel */
2387 // TODO: make this use UI controls for the buttons
2388 void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
2389 {
2390         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2391         View2D *v2d= &ac->ar->v2d;
2392         short selected, offset;
2393         float y, ymid, ytext;
2394         
2395         /* sanity checks - don't draw anything */
2396         if ELEM(NULL, acf, ale)
2397                 return;
2398         
2399         /* get initial offset */
2400         if (acf->get_offset)
2401                 offset= acf->get_offset(ac, ale);
2402         else
2403                 offset= 0;
2404                 
2405         /* calculate appropriate y-coordinates for icon buttons 
2406          *      7 is hardcoded factor for half-height of icons
2407          */
2408         y= (ymaxc - yminc)/2 + yminc;
2409         ymid= y - 7;
2410         /* y-coordinates for text is only 4 down from middle */
2411         ytext= y - 4;
2412         
2413         /* check if channel is selected */
2414         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
2415                 selected= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
2416         else
2417                 selected= 0;
2418                 
2419         /* set blending again, as may not be set in previous step */
2420         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2421         glEnable(GL_BLEND);
2422         
2423         /* step 1) draw backdrop ...........................................  */
2424         if (acf->draw_backdrop)
2425                 acf->draw_backdrop(ac, ale, yminc, ymaxc);
2426                 
2427         /* step 2) draw expand widget ....................................... */
2428         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
2429                 /* just skip - drawn as widget now */
2430                 offset += ICON_WIDTH; 
2431         }
2432                 
2433         /* step 3) draw icon ............................................... */
2434         if (acf->icon) {
2435                 UI_icon_draw(offset, ymid, acf->icon(ale));
2436                 offset += ICON_WIDTH; 
2437         }
2438         
2439         /* turn off blending, since not needed anymore... */
2440         glDisable(GL_BLEND);
2441                 
2442         /* step 4) draw special toggles  .................................
2443          *      - in Graph Editor, checkboxes for visibility in curves area
2444          *      - in NLA Editor, glowing dots for solo/not solo...
2445          */
2446         if (ac->sa) {
2447                 if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
2448                         /* for F-Curves, draw color-preview of curve behind checkbox */
2449                         if (ale->type == ANIMTYPE_FCURVE) {
2450                                 FCurve *fcu= (FCurve *)ale->data;
2451                                 
2452                                 /* F-Curve channels need to have a special 'color code' box drawn, which is colored with whatever 
2453                                  * color the curve has stored 
2454                                  */
2455                                 glColor3fv(fcu->color);
2456                                 
2457                                 /* just a solid color rect
2458                                  *      hardcoded 17 pixels width is slightly wider than icon width, so that 
2459                                  *      there's a slight border around it 
2460                                  */
2461                                 glRectf(offset, yminc, offset+17, ymaxc);
2462                         }
2463                         
2464                         /* icon is drawn as widget now... */
2465                         offset += ICON_WIDTH; 
2466                 }
2467                 else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
2468                         /* just skip - drawn as widget now */
2469                         offset += ICON_WIDTH; 
2470                 }
2471         }
2472         
2473         /* step 5) draw name ............................................... */
2474         if (acf->name) {
2475                 char name[256]; /* hopefully this will be enough! */
2476                 
2477                 /* set text color */
2478                 if (selected)
2479                         UI_ThemeColor(TH_TEXT_HI);
2480                 else
2481                         UI_ThemeColor(TH_TEXT);
2482                         
2483                 /* get name */
2484                 acf->name(ale, name);
2485                 
2486                 offset += 3;
2487                 UI_DrawString(offset, ytext, name);
2488         }
2489         
2490         /* step 6) draw backdrops behidn mute+protection toggles + (sliders) ....................... */
2491         /* reset offset - now goes from RHS of panel */
2492         offset = 0;
2493         
2494         // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
2495         
2496         if (v2d) {
2497                 short draw_sliders = 0;
2498                 float color[3];
2499                 
2500                 /* get and set backdrop color */
2501                 acf->get_backdrop_color(ac, ale, color);
2502                 glColor3fv(color);
2503                 
2504                 /* check if we need to show the sliders */
2505                 if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
2506                         switch (ac->spacetype) {
2507                                 case SPACE_ACTION:
2508                                 {
2509                                         SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
2510                                         draw_sliders= (saction->flag & SACTION_SLIDERS);
2511                                 }
2512                                         break;
2513                                 case SPACE_IPO:
2514                                 {
2515                                         SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
2516                                         draw_sliders= (sipo->flag & SIPO_SLIDERS);
2517                                 }
2518                                         break;
2519                         }
2520                 }
2521                 
2522                 /* check if there's enough space for the toggles if the sliders are drawn too */
2523                 if ( !(draw_sliders) || ((v2d->mask.xmax-v2d->mask.xmin) > ACHANNEL_BUTTON_WIDTH/2) ) {
2524                         /* protect... */
2525                         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT))
2526                                 offset += ICON_WIDTH;
2527                         /* mute... */
2528                         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE))
2529                                 offset += ICON_WIDTH;
2530                 }
2531                 
2532                 /* draw slider
2533                  *      - even if we can draw sliders for this view, we must also check that the channel-type supports them
2534                  *        (only only F-Curves really can support them for now)
2535                  *      - slider should start before the toggles (if they're visible) to keep a clean line down the side
2536                  */
2537                 if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) {
2538                         /* adjust offset */
2539                         offset += SLIDER_WIDTH;
2540                 }
2541                 
2542                 
2543                 /* finally draw a backdrop rect behind these 
2544                  *      - starts from the point where the first toggle/slider starts, 
2545                  *      - ends past the space that might be reserved for a scroller
2546                  */
2547                 glRectf(v2d->cur.xmax-(float)offset, yminc, v2d->cur.xmax+EXTRA_SCROLL_PAD, ymaxc);
2548         }
2549 }
2550
2551 /* ------------------ */
2552
2553 /* callback for (normal) widget settings - send notifiers */
2554 static void achannel_setting_widget_cb(bContext *C, void *poin, void *poin2)
2555 {
2556         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2557 }
2558
2559 /* callback for widget settings that need flushing */
2560 static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void *setting_wrap)
2561 {
2562         bAnimListElem *ale_setting= (bAnimListElem *)ale_npoin;
2563         bAnimContext ac;
2564         ListBase anim_data = {NULL, NULL};
2565         int filter;
2566         int setting = GET_INT_FROM_POINTER(setting_wrap);
2567         short on = 0;
2568         
2569         /* send notifiers before doing anything else... */
2570         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2571         
2572         /* verify animation context */
2573         if (ANIM_animdata_get_context(C, &ac) == 0)
2574                 return;
2575         
2576         /* verify that we have a channel to operate on, and that it has all we need */
2577         if (ale_setting) {
2578                 /* check if the setting is on... */
2579                 on= ANIM_channel_setting_get(&ac, ale_setting, setting);
2580                 
2581                 /* on == -1 means setting not found... */
2582                 if (on == -1)
2583                         return;
2584         }
2585         else
2586                 return;
2587         
2588         /* get all channels that can possibly be chosen 
2589          *      - therefore, the filter is simply ANIMFILTER_CHANNELS, since if we took VISIBLE too,
2590          *        then the channels under closed expanders get ignored...
2591          */
2592         filter= ANIMFILTER_CHANNELS;
2593         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
2594         
2595         /* call API method to flush the setting */
2596         ANIM_flush_setting_anim_channels(&ac, &anim_data, ale_setting, setting, on);
2597         
2598         /* free temp data */
2599         BLI_freelistN(&anim_data);
2600 }
2601
2602 /* callback for widget sliders - insert keyframes */
2603 static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
2604 {
2605         ID *id= (ID *)id_poin;
2606         FCurve *fcu= (FCurve *)fcu_poin;
2607         
2608         Scene *scene= CTX_data_scene(C);
2609         PointerRNA id_ptr, ptr;
2610         PropertyRNA *prop;
2611         short flag=0, done=0;
2612         float cfra;
2613         
2614         /* get current frame */
2615         // NOTE: this will do for now...
2616         cfra= (float)CFRA;
2617         
2618         /* get flags for keyframing */
2619         flag = ANIM_get_keyframing_flags(scene, 1);
2620         
2621         /* get RNA pointer, and resolve the path */
2622         RNA_id_pointer_create(id, &id_ptr);
2623         
2624         /* try to resolve the path stored in the F-Curve */
2625         if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) {
2626                 /* set the special 'replace' flag if on a keyframe */
2627                 if (fcurve_frame_has_keyframe(fcu, cfra, 0))
2628                         flag |= INSERTKEY_REPLACE;
2629                 
2630                 /* insert a keyframe for this F-Curve */
2631                 done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
2632                 
2633                 if (done)
2634                         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2635         }
2636 }
2637
2638 /* callback for shapekey widget sliders - insert keyframes */
2639 static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin)
2640 {
2641         Key *key= (Key *)key_poin;
2642         KeyBlock *kb= (KeyBlock *)kb_poin;
2643         char *rna_path= key_get_curValue_rnaPath(key, kb);
2644         
2645         Scene *scene= CTX_data_scene(C);
2646         PointerRNA id_ptr, ptr;
2647         PropertyRNA *prop;
2648         short flag=0, done=0;
2649         float cfra;
2650         
2651         /* get current frame */
2652         // NOTE: this will do for now...
2653         cfra= (float)CFRA;
2654         
2655         /* get flags for keyframing */
2656         flag = ANIM_get_keyframing_flags(scene, 1);
2657         
2658         /* get RNA pointer, and resolve the path */
2659         RNA_id_pointer_create((ID *)key, &id_ptr);
2660         
2661         /* try to resolve the path stored in the F-Curve */
2662         if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
2663                 /* find or create new F-Curve */
2664                 // XXX is the group name for this ok?
2665                 bAction *act= verify_adt_action((ID *)key, 1);
2666                 FCurve *fcu= verify_fcurve(act, NULL, rna_path, 0, 1);
2667                 
2668                 /* set the special 'replace' flag if on a keyframe */
2669                 if (fcurve_frame_has_keyframe(fcu, cfra, 0))
2670                         flag |= INSERTKEY_REPLACE;
2671                 
2672                 /* insert a keyframe for this F-Curve */
2673                 done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
2674                 
2675                 if (done)
2676                         WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
2677         }
2678         
2679         /* free the path */
2680         if (rna_path)
2681                 MEM_freeN(rna_path);
2682 }
2683
2684 /* Draw a widget for some setting */
2685 static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting)
2686 {
2687         short negflag, ptrsize, enabled, butType;
2688         int flag, icon;
2689         void *ptr;
2690         char *tooltip;
2691         uiBut *but = NULL;
2692         
2693         /* get the flag and the pointer to that flag */
2694         flag= acf->setting_flag(setting, &negflag);
2695         ptr= acf->setting_ptr(ale, setting, &ptrsize);
2696         enabled= ANIM_channel_setting_get(ac, ale, setting);
2697         
2698         /* get the base icon for the setting */
2699         switch (setting) {
2700                 case ACHANNEL_SETTING_VISIBLE:  /* visibility checkboxes */
2701                         //icon= ((enabled)? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT);
2702                         icon= ICON_CHECKBOX_DEHLT;
2703                         
2704                         if (ale->type == ANIMTYPE_FCURVE)
2705                                 tooltip= "Channel is visible in Graph Editor for editing.";
2706                         else
2707                                 tooltip= "Channel(s) are visible in Graph Editor for editing.";
2708                         break;
2709                         
2710                 case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
2711                         //icon= ((enabled)? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
2712                         icon= ICON_TRIA_RIGHT;
2713                         tooltip= "Make channels grouped under this channel visible.";
2714                         break;
2715                         
2716                 case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */
2717                         //icon= ((enabled)? ICON_LAYER_ACTIVE : ICON_LAYER_USED);
2718                         icon= ICON_LAYER_USED;
2719                         tooltip= "NLA Track is the only one evaluated for the AnimData block it belongs to.";
2720                         break;
2721                 
2722                 /* --- */
2723                 
2724                 case ACHANNEL_SETTING_PROTECT: /* protected lock */
2725                         // TODO: what about when there's no protect needed?
2726                         //icon= ((enabled)? ICON_LOCKED : ICON_UNLOCKED);
2727                         icon= ICON_UNLOCKED;
2728                         tooltip= "Editability of keyframes for this channel.";
2729                         break;
2730                         
2731                 case ACHANNEL_SETTING_MUTE: /* muted eye */
2732                         //icon= ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
2733                         icon= ICON_MUTE_IPO_OFF;
2734                         
2735                         if (ale->type == ALE_FCURVE) 
2736                                 tooltip= "Does F-Curve contribute to result.";
2737                         else
2738                                 tooltip= "Do channels contribute to result.";
2739                         break;
2740                         
2741                 default:
2742                         tooltip= NULL;
2743                         icon= 0;
2744                         break;
2745         }
2746         
2747         /* type of button */
2748         if (negflag)
2749                 butType= ICONTOGN;
2750         else
2751                 butType= ICONTOG;
2752         
2753         /* draw button for setting */
2754         if (ptr && flag) {
2755                 switch (ptrsize) {
2756                         case sizeof(int):       /* integer pointer for setting */
2757                                 but= uiDefIconButBitI(block, butType, flag, 0, icon, 
2758                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2759                                 break;
2760                                 
2761                         case sizeof(short):     /* short pointer for setting */
2762                                 but= uiDefIconButBitS(block, butType, flag, 0, icon, 
2763                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2764                                 break;
2765                                 
2766                         case sizeof(char):      /* char pointer for setting */
2767                                 but= uiDefIconButBitC(block, butType, flag, 0, icon, 
2768                                                 xpos, ypos, ICON_WIDTH, ICON_WIDTH, ptr, 0, 0, 0, 0, tooltip);
2769                                 break;
2770                 }
2771                 
2772                 /* set call to send relevant notifiers and/or perform type-specific updates */
2773                 if (but) {
2774                         switch (setting) {
2775                                 /* settings needing flushing up/down hierarchy  */
2776                                 case ACHANNEL_SETTING_VISIBLE: /* Graph Editor - 'visibility' toggles */
2777                                 case ACHANNEL_SETTING_PROTECT: /* General - protection flags */
2778                                 case ACHANNEL_SETTING_MUTE: /* General - muting flags */
2779                                         uiButSetNFunc(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting));
2780                                         break;
2781                                         
2782                                 /* no flushing */
2783                                 case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush, otherwise all would open/close at once */
2784                                 default:
2785                                         uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
2786                         }
2787                 }
2788         }
2789 }
2790
2791 /* Draw UI widgets the given channel */
2792 // TODO: make this use UI controls for the buttons
2793 void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *block, float yminc, float ymaxc)
2794 {
2795         bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
2796         View2D *v2d= &ac->ar->v2d;
2797         float y, ymid, ytext;
2798         short offset;
2799         
2800         /* sanity checks - don't draw anything */
2801         if ELEM3(NULL, acf, ale, block)
2802                 return;
2803         
2804         /* get initial offset */
2805         if (acf->get_offset)
2806                 offset= acf->get_offset(ac, ale);
2807         else
2808                 offset= 0;
2809                 
2810         /* calculate appropriate y-coordinates for icon buttons 
2811          *      7 is hardcoded factor for half-height of icons
2812          */
2813         y= (ymaxc - yminc)/2 + yminc;
2814         ymid= y - 7;
2815         /* y-coordinates for text is only 4 down from middle */
2816         ytext= y - 4;
2817         
2818         /* no button backdrop behind icons */
2819         uiBlockSetEmboss(block, UI_EMBOSSN);
2820         
2821         /* step 1) draw expand widget ....................................... */
2822         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
2823                 draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_EXPAND);
2824                 offset += ICON_WIDTH; 
2825         }
2826                 
2827         /* step 2) draw icon ............................................... */
2828         if (acf->icon) {
2829                 /* icon is not drawn here (not a widget) */
2830                 offset += ICON_WIDTH; 
2831         }
2832                 
2833         /* step 3) draw special toggles  .................................
2834          *      - in Graph Editor, checkboxes for visibility in curves area
2835          *      - in NLA Editor, glowing dots for solo/not solo...
2836          */
2837         if (ac->sa) {
2838                 if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
2839                         /* visibility toggle  */
2840                         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
2841                         offset += ICON_WIDTH; 
2842                 }
2843                 else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
2844                         /* 'solo' setting for NLA Tracks */
2845                         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
2846                         offset += ICON_WIDTH; 
2847                 }
2848         }
2849         
2850         /* step 4) draw text... */
2851         /* NOTE: this is not done here, since nothing to be clicked on... */
2852         
2853         /* step 5) draw mute+protection toggles + (sliders) ....................... */
2854         /* reset offset - now goes from RHS of panel */
2855         offset = 0;
2856         
2857         // TODO: when drawing sliders, make those draw instead of these toggles if not enough space
2858         
2859         if (v2d) {
2860                 short draw_sliders = 0;
2861                 
2862                 /* check if we need to show the sliders */
2863                 if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
2864                         switch (ac->spacetype) {
2865                                 case SPACE_ACTION:
2866                                 {
2867                                         SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
2868                                         draw_sliders= (saction->flag & SACTION_SLIDERS);
2869                                 }
2870                                         break;
2871                                 case SPACE_IPO:
2872                                 {
2873                                         SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
2874                                         draw_sliders= (sipo->flag & SIPO_SLIDERS);
2875                                 }
2876                                         break;
2877                         }
2878                 }
2879                 
2880                 /* check if there's enough space for the toggles if the sliders are drawn too */
2881                 if ( !(draw_sliders) || ((v2d->mask.xmax-v2d->mask.xmin) > ACHANNEL_BUTTON_WIDTH/2) ) {
2882                         /* protect... */
2883                         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
2884                                 offset += ICON_WIDTH; 
2885                                 draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_PROTECT);
2886                         }
2887                         /* mute... */
2888                         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
2889                                 offset += ICON_WIDTH;
2890                                 draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax-offset, ymid, ACHANNEL_SETTING_MUTE);
2891                         }
2892                 }
2893                 
2894                 /* draw slider
2895                  *      - even if we can draw sliders for this view, we must also check that the channel-type supports them
2896                  *        (only only F-Curves really can support them for now)
2897                  *      - to make things easier, we use RNA-autobuts for this so that changes are reflected immediately, 
2898                  *        whereever they occurred. BUT, we don't use the layout engine, otherwise we'd get wrong alignment,
2899                  *        and wouldn't be able to auto-keyframe...
2900                  *      - slider should start before the toggles (if they're visible) to keep a clean line down the side
2901                  */
2902                 if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) {
2903                         /* adjust offset */
2904                         offset += SLIDER_WIDTH;
2905                         
2906                         /* need backdrop behind sliders... */
2907                         uiBlockSetEmboss(block, UI_EMBOSS);
2908                         
2909                         if (ale->id) { /* Slider using RNA Access -------------------- */
2910                                 PointerRNA id_ptr, ptr;
2911                                 PropertyRNA *prop;
2912                                 char *rna_path = NULL;
2913                                 int array_index = 0;
2914                                 short free_path = 0;
2915                                 
2916                                 /* get destination info */
2917                                 if (ale->type == ANIMTYPE_FCURVE) {
2918                                         FCurve *fcu= (FCurve *)ale->data;
2919                                         
2920                                         rna_path= fcu->rna_path;
2921                                         array_index= fcu->array_index;
2922                                 }
2923                                 else if (ale->type == ANIMTYPE_SHAPEKEY) {
2924                                         KeyBlock *kb= (KeyBlock *)ale->data;
2925                                         Key *key= (Key *)ale->id;
2926                                         
2927                                         rna_path= key_get_curValue_rnaPath(key, kb);
2928                                         free_path= 1;
2929                                 }
2930                                 
2931                                 /* only if RNA-Path found */
2932                                 if (rna_path) {
2933                                         /* get RNA pointer, and resolve the path */
2934                                         RNA_id_pointer_create(ale->id, &id_ptr);
2935                                         
2936                                         /* try to resolve the path */
2937                                         if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
2938                                                 uiBut *but;
2939                                                 
2940                                                 /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
2941                                                 but= uiDefAutoButR(block, &ptr, prop, array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
2942                                                 
2943                                                 /* assign keyframing function according to slider type */
2944                                                 if (ale->type == ANIMTYPE_SHAPEKEY)
2945                                                         uiButSetFunc(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
2946                                                 else
2947                                                         uiButSetFunc(but, achannel_setting_slider_cb, ale->id, ale->data);
2948                                         }
2949                                         
2950                                         /* free the path if necessary */
2951                                         if (free_path)
2952                                                 MEM_freeN(rna_path);
2953                                 }
2954                         }
2955                         else { /* Special Slider for stuff without RNA Access ---------- */
2956                                 // TODO: only implement this case when we really need it...
2957                         }
2958                 }
2959         }
2960 }
2961
2962 /* *********************************************** */