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