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