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