a17ee820595cad9385777e8eaf8c6e44059d92c2
[blender.git] / source / blender / editors / animation / anim_channels_defines.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edanimation
22  */
23
24 #include <stdio.h>
25
26 #include "MEM_guardedalloc.h"
27
28 #include "BLI_blenlib.h"
29 #include "BLI_math.h"
30 #include "BLI_utildefines.h"
31
32 #include "BLT_translation.h"
33
34 #include "DNA_anim_types.h"
35 #include "DNA_armature_types.h"
36 #include "DNA_cachefile_types.h"
37 #include "DNA_camera_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_particle_types.h"
40 #include "DNA_screen_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_space_types.h"
43 #include "DNA_key_types.h"
44 #include "DNA_light_types.h"
45 #include "DNA_lattice_types.h"
46 #include "DNA_linestyle_types.h"
47 #include "DNA_mesh_types.h"
48 #include "DNA_material_types.h"
49 #include "DNA_meta_types.h"
50 #include "DNA_node_types.h"
51 #include "DNA_world_types.h"
52 #include "DNA_gpencil_types.h"
53 #include "DNA_speaker_types.h"
54 #include "DNA_mask_types.h"
55
56 #include "RNA_access.h"
57
58 #include "BKE_animsys.h"
59 #include "BKE_curve.h"
60 #include "BKE_gpencil.h"
61 #include "BKE_key.h"
62 #include "BKE_main.h"
63 #include "BKE_nla.h"
64 #include "BKE_context.h"
65
66 #include "GPU_immediate.h"
67 #include "GPU_state.h"
68
69 #include "DEG_depsgraph.h"
70
71 #include "UI_interface.h"
72 #include "UI_interface_icons.h"
73 #include "UI_resources.h"
74
75 #include "ED_anim_api.h"
76 #include "ED_keyframing.h"
77
78 #include "WM_api.h"
79 #include "WM_types.h"
80
81 /* *********************************************** */
82 // XXX constant defines to be moved elsewhere?
83
84 /* extra padding for lengths (to go under scrollers) */
85 #define EXTRA_SCROLL_PAD 100.0f
86
87 /* size of indent steps */
88 #define INDENT_STEP_SIZE (0.35f * U.widget_unit)
89
90 /* size of string buffers used for animation channel displayed names */
91 #define ANIM_CHAN_NAME_SIZE 256
92
93 /* get the pointer used for some flag */
94 #define GET_ACF_FLAG_PTR(ptr, type) ((*(type) = sizeof((ptr))), &(ptr))
95
96 /* *********************************************** */
97 /* Generic Functions (Type independent) */
98
99 /* Draw Backdrop ---------------------------------- */
100
101 /* get backdrop color for top-level widgets (Scene and Object only) */
102 static void acf_generic_root_color(bAnimContext *UNUSED(ac),
103                                    bAnimListElem *UNUSED(ale),
104                                    float r_color[3])
105 {
106   /* darker blue for top-level widgets */
107   UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, r_color);
108 }
109
110 /* backdrop for top-level widgets (Scene and Object only) */
111 static void acf_generic_root_backdrop(bAnimContext *ac,
112                                       bAnimListElem *ale,
113                                       float yminc,
114                                       float ymaxc)
115 {
116   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
117   View2D *v2d = &ac->ar->v2d;
118   short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
119   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
120   float color[3];
121
122   /* set backdrop drawing color */
123   acf->get_backdrop_color(ac, ale, color);
124
125   /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
126   UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT :
127                                            (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
128   UI_draw_roundbox_3fvAlpha(
129       true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
130 }
131
132 /* get backdrop color for data expanders under top-level Scene/Object */
133 static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac),
134                                          bAnimListElem *UNUSED(ale),
135                                          float r_color[3])
136 {
137   /* lighter color than top-level widget */
138   UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, r_color);
139 }
140
141 /* backdrop for data expanders under top-level Scene/Object */
142 static void acf_generic_dataexpand_backdrop(bAnimContext *ac,
143                                             bAnimListElem *ale,
144                                             float yminc,
145                                             float ymaxc)
146 {
147   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
148   View2D *v2d = &ac->ar->v2d;
149   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
150   float color[3];
151
152   uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
153
154   /* set backdrop drawing color */
155   acf->get_backdrop_color(ac, ale, color);
156
157   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
158   immUniformColor3fv(color);
159
160   /* no rounded corner - just rectangular box */
161   immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
162
163   immUnbindProgram();
164 }
165
166 /* helper method to test if group colors should be drawn */
167 static bool acf_show_channel_colors(bAnimContext *ac)
168 {
169   bool showGroupColors = false;
170
171   if (ac->sl) {
172     switch (ac->spacetype) {
173       case SPACE_ACTION: {
174         SpaceAction *saction = (SpaceAction *)ac->sl;
175         showGroupColors = !(saction->flag & SACTION_NODRAWGCOLORS);
176
177         break;
178       }
179       case SPACE_GRAPH: {
180         SpaceGraph *sipo = (SpaceGraph *)ac->sl;
181         showGroupColors = !(sipo->flag & SIPO_NODRAWGCOLORS);
182
183         break;
184       }
185     }
186   }
187
188   return showGroupColors;
189 }
190
191 /* get backdrop color for generic channels */
192 static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
193 {
194   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
195   bActionGroup *grp = NULL;
196   short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
197   bool showGroupColors = acf_show_channel_colors(ac);
198
199   if (ale->type == ANIMTYPE_FCURVE) {
200     FCurve *fcu = (FCurve *)ale->data;
201     grp = fcu->grp;
202   }
203
204   /* set color for normal channels
205    * - use 3 shades of color group/standard color for 3 indention level
206    * - only use group colors if allowed to, and if actually feasible
207    */
208   if (showGroupColors && (grp) && (grp->customCol)) {
209     unsigned char cp[3];
210
211     if (indent == 2) {
212       copy_v3_v3_char((char *)cp, grp->cs.solid);
213     }
214     else if (indent == 1) {
215       copy_v3_v3_char((char *)cp, grp->cs.select);
216     }
217     else {
218       copy_v3_v3_char((char *)cp, grp->cs.active);
219     }
220
221     /* copy the colors over, transforming from bytes to floats */
222     rgb_uchar_to_float(r_color, cp);
223   }
224   else {
225     // FIXME: what happens when the indention is 1 greater than what it should be (due to grouping)?
226     int colOfs = 10 - 10 * indent;
227     UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
228   }
229 }
230
231 /* get backdrop color for grease pencil channels */
232 static void acf_gpencil_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
233 {
234   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
235   short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
236   bool showGroupColors = acf_show_channel_colors(ac);
237
238   if ((showGroupColors) && (ale->type == ANIMTYPE_GPLAYER)) {
239     bGPDlayer *gpl = (bGPDlayer *)ale->data;
240     copy_v3_v3(r_color, gpl->color);
241   }
242   else {
243     int colOfs = 10 - 10 * indent;
244     UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
245   }
246 }
247
248 /* backdrop for generic channels */
249 static void acf_generic_channel_backdrop(bAnimContext *ac,
250                                          bAnimListElem *ale,
251                                          float yminc,
252                                          float ymaxc)
253 {
254   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
255   View2D *v2d = &ac->ar->v2d;
256   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
257   float color[3];
258
259   uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
260
261   /* set backdrop drawing color */
262   acf->get_backdrop_color(ac, ale, color);
263
264   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
265   immUniformColor3fv(color);
266
267   /* no rounded corners - just rectangular box */
268   immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
269
270   immUnbindProgram();
271 }
272
273 /* Indention + Offset ------------------------------------------- */
274
275 /* indention level is always the value in the name */
276 static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
277 {
278   return 0;
279 }
280 static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
281 {
282   return 1;
283 }
284 #if 0  // XXX not used
285 static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
286 {
287   return 2;
288 }
289 #endif
290
291 /* indention which varies with the grouping status */
292 static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale)
293 {
294   short indent = 0;
295
296   /* grouped F-Curves need extra level of indention */
297   if (ale->type == ANIMTYPE_FCURVE) {
298     FCurve *fcu = (FCurve *)ale->data;
299
300     // TODO: we need some way of specifying that the indention color should be one less...
301     if (fcu->grp)
302       indent++;
303   }
304
305   /* no indention */
306   return indent;
307 }
308
309 /* basic offset for channels derived from indention */
310 static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
311 {
312   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
313
314   if (acf && acf->get_indent_level)
315     return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
316   else
317     return 0;
318 }
319
320 /* offset based on nodetree type */
321 static short acf_nodetree_rootType_offset(bNodeTree *ntree)
322 {
323   if (ntree) {
324     switch (ntree->type) {
325       case NTREE_SHADER:
326         /* 1 additional level (i.e. is indented one level in from material,
327          * so shift all right by one step)
328          */
329         return INDENT_STEP_SIZE;
330
331       case NTREE_COMPOSIT:
332         /* no additional levels needed */
333         return 0;
334
335       case NTREE_TEXTURE:
336         /* 2 additional levels */
337         return INDENT_STEP_SIZE * 2;
338     }
339   }
340
341   /* unknown */
342   return 0;
343 }
344
345 /* offset for groups + grouped entities */
346 static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
347 {
348   short offset = acf_generic_basic_offset(ac, ale);
349
350   if (ale->id) {
351     /* texture animdata */
352     if (GS(ale->id->name) == ID_TE) {
353       offset += U.widget_unit;
354     }
355     /* materials and particles animdata */
356     else if (ELEM(GS(ale->id->name), ID_MA, ID_PA))
357       offset += (short)(0.7f * U.widget_unit);
358
359     /* If not in Action Editor mode, action-groups (and their children)
360      * must carry some offset too. */
361     else if (ac->datatype != ANIMCONT_ACTION)
362       offset += (short)(0.7f * U.widget_unit);
363
364     /* nodetree animdata */
365     if (GS(ale->id->name) == ID_NT) {
366       offset += acf_nodetree_rootType_offset((bNodeTree *)ale->id);
367     }
368   }
369
370   /* offset is just the normal type - i.e. based on indention */
371   return offset;
372 }
373
374 /* Name ------------------------------------------- */
375
376 /* name for ID block entries */
377 static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
378 {
379   ID *id = (ID *)ale->data; /* data pointed to should be an ID block */
380
381   /* just copy the name... */
382   if (id && name)
383     BLI_strncpy(name, id->name + 2, ANIM_CHAN_NAME_SIZE);
384 }
385
386 /* name property for ID block entries */
387 static bool acf_generic_idblock_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
388 {
389   RNA_id_pointer_create(ale->data, ptr);
390   *prop = RNA_struct_name_property(ptr->type);
391
392   return (*prop != NULL);
393 }
394
395 /* name property for ID block entries which are just subheading "fillers" */
396 static bool acf_generic_idfill_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
397 {
398   /* actual ID we're representing is stored in ale->data not ale->id, as id gives the owner */
399   RNA_id_pointer_create(ale->data, ptr);
400   *prop = RNA_struct_name_property(ptr->type);
401
402   return (*prop != NULL);
403 }
404
405 /* Settings ------------------------------------------- */
406
407 #if 0
408 /* channel type has no settings */
409 static bool acf_generic_none_setting_valid(bAnimContext *ac,
410                                            bAnimListElem *ale,
411                                            eAnimChannel_Settings setting)
412 {
413   return false;
414 }
415 #endif
416
417 /* check if some setting exists for this object-based data-expander (datablock only) */
418 static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac,
419                                                  bAnimListElem *UNUSED(ale),
420                                                  eAnimChannel_Settings setting)
421 {
422   switch (setting) {
423     /* expand is always supported */
424     case ACHANNEL_SETTING_EXPAND:
425       return true;
426
427     /* mute is only supported for NLA */
428     case ACHANNEL_SETTING_MUTE:
429       return ((ac) && (ac->spacetype == SPACE_NLA));
430
431     /* select is ok for most "ds*" channels (e.g. dsmat) */
432     case ACHANNEL_SETTING_SELECT:
433       return true;
434
435     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
436       return true;
437
438     /* other flags are never supported */
439     default:
440       return false;
441   }
442 }
443
444 /* *********************************************** */
445 /* Type Specific Functions + Defines */
446
447 /* Animation Summary ----------------------------------- */
448
449 /* get backdrop color for summary widget */
450 static void acf_summary_color(bAnimContext *UNUSED(ac),
451                               bAnimListElem *UNUSED(ale),
452                               float r_color[3])
453 {
454   /* reddish color - same as the 'action' line in NLA */
455   UI_GetThemeColor3fv(TH_ANIM_ACTIVE, r_color);
456 }
457
458 /* backdrop for summary widget */
459 static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
460 {
461   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
462   View2D *v2d = &ac->ar->v2d;
463   float color[3];
464
465   /* set backdrop drawing color */
466   acf->get_backdrop_color(ac, ale, color);
467
468   /* rounded corners on LHS only
469    * - top and bottom
470    * - special hack: make the top a bit higher, since we are first...
471    */
472   UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
473   UI_draw_roundbox_3fvAlpha(
474       true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
475 }
476
477 /* name for summary entries */
478 static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
479 {
480   if (name)
481     BLI_strncpy(name, IFACE_("Dope Sheet Summary"), ANIM_CHAN_NAME_SIZE);
482 }
483
484 // FIXME: this is really a temp icon I think
485 static int acf_summary_icon(bAnimListElem *UNUSED(ale))
486 {
487   return ICON_BORDERMOVE;
488 }
489
490 /* check if some setting exists for this channel */
491 static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac),
492                                       bAnimListElem *UNUSED(ale),
493                                       eAnimChannel_Settings setting)
494 {
495   /* only expanded is supported, as it is used for hiding all stuff which the summary covers */
496   return (setting == ACHANNEL_SETTING_EXPAND);
497 }
498
499 /* get the appropriate flag(s) for the setting when it is valid  */
500 static int acf_summary_setting_flag(bAnimContext *UNUSED(ac),
501                                     eAnimChannel_Settings setting,
502                                     bool *neg)
503 {
504   if (setting == ACHANNEL_SETTING_EXPAND) {
505     /* expanded */
506     *neg = true;
507     return ADS_FLAG_SUMMARY_COLLAPSED;
508   }
509   else {
510     /* unsupported */
511     *neg = false;
512     return 0;
513   }
514 }
515
516 /* get pointer to the setting */
517 static void *acf_summary_setting_ptr(bAnimListElem *ale,
518                                      eAnimChannel_Settings setting,
519                                      short *type)
520 {
521   bAnimContext *ac = (bAnimContext *)ale->data;
522
523   /* if data is valid, return pointer to active dopesheet's relevant flag
524    * - this is restricted to DopeSheet/Action Editor only
525    */
526   if ((ac->sl) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
527     SpaceAction *saction = (SpaceAction *)ac->sl;
528     bDopeSheet *ads = &saction->ads;
529
530     /* return pointer to DopeSheet's flag */
531     return GET_ACF_FLAG_PTR(ads->flag, type);
532   }
533   else {
534     /* can't return anything useful - unsupported */
535     *type = 0;
536     return NULL;
537   }
538 }
539
540 /* all animation summary (DopeSheet only) type define */
541 static bAnimChannelType ACF_SUMMARY = {
542     "Summary",              /* type name */
543     ACHANNEL_ROLE_EXPANDER, /* role */
544
545     acf_summary_color,       /* backdrop color */
546     acf_summary_backdrop,    /* backdrop */
547     acf_generic_indention_0, /* indent level */
548     NULL,                    /* offset */
549
550     acf_summary_name, /* name */
551     NULL,             /* name prop */
552     acf_summary_icon, /* icon */
553
554     acf_summary_setting_valid, /* has setting */
555     acf_summary_setting_flag,  /* flag for setting */
556     acf_summary_setting_ptr,   /* pointer for setting */
557 };
558
559 /* Scene ------------------------------------------- */
560
561 // TODO: just get this from RNA?
562 static int acf_scene_icon(bAnimListElem *UNUSED(ale))
563 {
564   return ICON_SCENE_DATA;
565 }
566
567 /* check if some setting exists for this channel */
568 static bool acf_scene_setting_valid(bAnimContext *ac,
569                                     bAnimListElem *UNUSED(ale),
570                                     eAnimChannel_Settings setting)
571 {
572   switch (setting) {
573     /* muted only in NLA */
574     case ACHANNEL_SETTING_MUTE:
575       return ((ac) && (ac->spacetype == SPACE_NLA));
576
577     /* visible only in Graph Editor */
578     case ACHANNEL_SETTING_VISIBLE:
579       return ((ac) && (ac->spacetype == SPACE_GRAPH));
580
581     /* only select and expand supported otherwise */
582     case ACHANNEL_SETTING_SELECT:
583     case ACHANNEL_SETTING_EXPAND:
584       return true;
585
586     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
587       return false;
588
589     default:
590       return false;
591   }
592 }
593
594 /* get the appropriate flag(s) for the setting when it is valid  */
595 static int acf_scene_setting_flag(bAnimContext *UNUSED(ac),
596                                   eAnimChannel_Settings setting,
597                                   bool *neg)
598 {
599   /* clear extra return data first */
600   *neg = false;
601
602   switch (setting) {
603     case ACHANNEL_SETTING_SELECT: /* selected */
604       return SCE_DS_SELECTED;
605
606     case ACHANNEL_SETTING_EXPAND: /* expanded */
607       *neg = true;
608       return SCE_DS_COLLAPSED;
609
610     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
611       return ADT_NLA_EVAL_OFF;
612
613     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
614       *neg = true;
615       return ADT_CURVES_NOT_VISIBLE;
616
617     default: /* unsupported */
618       return 0;
619   }
620 }
621
622 /* get pointer to the setting */
623 static void *acf_scene_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
624 {
625   Scene *scene = (Scene *)ale->data;
626
627   /* clear extra return data first */
628   *type = 0;
629
630   switch (setting) {
631     case ACHANNEL_SETTING_SELECT: /* selected */
632       return GET_ACF_FLAG_PTR(scene->flag, type);
633
634     case ACHANNEL_SETTING_EXPAND: /* expanded */
635       return GET_ACF_FLAG_PTR(scene->flag, type);
636
637     case ACHANNEL_SETTING_MUTE:    /* mute (only in NLA) */
638     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
639       if (scene->adt)
640         return GET_ACF_FLAG_PTR(scene->adt->flag, type);
641       return NULL;
642
643     default: /* unsupported */
644       return NULL;
645   }
646 }
647
648 /* scene type define */
649 static bAnimChannelType ACF_SCENE = {
650     "Scene",                /* type name */
651     ACHANNEL_ROLE_EXPANDER, /* role */
652
653     acf_generic_root_color,    /* backdrop color */
654     acf_generic_root_backdrop, /* backdrop */
655     acf_generic_indention_0,   /* indent level */
656     NULL,                      /* offset */
657
658     acf_generic_idblock_name,      /* name */
659     acf_generic_idblock_name_prop, /* name prop */
660     acf_scene_icon,                /* icon */
661
662     acf_scene_setting_valid, /* has setting */
663     acf_scene_setting_flag,  /* flag for setting */
664     acf_scene_setting_ptr,   /* pointer for setting */
665 };
666
667 /* Object ------------------------------------------- */
668
669 static int acf_object_icon(bAnimListElem *ale)
670 {
671   Base *base = (Base *)ale->data;
672   Object *ob = base->object;
673
674   /* icon depends on object-type */
675   switch (ob->type) {
676     case OB_LAMP:
677       return ICON_OUTLINER_OB_LIGHT;
678     case OB_MESH:
679       return ICON_OUTLINER_OB_MESH;
680     case OB_CAMERA:
681       return ICON_OUTLINER_OB_CAMERA;
682     case OB_CURVE:
683       return ICON_OUTLINER_OB_CURVE;
684     case OB_MBALL:
685       return ICON_OUTLINER_OB_META;
686     case OB_LATTICE:
687       return ICON_OUTLINER_OB_LATTICE;
688     case OB_SPEAKER:
689       return ICON_OUTLINER_OB_SPEAKER;
690     case OB_LIGHTPROBE:
691       return ICON_OUTLINER_OB_LIGHTPROBE;
692     case OB_ARMATURE:
693       return ICON_OUTLINER_OB_ARMATURE;
694     case OB_FONT:
695       return ICON_OUTLINER_OB_FONT;
696     case OB_SURF:
697       return ICON_OUTLINER_OB_SURFACE;
698     case OB_EMPTY:
699       return ICON_OUTLINER_OB_EMPTY;
700     case OB_GPENCIL:
701       return ICON_OUTLINER_OB_GREASEPENCIL;
702     default:
703       return ICON_OBJECT_DATA;
704   }
705 }
706
707 /* name for object */
708 static void acf_object_name(bAnimListElem *ale, char *name)
709 {
710   Base *base = (Base *)ale->data;
711   Object *ob = base->object;
712
713   /* just copy the name... */
714   if (ob && name)
715     BLI_strncpy(name, ob->id.name + 2, ANIM_CHAN_NAME_SIZE);
716 }
717
718 /* name property for object */
719 static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
720 {
721   RNA_id_pointer_create(ale->id, ptr);
722   *prop = RNA_struct_name_property(ptr->type);
723
724   return (*prop != NULL);
725 }
726
727 /* check if some setting exists for this channel */
728 static bool acf_object_setting_valid(bAnimContext *ac,
729                                      bAnimListElem *ale,
730                                      eAnimChannel_Settings setting)
731 {
732   Base *base = (Base *)ale->data;
733   Object *ob = base->object;
734
735   switch (setting) {
736     /* muted only in NLA */
737     case ACHANNEL_SETTING_MUTE:
738       return ((ac) && (ac->spacetype == SPACE_NLA));
739
740     /* visible only in Graph Editor */
741     case ACHANNEL_SETTING_VISIBLE:
742       return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
743
744     /* only select and expand supported otherwise */
745     case ACHANNEL_SETTING_SELECT:
746     case ACHANNEL_SETTING_EXPAND:
747       return true;
748
749     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
750       return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
751
752     default:
753       return false;
754   }
755 }
756
757 /* get the appropriate flag(s) for the setting when it is valid  */
758 static int acf_object_setting_flag(bAnimContext *UNUSED(ac),
759                                    eAnimChannel_Settings setting,
760                                    bool *neg)
761 {
762   /* clear extra return data first */
763   *neg = false;
764
765   switch (setting) {
766     case ACHANNEL_SETTING_SELECT: /* selected */
767       return BASE_SELECTED;
768
769     case ACHANNEL_SETTING_EXPAND: /* expanded */
770       *neg = 1;
771       return OB_ADS_COLLAPSED;
772
773     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
774       return ADT_NLA_EVAL_OFF;
775
776     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
777       *neg = true;
778       return ADT_CURVES_NOT_VISIBLE;
779
780     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
781       return ADT_CURVES_ALWAYS_VISIBLE;
782
783     default: /* unsupported */
784       return 0;
785   }
786 }
787
788 /* get pointer to the setting */
789 static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
790 {
791   Base *base = (Base *)ale->data;
792   Object *ob = base->object;
793
794   /* clear extra return data first */
795   *type = 0;
796
797   switch (setting) {
798     case ACHANNEL_SETTING_SELECT: /* selected */
799       return GET_ACF_FLAG_PTR(base->flag, type);
800
801     case ACHANNEL_SETTING_EXPAND:                  /* expanded */
802       return GET_ACF_FLAG_PTR(ob->nlaflag, type);  // xxx
803
804     case ACHANNEL_SETTING_MUTE:    /* mute (only in NLA) */
805     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
806     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
807       if (ob->adt)
808         return GET_ACF_FLAG_PTR(ob->adt->flag, type);
809       return NULL;
810
811     default: /* unsupported */
812       return NULL;
813   }
814 }
815
816 /* object type define */
817 static bAnimChannelType ACF_OBJECT = {
818     "Object",               /* type name */
819     ACHANNEL_ROLE_EXPANDER, /* role */
820
821     acf_generic_root_color,    /* backdrop color */
822     acf_generic_root_backdrop, /* backdrop */
823     acf_generic_indention_0,   /* indent level */
824     NULL,                      /* offset */
825
826     acf_object_name,      /* name */
827     acf_object_name_prop, /* name prop */
828     acf_object_icon,      /* icon */
829
830     acf_object_setting_valid, /* has setting */
831     acf_object_setting_flag,  /* flag for setting */
832     acf_object_setting_ptr,   /* pointer for setting */
833 };
834
835 /* Group ------------------------------------------- */
836
837 /* get backdrop color for group widget */
838 static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
839 {
840   bActionGroup *agrp = (bActionGroup *)ale->data;
841   bool showGroupColors = acf_show_channel_colors(ac);
842
843   if (showGroupColors && agrp->customCol) {
844     unsigned char cp[3];
845
846     /* highlight only for active */
847     if (ale->flag & AGRP_ACTIVE)
848       copy_v3_v3_char((char *)cp, agrp->cs.select);
849     else
850       copy_v3_v3_char((char *)cp, agrp->cs.solid);
851
852     /* copy the colors over, transforming from bytes to floats */
853     rgb_uchar_to_float(r_color, cp);
854   }
855   else {
856     /* highlight only for active */
857     if (ale->flag & AGRP_ACTIVE)
858       UI_GetThemeColor3fv(TH_GROUP_ACTIVE, r_color);
859     else
860       UI_GetThemeColor3fv(TH_GROUP, r_color);
861   }
862 }
863
864 /* backdrop for group widget */
865 static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
866 {
867   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
868   View2D *v2d = &ac->ar->v2d;
869   short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
870   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
871   float color[3];
872
873   /* set backdrop drawing color */
874   acf->get_backdrop_color(ac, ale, color);
875
876   /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
877   UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
878   UI_draw_roundbox_3fvAlpha(
879       true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
880 }
881
882 /* name for group entries */
883 static void acf_group_name(bAnimListElem *ale, char *name)
884 {
885   bActionGroup *agrp = (bActionGroup *)ale->data;
886
887   /* just copy the name... */
888   if (agrp && name)
889     BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE);
890 }
891
892 /* name property for group entries */
893 static bool acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
894 {
895   RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
896   *prop = RNA_struct_name_property(ptr->type);
897
898   return (*prop != NULL);
899 }
900
901 /* check if some setting exists for this channel */
902 static bool acf_group_setting_valid(bAnimContext *ac,
903                                     bAnimListElem *UNUSED(ale),
904                                     eAnimChannel_Settings setting)
905 {
906   /* for now, all settings are supported, though some are only conditionally */
907   switch (setting) {
908     /* unsupported */
909     case ACHANNEL_SETTING_SOLO: /* Only available in NLA Editor for tracks */
910       return false;
911
912     /* conditionally supported */
913     case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
914       return (ac->spacetype == SPACE_GRAPH);
915
916     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
917       return (ac->spacetype == SPACE_GRAPH);
918
919     default: /* always supported */
920       return true;
921   }
922 }
923
924 /* get the appropriate flag(s) for the setting when it is valid  */
925 static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
926 {
927   /* clear extra return data first */
928   *neg = false;
929
930   switch (setting) {
931     case ACHANNEL_SETTING_SELECT: /* selected */
932       return AGRP_SELECTED;
933
934     case ACHANNEL_SETTING_EXPAND: /* expanded */
935     {
936       /* NOTE: Graph Editor uses a different flag to everywhere else for this,
937        * allowing different collapsing of groups there, since sharing the flag
938        * proved to be a hazard for workflows...
939        */
940       return (ac->spacetype == SPACE_GRAPH) ? AGRP_EXPANDED_G : /* Graph Editor case */
941                  AGRP_EXPANDED;                                 /* DopeSheet and elsewhere */
942     }
943
944     case ACHANNEL_SETTING_MUTE: /* muted */
945       return AGRP_MUTED;
946
947     case ACHANNEL_SETTING_MOD_OFF: /* muted */
948       *neg = 1;
949       return AGRP_MODIFIERS_OFF;
950
951     case ACHANNEL_SETTING_PROTECT: /* protected */
952       return AGRP_PROTECTED;
953
954     case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
955       *neg = 1;
956       return AGRP_NOTVISIBLE;
957
958     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
959       return ADT_CURVES_ALWAYS_VISIBLE;
960
961     default:
962       /* this shouldn't happen */
963       return 0;
964   }
965 }
966
967 /* get pointer to the setting */
968 static void *acf_group_setting_ptr(bAnimListElem *ale,
969                                    eAnimChannel_Settings UNUSED(setting),
970                                    short *type)
971 {
972   bActionGroup *agrp = (bActionGroup *)ale->data;
973
974   /* all flags are just in agrp->flag for now... */
975   return GET_ACF_FLAG_PTR(agrp->flag, type);
976 }
977
978 /* group type define */
979 static bAnimChannelType ACF_GROUP = {
980     "Group",               /* type name */
981     ACHANNEL_ROLE_CHANNEL, /* role */
982
983     acf_group_color,          /* backdrop color */
984     acf_group_backdrop,       /* backdrop */
985     acf_generic_indention_0,  /* indent level */
986     acf_generic_group_offset, /* offset */
987
988     acf_group_name,      /* name */
989     acf_group_name_prop, /* name prop */
990     NULL,                /* icon */
991
992     acf_group_setting_valid, /* has setting */
993     acf_group_setting_flag,  /* flag for setting */
994     acf_group_setting_ptr,   /* pointer for setting */
995 };
996
997 /* F-Curve ------------------------------------------- */
998
999 /* name for fcurve entries */
1000 static void acf_fcurve_name(bAnimListElem *ale, char *name)
1001 {
1002   getname_anim_fcurve(name, ale->id, ale->data);
1003 }
1004
1005 /* "name" property for fcurve entries */
1006 static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
1007 {
1008   FCurve *fcu = (FCurve *)ale->data;
1009
1010   /* Ctrl-Click Usability Convenience Hack:
1011    * For disabled F-Curves, allow access to the RNA Path
1012    * as our "name" so that user can perform quick fixes
1013    */
1014   if (fcu->flag & FCURVE_DISABLED) {
1015     RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
1016     *prop = RNA_struct_find_property(ptr, "data_path");
1017   }
1018   else {
1019     /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
1020     *prop = NULL;
1021   }
1022
1023   return (*prop != NULL);
1024 }
1025
1026 /* check if some setting exists for this channel */
1027 static bool acf_fcurve_setting_valid(bAnimContext *ac,
1028                                      bAnimListElem *ale,
1029                                      eAnimChannel_Settings setting)
1030 {
1031   FCurve *fcu = (FCurve *)ale->data;
1032
1033   switch (setting) {
1034     /* unsupported */
1035     case ACHANNEL_SETTING_SOLO:   /* Solo Flag is only for NLA */
1036     case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
1037     case ACHANNEL_SETTING_PINNED: /* This is only for NLA Actions */
1038       return false;
1039
1040     /* conditionally available */
1041     case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
1042       if (fcu->bezt)
1043         return true;
1044       else
1045         return false;  // NOTE: in this special case, we need to draw ICON_ZOOMOUT
1046
1047     case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
1048       return (ac->spacetype == SPACE_GRAPH);
1049
1050     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
1051       return false;
1052
1053     /* always available */
1054     default:
1055       return true;
1056   }
1057 }
1058
1059 /* get the appropriate flag(s) for the setting when it is valid  */
1060 static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac),
1061                                    eAnimChannel_Settings setting,
1062                                    bool *neg)
1063 {
1064   /* clear extra return data first */
1065   *neg = false;
1066
1067   switch (setting) {
1068     case ACHANNEL_SETTING_SELECT: /* selected */
1069       return FCURVE_SELECTED;
1070
1071     case ACHANNEL_SETTING_MUTE: /* muted */
1072       return FCURVE_MUTED;
1073
1074     case ACHANNEL_SETTING_PROTECT: /* protected */
1075       return FCURVE_PROTECTED;
1076
1077     case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
1078       return FCURVE_VISIBLE;
1079
1080     case ACHANNEL_SETTING_MOD_OFF:
1081       *neg = 1;
1082       return FCURVE_MOD_OFF;
1083
1084     default: /* unsupported */
1085       return 0;
1086   }
1087 }
1088
1089 /* get pointer to the setting */
1090 static void *acf_fcurve_setting_ptr(bAnimListElem *ale,
1091                                     eAnimChannel_Settings UNUSED(setting),
1092                                     short *type)
1093 {
1094   FCurve *fcu = (FCurve *)ale->data;
1095
1096   /* all flags are just in agrp->flag for now... */
1097   return GET_ACF_FLAG_PTR(fcu->flag, type);
1098 }
1099
1100 /* fcurve type define */
1101 static bAnimChannelType ACF_FCURVE = {
1102     "F-Curve",             /* type name */
1103     ACHANNEL_ROLE_CHANNEL, /* role */
1104
1105     acf_generic_channel_color,    /* backdrop color */
1106     acf_generic_channel_backdrop, /* backdrop */
1107     acf_generic_indention_flexible,
1108     /* indent level */        // xxx rename this to f-curves only?
1109     acf_generic_group_offset, /* offset */
1110
1111     acf_fcurve_name,      /* name */
1112     acf_fcurve_name_prop, /* name prop */
1113     NULL,                 /* icon */
1114
1115     acf_fcurve_setting_valid, /* has setting */
1116     acf_fcurve_setting_flag,  /* flag for setting */
1117     acf_fcurve_setting_ptr,   /* pointer for setting */
1118 };
1119
1120 /* NLA Control FCurves Expander ----------------------- */
1121
1122 /* get backdrop color for nla controls widget */
1123 static void acf_nla_controls_color(bAnimContext *UNUSED(ac),
1124                                    bAnimListElem *UNUSED(ale),
1125                                    float r_color[3])
1126 {
1127   // TODO: give this its own theme setting?
1128   UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color);
1129 }
1130
1131 /* backdrop for nla controls expander widget */
1132 static void acf_nla_controls_backdrop(bAnimContext *ac,
1133                                       bAnimListElem *ale,
1134                                       float yminc,
1135                                       float ymaxc)
1136 {
1137   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
1138   View2D *v2d = &ac->ar->v2d;
1139   short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
1140   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
1141   float color[3];
1142
1143   /* set backdrop drawing color */
1144   acf->get_backdrop_color(ac, ale, color);
1145
1146   /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
1147   UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
1148   UI_draw_roundbox_3fvAlpha(
1149       true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
1150 }
1151
1152 /* name for nla controls expander entries */
1153 static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name)
1154 {
1155   BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
1156 }
1157
1158 /* check if some setting exists for this channel */
1159 static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac),
1160                                            bAnimListElem *UNUSED(ale),
1161                                            eAnimChannel_Settings setting)
1162 {
1163   /* for now, all settings are supported, though some are only conditionally */
1164   switch (setting) {
1165     /* supported */
1166     case ACHANNEL_SETTING_EXPAND:
1167       return true;
1168
1169       // TODO: selected?
1170
1171     default: /* unsupported */
1172       return false;
1173   }
1174 }
1175
1176 /* get the appropriate flag(s) for the setting when it is valid  */
1177 static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac),
1178                                          eAnimChannel_Settings setting,
1179                                          bool *neg)
1180 {
1181   /* clear extra return data first */
1182   *neg = false;
1183
1184   switch (setting) {
1185     case ACHANNEL_SETTING_EXPAND: /* expanded */
1186       *neg = true;
1187       return ADT_NLA_SKEYS_COLLAPSED;
1188
1189     default:
1190       /* this shouldn't happen */
1191       return 0;
1192   }
1193 }
1194
1195 /* get pointer to the setting */
1196 static void *acf_nla_controls_setting_ptr(bAnimListElem *ale,
1197                                           eAnimChannel_Settings UNUSED(setting),
1198                                           short *type)
1199 {
1200   AnimData *adt = (AnimData *)ale->data;
1201
1202   /* all flags are just in adt->flag for now... */
1203   return GET_ACF_FLAG_PTR(adt->flag, type);
1204 }
1205
1206 static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
1207 {
1208   return ICON_NLA;
1209 }
1210
1211 /* NLA Control FCurves Expander type define */
1212 static bAnimChannelType ACF_NLACONTROLS = {
1213     "NLA Controls Expander", /* type name */
1214     ACHANNEL_ROLE_EXPANDER,  /* role */
1215
1216     acf_nla_controls_color,    /* backdrop color */
1217     acf_nla_controls_backdrop, /* backdrop */
1218     acf_generic_indention_0,   /* indent level */
1219     acf_generic_group_offset,  /* offset */
1220
1221     acf_nla_controls_name, /* name */
1222     NULL,                  /* name prop */
1223     acf_nla_controls_icon, /* icon */
1224
1225     acf_nla_controls_setting_valid, /* has setting */
1226     acf_nla_controls_setting_flag,  /* flag for setting */
1227     acf_nla_controls_setting_ptr,   /* pointer for setting */
1228 };
1229
1230 /* NLA Control F-Curve -------------------------------- */
1231
1232 /* name for nla control fcurve entries */
1233 static void acf_nla_curve_name(bAnimListElem *ale, char *name)
1234 {
1235   NlaStrip *strip = ale->owner;
1236   FCurve *fcu = ale->data;
1237   PropertyRNA *prop;
1238
1239   /* try to get RNA property that this shortened path (relative to the strip) refers to */
1240   prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path);
1241   if (prop) {
1242     /* "name" of this strip displays the UI identifier + the name of the NlaStrip */
1243     BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name);
1244   }
1245   else {
1246     /* unknown property... */
1247     BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
1248   }
1249 }
1250
1251 /* NLA Control F-Curve type define */
1252 static bAnimChannelType ACF_NLACURVE = {
1253     "NLA Control F-Curve", /* type name */
1254     ACHANNEL_ROLE_CHANNEL, /* role */
1255
1256     acf_generic_channel_color,    /* backdrop color */
1257     acf_generic_channel_backdrop, /* backdrop */
1258     acf_generic_indention_1,      /* indent level */
1259     acf_generic_group_offset,     /* offset */
1260
1261     acf_nla_curve_name,   /* name */
1262     acf_fcurve_name_prop, /* name prop */
1263     NULL,                 /* icon */
1264
1265     acf_fcurve_setting_valid, /* has setting */
1266     acf_fcurve_setting_flag,  /* flag for setting */
1267     acf_fcurve_setting_ptr,   /* pointer for setting */
1268 };
1269
1270 /* Object Action Expander  ------------------------------------------- */
1271
1272 // TODO: just get this from RNA?
1273 static int acf_fillactd_icon(bAnimListElem *UNUSED(ale))
1274 {
1275   return ICON_ACTION;
1276 }
1277
1278 /* check if some setting exists for this channel */
1279 static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac),
1280                                        bAnimListElem *UNUSED(ale),
1281                                        eAnimChannel_Settings setting)
1282 {
1283   switch (setting) {
1284     /* only select and expand supported */
1285     case ACHANNEL_SETTING_SELECT:
1286     case ACHANNEL_SETTING_EXPAND:
1287       return true;
1288
1289     default:
1290       return false;
1291   }
1292 }
1293
1294 /* get the appropriate flag(s) for the setting when it is valid  */
1295 static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac),
1296                                      eAnimChannel_Settings setting,
1297                                      bool *neg)
1298 {
1299   /* clear extra return data first */
1300   *neg = false;
1301
1302   switch (setting) {
1303     case ACHANNEL_SETTING_SELECT: /* selected */
1304       return ADT_UI_SELECTED;
1305
1306     case ACHANNEL_SETTING_EXPAND: /* expanded */
1307       *neg = true;
1308       return ACT_COLLAPSED;
1309
1310     default: /* unsupported */
1311       return 0;
1312   }
1313 }
1314
1315 /* get pointer to the setting */
1316 static void *acf_fillactd_setting_ptr(bAnimListElem *ale,
1317                                       eAnimChannel_Settings setting,
1318                                       short *type)
1319 {
1320   bAction *act = (bAction *)ale->data;
1321   AnimData *adt = ale->adt;
1322
1323   /* clear extra return data first */
1324   *type = 0;
1325
1326   switch (setting) {
1327     case ACHANNEL_SETTING_SELECT: /* selected */
1328       if (adt) {
1329         return GET_ACF_FLAG_PTR(adt->flag, type);
1330       }
1331       return NULL;
1332
1333     case ACHANNEL_SETTING_EXPAND: /* expanded */
1334       return GET_ACF_FLAG_PTR(act->flag, type);
1335
1336     default: /* unsupported */
1337       return NULL;
1338   }
1339 }
1340
1341 /* object action expander type define */
1342 static bAnimChannelType ACF_FILLACTD = {
1343     "Ob-Action Filler",     /* type name */
1344     ACHANNEL_ROLE_EXPANDER, /* role */
1345
1346     acf_generic_dataexpand_color,    /* backdrop color */
1347     acf_generic_dataexpand_backdrop, /* backdrop */
1348     acf_generic_indention_1,         /* indent level */
1349     acf_generic_basic_offset,        /* offset */
1350
1351     acf_generic_idblock_name,     /* name */
1352     acf_generic_idfill_name_prop, /* name prop */
1353     acf_fillactd_icon,            /* icon */
1354
1355     acf_fillactd_setting_valid, /* has setting */
1356     acf_fillactd_setting_flag,  /* flag for setting */
1357     acf_fillactd_setting_ptr,   /* pointer for setting */
1358 };
1359
1360 /* Drivers Expander  ------------------------------------------- */
1361
1362 // TODO: just get this from RNA?
1363 static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
1364 {
1365   return ICON_DRIVER;
1366 }
1367
1368 static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
1369 {
1370   BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
1371 }
1372
1373 /* check if some setting exists for this channel */
1374 // TODO: this could be made more generic
1375 static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac),
1376                                           bAnimListElem *UNUSED(ale),
1377                                           eAnimChannel_Settings setting)
1378 {
1379   switch (setting) {
1380     /* only expand supported */
1381     case ACHANNEL_SETTING_EXPAND:
1382       return true;
1383
1384     default:
1385       return false;
1386   }
1387 }
1388
1389 /* get the appropriate flag(s) for the setting when it is valid  */
1390 static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac),
1391                                         eAnimChannel_Settings setting,
1392                                         bool *neg)
1393 {
1394   /* clear extra return data first */
1395   *neg = false;
1396
1397   switch (setting) {
1398     case ACHANNEL_SETTING_EXPAND: /* expanded */
1399       *neg = true;
1400       return ADT_DRIVERS_COLLAPSED;
1401
1402     default: /* unsupported */
1403       return 0;
1404   }
1405 }
1406
1407 /* get pointer to the setting */
1408 static void *acf_filldrivers_setting_ptr(bAnimListElem *ale,
1409                                          eAnimChannel_Settings setting,
1410                                          short *type)
1411 {
1412   AnimData *adt = (AnimData *)ale->data;
1413
1414   /* clear extra return data first */
1415   *type = 0;
1416
1417   switch (setting) {
1418     case ACHANNEL_SETTING_EXPAND: /* expanded */
1419       return GET_ACF_FLAG_PTR(adt->flag, type);
1420
1421     default: /* unsupported */
1422       return NULL;
1423   }
1424 }
1425
1426 /* drivers expander type define */
1427 static bAnimChannelType ACF_FILLDRIVERS = {
1428     "Drivers Filler",       /* type name */
1429     ACHANNEL_ROLE_EXPANDER, /* role */
1430
1431     acf_generic_dataexpand_color,    /* backdrop color */
1432     acf_generic_dataexpand_backdrop, /* backdrop */
1433     acf_generic_indention_1,         /* indent level */
1434     acf_generic_basic_offset,        /* offset */
1435
1436     acf_filldrivers_name, /* name */
1437     NULL,                 /* name prop */
1438     acf_filldrivers_icon, /* icon */
1439
1440     acf_filldrivers_setting_valid, /* has setting */
1441     acf_filldrivers_setting_flag,  /* flag for setting */
1442     acf_filldrivers_setting_ptr,   /* pointer for setting */
1443 };
1444
1445 /* Material Expander  ------------------------------------------- */
1446
1447 // TODO: just get this from RNA?
1448 static int acf_dsmat_icon(bAnimListElem *UNUSED(ale))
1449 {
1450   return ICON_MATERIAL_DATA;
1451 }
1452
1453 /* get the appropriate flag(s) for the setting when it is valid  */
1454 static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac),
1455                                   eAnimChannel_Settings setting,
1456                                   bool *neg)
1457 {
1458   /* clear extra return data first */
1459   *neg = false;
1460
1461   switch (setting) {
1462     case ACHANNEL_SETTING_EXPAND: /* expanded */
1463       return MA_DS_EXPAND;
1464
1465     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1466       return ADT_NLA_EVAL_OFF;
1467
1468     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1469       *neg = true;
1470       return ADT_CURVES_NOT_VISIBLE;
1471
1472     case ACHANNEL_SETTING_SELECT: /* selected */
1473       return ADT_UI_SELECTED;
1474
1475     default: /* unsupported */
1476       return 0;
1477   }
1478 }
1479
1480 /* get pointer to the setting */
1481 static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1482 {
1483   Material *ma = (Material *)ale->data;
1484
1485   /* clear extra return data first */
1486   *type = 0;
1487
1488   switch (setting) {
1489     case ACHANNEL_SETTING_EXPAND: /* expanded */
1490       return GET_ACF_FLAG_PTR(ma->flag, type);
1491
1492     case ACHANNEL_SETTING_SELECT:  /* selected */
1493     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1494     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1495       if (ma->adt)
1496         return GET_ACF_FLAG_PTR(ma->adt->flag, type);
1497       return NULL;
1498
1499     default: /* unsupported */
1500       return NULL;
1501   }
1502 }
1503
1504 /* material expander type define */
1505 static bAnimChannelType ACF_DSMAT = {
1506     "Material Data Expander", /* type name */
1507     ACHANNEL_ROLE_EXPANDER,   /* role */
1508
1509     acf_generic_dataexpand_color,    /* backdrop color */
1510     acf_generic_dataexpand_backdrop, /* backdrop */
1511     acf_generic_indention_1,         /* indent level */
1512     acf_generic_basic_offset,        /* offset */
1513
1514     acf_generic_idblock_name,      /* name */
1515     acf_generic_idblock_name_prop, /* name prop */
1516     acf_dsmat_icon,                /* icon */
1517
1518     acf_generic_dataexpand_setting_valid, /* has setting */
1519     acf_dsmat_setting_flag,               /* flag for setting */
1520     acf_dsmat_setting_ptr,                /* pointer for setting */
1521 };
1522
1523 /* Light Expander  ------------------------------------------- */
1524
1525 // TODO: just get this from RNA?
1526 static int acf_dslight_icon(bAnimListElem *UNUSED(ale))
1527 {
1528   return ICON_LIGHT_DATA;
1529 }
1530
1531 /* get the appropriate flag(s) for the setting when it is valid  */
1532 static int acf_dslight_setting_flag(bAnimContext *UNUSED(ac),
1533                                     eAnimChannel_Settings setting,
1534                                     bool *neg)
1535 {
1536   /* clear extra return data first */
1537   *neg = false;
1538
1539   switch (setting) {
1540     case ACHANNEL_SETTING_EXPAND: /* expanded */
1541       return LA_DS_EXPAND;
1542
1543     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1544       return ADT_NLA_EVAL_OFF;
1545
1546     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1547       *neg = true;
1548       return ADT_CURVES_NOT_VISIBLE;
1549
1550     case ACHANNEL_SETTING_SELECT: /* selected */
1551       return ADT_UI_SELECTED;
1552
1553     default: /* unsupported */
1554       return 0;
1555   }
1556 }
1557
1558 /* get pointer to the setting */
1559 static void *acf_dslight_setting_ptr(bAnimListElem *ale,
1560                                      eAnimChannel_Settings setting,
1561                                      short *type)
1562 {
1563   Light *la = (Light *)ale->data;
1564
1565   /* clear extra return data first */
1566   *type = 0;
1567
1568   switch (setting) {
1569     case ACHANNEL_SETTING_EXPAND: /* expanded */
1570       return GET_ACF_FLAG_PTR(la->flag, type);
1571
1572     case ACHANNEL_SETTING_SELECT:  /* selected */
1573     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1574     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1575       if (la->adt)
1576         return GET_ACF_FLAG_PTR(la->adt->flag, type);
1577       return NULL;
1578
1579     default: /* unsupported */
1580       return NULL;
1581   }
1582 }
1583
1584 /* light expander type define */
1585 static bAnimChannelType ACF_DSLIGHT = {
1586     "Light Expander",       /* type name */
1587     ACHANNEL_ROLE_EXPANDER, /* role */
1588
1589     acf_generic_dataexpand_color,    /* backdrop color */
1590     acf_generic_dataexpand_backdrop, /* backdrop */
1591     acf_generic_indention_1,         /* indent level */
1592     acf_generic_basic_offset,        /* offset */
1593
1594     acf_generic_idblock_name,      /* name */
1595     acf_generic_idblock_name_prop, /* name prop */
1596     acf_dslight_icon,              /* icon */
1597
1598     acf_generic_dataexpand_setting_valid, /* has setting */
1599     acf_dslight_setting_flag,             /* flag for setting */
1600     acf_dslight_setting_ptr,              /* pointer for setting */
1601 };
1602
1603 /* Texture Expander  ------------------------------------------- */
1604
1605 // TODO: just get this from RNA?
1606 static int acf_dstex_icon(bAnimListElem *UNUSED(ale))
1607 {
1608   return ICON_TEXTURE_DATA;
1609 }
1610
1611 /* offset for texture expanders */
1612 // FIXME: soon to be obsolete?
1613 static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
1614 {
1615   return 14;  // XXX: simply include this in indention instead?
1616 }
1617
1618 /* get the appropriate flag(s) for the setting when it is valid  */
1619 static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac),
1620                                   eAnimChannel_Settings setting,
1621                                   bool *neg)
1622 {
1623   /* clear extra return data first */
1624   *neg = false;
1625
1626   switch (setting) {
1627     case ACHANNEL_SETTING_EXPAND: /* expanded */
1628       return TEX_DS_EXPAND;
1629
1630     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1631       return ADT_NLA_EVAL_OFF;
1632
1633     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1634       *neg = true;
1635       return ADT_CURVES_NOT_VISIBLE;
1636
1637     case ACHANNEL_SETTING_SELECT: /* selected */
1638       return ADT_UI_SELECTED;
1639
1640     default: /* unsupported */
1641       return 0;
1642   }
1643 }
1644
1645 /* get pointer to the setting */
1646 static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1647 {
1648   Tex *tex = (Tex *)ale->data;
1649
1650   /* clear extra return data first */
1651   *type = 0;
1652
1653   switch (setting) {
1654     case ACHANNEL_SETTING_EXPAND: /* expanded */
1655       return GET_ACF_FLAG_PTR(tex->flag, type);
1656
1657     case ACHANNEL_SETTING_SELECT:  /* selected */
1658     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1659     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1660       if (tex->adt)
1661         return GET_ACF_FLAG_PTR(tex->adt->flag, type);
1662       return NULL;
1663
1664     default: /* unsupported */
1665       return NULL;
1666   }
1667 }
1668
1669 /* texture expander type define */
1670 static bAnimChannelType ACF_DSTEX = {
1671     "Texture Data Expander", /* type name */
1672     ACHANNEL_ROLE_EXPANDER,  /* role */
1673
1674     acf_generic_dataexpand_color,    /* backdrop color */
1675     acf_generic_dataexpand_backdrop, /* backdrop */
1676     acf_generic_indention_1,         /* indent level */
1677     acf_dstex_offset,                /* offset */
1678
1679     acf_generic_idblock_name,     /* name */
1680     acf_generic_idfill_name_prop, /* name prop */
1681     acf_dstex_icon,               /* icon */
1682
1683     acf_generic_dataexpand_setting_valid, /* has setting */
1684     acf_dstex_setting_flag,               /* flag for setting */
1685     acf_dstex_setting_ptr,                /* pointer for setting */
1686 };
1687
1688 /* Camera Expander  ------------------------------------------- */
1689
1690 // TODO: just get this from RNA?
1691 static int acf_dscachefile_icon(bAnimListElem *ale)
1692 {
1693   UNUSED_VARS(ale);
1694   return ICON_FILE;
1695 }
1696
1697 /* get the appropriate flag(s) for the setting when it is valid  */
1698 static int acf_dscachefile_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
1699 {
1700   /* clear extra return data first */
1701   *neg = false;
1702
1703   switch (setting) {
1704     case ACHANNEL_SETTING_EXPAND: /* expanded */
1705       return CACHEFILE_DS_EXPAND;
1706
1707     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1708       return ADT_NLA_EVAL_OFF;
1709
1710     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1711       *neg = true;
1712       return ADT_CURVES_NOT_VISIBLE;
1713
1714     case ACHANNEL_SETTING_SELECT: /* selected */
1715       return ADT_UI_SELECTED;
1716
1717     default: /* unsupported */
1718       return 0;
1719   }
1720
1721   UNUSED_VARS(ac);
1722 }
1723
1724 /* get pointer to the setting */
1725 static void *acf_dscachefile_setting_ptr(bAnimListElem *ale,
1726                                          eAnimChannel_Settings setting,
1727                                          short *type)
1728 {
1729   CacheFile *cache_file = (CacheFile *)ale->data;
1730
1731   /* clear extra return data first */
1732   *type = 0;
1733
1734   switch (setting) {
1735     case ACHANNEL_SETTING_EXPAND: /* expanded */
1736       return GET_ACF_FLAG_PTR(cache_file->flag, type);
1737
1738     case ACHANNEL_SETTING_SELECT:  /* selected */
1739     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1740     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1741       if (cache_file->adt) {
1742         return GET_ACF_FLAG_PTR(cache_file->adt->flag, type);
1743       }
1744
1745       return NULL;
1746
1747     default: /* unsupported */
1748       return NULL;
1749   }
1750 }
1751
1752 /* CacheFile expander type define. */
1753 static bAnimChannelType ACF_DSCACHEFILE = {
1754     "Cache File Expander",  /* type name */
1755     ACHANNEL_ROLE_EXPANDER, /* role */
1756
1757     acf_generic_dataexpand_color,    /* backdrop color */
1758     acf_generic_dataexpand_backdrop, /* backdrop */
1759     acf_generic_indention_1,         /* indent level */
1760     acf_generic_basic_offset,        /* offset */
1761
1762     acf_generic_idblock_name,     /* name */
1763     acf_generic_idfill_name_prop, /* name prop */
1764     acf_dscachefile_icon,         /* icon */
1765
1766     acf_generic_dataexpand_setting_valid, /* has setting */
1767     acf_dscachefile_setting_flag,         /* flag for setting */
1768     acf_dscachefile_setting_ptr,          /* pointer for setting */
1769 };
1770
1771 /* Camera Expander  ------------------------------------------- */
1772
1773 // TODO: just get this from RNA?
1774 static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
1775 {
1776   return ICON_CAMERA_DATA;
1777 }
1778
1779 /* get the appropriate flag(s) for the setting when it is valid  */
1780 static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac),
1781                                   eAnimChannel_Settings setting,
1782                                   bool *neg)
1783 {
1784   /* clear extra return data first */
1785   *neg = false;
1786
1787   switch (setting) {
1788     case ACHANNEL_SETTING_EXPAND: /* expanded */
1789       return CAM_DS_EXPAND;
1790
1791     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1792       return ADT_NLA_EVAL_OFF;
1793
1794     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1795       *neg = true;
1796       return ADT_CURVES_NOT_VISIBLE;
1797
1798     case ACHANNEL_SETTING_SELECT: /* selected */
1799       return ADT_UI_SELECTED;
1800
1801     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
1802       return ADT_CURVES_ALWAYS_VISIBLE;
1803
1804     default: /* unsupported */
1805       return 0;
1806   }
1807 }
1808
1809 /* get pointer to the setting */
1810 static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1811 {
1812   Camera *ca = (Camera *)ale->data;
1813
1814   /* clear extra return data first */
1815   *type = 0;
1816
1817   switch (setting) {
1818     case ACHANNEL_SETTING_EXPAND: /* expanded */
1819       return GET_ACF_FLAG_PTR(ca->flag, type);
1820
1821     case ACHANNEL_SETTING_SELECT:  /* selected */
1822     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1823     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1824     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
1825       if (ca->adt)
1826         return GET_ACF_FLAG_PTR(ca->adt->flag, type);
1827       return NULL;
1828
1829     default: /* unsupported */
1830       return NULL;
1831   }
1832 }
1833
1834 /* camera expander type define */
1835 static bAnimChannelType ACF_DSCAM = {
1836     "Camera Expander",      /* type name */
1837     ACHANNEL_ROLE_EXPANDER, /* role */
1838
1839     acf_generic_dataexpand_color,    /* backdrop color */
1840     acf_generic_dataexpand_backdrop, /* backdrop */
1841     acf_generic_indention_1,         /* indent level */
1842     acf_generic_basic_offset,        /* offset */
1843
1844     acf_generic_idblock_name,     /* name */
1845     acf_generic_idfill_name_prop, /* name prop */
1846     acf_dscam_icon,               /* icon */
1847
1848     acf_generic_dataexpand_setting_valid, /* has setting */
1849     acf_dscam_setting_flag,               /* flag for setting */
1850     acf_dscam_setting_ptr,                /* pointer for setting */
1851 };
1852
1853 /* Curve Expander  ------------------------------------------- */
1854
1855 // TODO: just get this from RNA?
1856 static int acf_dscur_icon(bAnimListElem *ale)
1857 {
1858   Curve *cu = (Curve *)ale->data;
1859   short obtype = BKE_curve_type_get(cu);
1860
1861   switch (obtype) {
1862     case OB_FONT:
1863       return ICON_FONT_DATA;
1864     case OB_SURF:
1865       return ICON_SURFACE_DATA;
1866     default:
1867       return ICON_CURVE_DATA;
1868   }
1869 }
1870
1871 /* get the appropriate flag(s) for the setting when it is valid  */
1872 static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac),
1873                                   eAnimChannel_Settings setting,
1874                                   bool *neg)
1875 {
1876   /* clear extra return data first */
1877   *neg = false;
1878
1879   switch (setting) {
1880     case ACHANNEL_SETTING_EXPAND: /* expanded */
1881       return CU_DS_EXPAND;
1882
1883     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1884       return ADT_NLA_EVAL_OFF;
1885
1886     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1887       *neg = true;
1888       return ADT_CURVES_NOT_VISIBLE;
1889
1890     case ACHANNEL_SETTING_SELECT: /* selected */
1891       return ADT_UI_SELECTED;
1892
1893     default: /* unsupported */
1894       return 0;
1895   }
1896 }
1897
1898 /* get pointer to the setting */
1899 static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1900 {
1901   Curve *cu = (Curve *)ale->data;
1902
1903   /* clear extra return data first */
1904   *type = 0;
1905
1906   switch (setting) {
1907     case ACHANNEL_SETTING_EXPAND: /* expanded */
1908       return GET_ACF_FLAG_PTR(cu->flag, type);
1909
1910     case ACHANNEL_SETTING_SELECT:  /* selected */
1911     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1912     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1913       if (cu->adt)
1914         return GET_ACF_FLAG_PTR(cu->adt->flag, type);
1915       return NULL;
1916
1917     default: /* unsupported */
1918       return NULL;
1919   }
1920 }
1921
1922 /* curve expander type define */
1923 static bAnimChannelType ACF_DSCUR = {
1924     "Curve Expander",       /* type name */
1925     ACHANNEL_ROLE_EXPANDER, /* role */
1926
1927     acf_generic_dataexpand_color,    /* backdrop color */
1928     acf_generic_dataexpand_backdrop, /* backdrop */
1929     acf_generic_indention_1,         /* indent level */
1930     acf_generic_basic_offset,        /* offset */
1931
1932     acf_generic_idblock_name,      /* name */
1933     acf_generic_idblock_name_prop, /* name prop */
1934     acf_dscur_icon,                /* icon */
1935
1936     acf_generic_dataexpand_setting_valid, /* has setting */
1937     acf_dscur_setting_flag,               /* flag for setting */
1938     acf_dscur_setting_ptr,                /* pointer for setting */
1939 };
1940
1941 /* Shape Key Expander  ------------------------------------------- */
1942
1943 // TODO: just get this from RNA?
1944 static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
1945 {
1946   return ICON_SHAPEKEY_DATA;
1947 }
1948
1949 /* get the appropriate flag(s) for the setting when it is valid  */
1950 static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac),
1951                                    eAnimChannel_Settings setting,
1952                                    bool *neg)
1953 {
1954   /* clear extra return data first */
1955   *neg = false;
1956
1957   switch (setting) {
1958     case ACHANNEL_SETTING_EXPAND: /* expanded */
1959       return KEY_DS_EXPAND;
1960
1961     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1962       return ADT_NLA_EVAL_OFF;
1963
1964     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1965       *neg = true;
1966       return ADT_CURVES_NOT_VISIBLE;
1967
1968     case ACHANNEL_SETTING_SELECT: /* selected */
1969       return ADT_UI_SELECTED;
1970
1971     default: /* unsupported */
1972       return 0;
1973   }
1974 }
1975
1976 /* get pointer to the setting */
1977 static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1978 {
1979   Key *key = (Key *)ale->data;
1980
1981   /* clear extra return data first */
1982   *type = 0;
1983
1984   switch (setting) {
1985     case ACHANNEL_SETTING_EXPAND: /* expanded */
1986       return GET_ACF_FLAG_PTR(key->flag, type);
1987
1988     case ACHANNEL_SETTING_SELECT:  /* selected */
1989     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1990     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1991       if (key->adt)
1992         return GET_ACF_FLAG_PTR(key->adt->flag, type);
1993       return NULL;
1994
1995     default: /* unsupported */
1996       return NULL;
1997   }
1998 }
1999
2000 /* shapekey expander type define */
2001 static bAnimChannelType ACF_DSSKEY = {
2002     "Shape Key Expander",   /* type name */
2003     ACHANNEL_ROLE_EXPANDER, /* role */
2004
2005     acf_generic_dataexpand_color,    /* backdrop color */
2006     acf_generic_dataexpand_backdrop, /* backdrop */
2007     acf_generic_indention_1,         /* indent level */
2008     acf_generic_basic_offset,        /* offset */
2009
2010     acf_generic_idblock_name,      /* name */
2011     acf_generic_idblock_name_prop, /* name prop */
2012     acf_dsskey_icon,               /* icon */
2013
2014     acf_generic_dataexpand_setting_valid, /* has setting */
2015     acf_dsskey_setting_flag,              /* flag for setting */
2016     acf_dsskey_setting_ptr,               /* pointer for setting */
2017 };
2018
2019 /* World Expander  ------------------------------------------- */
2020
2021 // TODO: just get this from RNA?
2022 static int acf_dswor_icon(bAnimListElem *UNUSED(ale))
2023 {
2024   return ICON_WORLD_DATA;
2025 }
2026
2027 /* get the appropriate flag(s) for the setting when it is valid  */
2028 static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac),
2029                                   eAnimChannel_Settings setting,
2030                                   bool *neg)
2031 {
2032   /* clear extra return data first */
2033   *neg = false;
2034
2035   switch (setting) {
2036     case ACHANNEL_SETTING_EXPAND: /* expanded */
2037       return WO_DS_EXPAND;
2038
2039     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2040       return ADT_NLA_EVAL_OFF;
2041
2042     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2043       *neg = true;
2044       return ADT_CURVES_NOT_VISIBLE;
2045
2046     case ACHANNEL_SETTING_SELECT: /* selected */
2047       return ADT_UI_SELECTED;
2048
2049     default: /* unsupported */
2050       return 0;
2051   }
2052 }
2053
2054 /* get pointer to the setting */
2055 static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2056 {
2057   World *wo = (World *)ale->data;
2058
2059   /* clear extra return data first */
2060   *type = 0;
2061
2062   switch (setting) {
2063     case ACHANNEL_SETTING_EXPAND: /* expanded */
2064       return GET_ACF_FLAG_PTR(wo->flag, type);
2065
2066     case ACHANNEL_SETTING_SELECT:  /* selected */
2067     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2068     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2069       if (wo->adt)
2070         return GET_ACF_FLAG_PTR(wo->adt->flag, type);
2071       return NULL;
2072
2073     default: /* unsupported */
2074       return NULL;
2075   }
2076 }
2077
2078 /* world expander type define */
2079 static bAnimChannelType ACF_DSWOR = {
2080     "World Expander",       /* type name */
2081     ACHANNEL_ROLE_EXPANDER, /* role */
2082
2083     acf_generic_dataexpand_color,    /* backdrop color */
2084     acf_generic_dataexpand_backdrop, /* backdrop */
2085     acf_generic_indention_1,         /* indent level */
2086     acf_generic_basic_offset,        /* offset */
2087
2088     acf_generic_idblock_name,     /* name */
2089     acf_generic_idfill_name_prop, /* name prop */
2090     acf_dswor_icon,               /* icon */
2091
2092     acf_generic_dataexpand_setting_valid, /* has setting */
2093     acf_dswor_setting_flag,               /* flag for setting */
2094     acf_dswor_setting_ptr,                /* pointer for setting */
2095 };
2096
2097 /* Particle Expander  ------------------------------------------- */
2098
2099 // TODO: just get this from RNA?
2100 static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
2101 {
2102   return ICON_PARTICLE_DATA;
2103 }
2104
2105 /* get the appropriate flag(s) for the setting when it is valid  */
2106 static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac),
2107                                    eAnimChannel_Settings setting,
2108                                    bool *neg)
2109 {
2110   /* clear extra return data first */
2111   *neg = false;
2112
2113   switch (setting) {
2114     case ACHANNEL_SETTING_EXPAND: /* expanded */
2115       return PART_DS_EXPAND;
2116
2117     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2118       return ADT_NLA_EVAL_OFF;
2119
2120     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2121       *neg = true;
2122       return ADT_CURVES_NOT_VISIBLE;
2123
2124     case ACHANNEL_SETTING_SELECT: /* selected */
2125       return ADT_UI_SELECTED;
2126
2127     default: /* unsupported */
2128       return 0;
2129   }
2130 }
2131
2132 /* get pointer to the setting */
2133 static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2134 {
2135   ParticleSettings *part = (ParticleSettings *)ale->data;
2136
2137   /* clear extra return data first */
2138   *type = 0;
2139
2140   switch (setting) {
2141     case ACHANNEL_SETTING_EXPAND: /* expanded */
2142       return GET_ACF_FLAG_PTR(part->flag, type);
2143
2144     case ACHANNEL_SETTING_SELECT:  /* selected */
2145     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2146     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2147       if (part->adt)
2148         return GET_ACF_FLAG_PTR(part->adt->flag, type);
2149       return NULL;
2150
2151     default: /* unsupported */
2152       return NULL;
2153   }
2154 }
2155
2156 /* particle expander type define */
2157 static bAnimChannelType ACF_DSPART = {
2158     "Particle Data Expander", /* type name */
2159     ACHANNEL_ROLE_EXPANDER,   /* role */
2160
2161     acf_generic_dataexpand_color,    /* backdrop color */
2162     acf_generic_dataexpand_backdrop, /* backdrop */
2163     acf_generic_indention_1,         /* indent level */
2164     acf_generic_basic_offset,        /* offset */
2165
2166     acf_generic_idblock_name,      /* name */
2167     acf_generic_idblock_name_prop, /* name prop */
2168     acf_dspart_icon,               /* icon */
2169
2170     acf_generic_dataexpand_setting_valid, /* has setting */
2171     acf_dspart_setting_flag,              /* flag for setting */
2172     acf_dspart_setting_ptr,               /* pointer for setting */
2173 };
2174
2175 /* MetaBall Expander  ------------------------------------------- */
2176
2177 // TODO: just get this from RNA?
2178 static int acf_dsmball_icon(bAnimListElem *UNUSED(ale))
2179 {
2180   return ICON_META_DATA;
2181 }
2182
2183 /* get the appropriate flag(s) for the setting when it is valid  */
2184 static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac),
2185                                     eAnimChannel_Settings setting,
2186                                     bool *neg)
2187 {
2188   /* clear extra return data first */
2189   *neg = false;
2190
2191   switch (setting) {
2192     case ACHANNEL_SETTING_EXPAND: /* expanded */
2193       return MB_DS_EXPAND;
2194
2195     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2196       return ADT_NLA_EVAL_OFF;
2197
2198     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2199       *neg = true;
2200       return ADT_CURVES_NOT_VISIBLE;
2201
2202     case ACHANNEL_SETTING_SELECT: /* selected */
2203       return ADT_UI_SELECTED;
2204
2205     default: /* unsupported */
2206       return 0;
2207   }
2208 }
2209
2210 /* get pointer to the setting */
2211 static void *acf_dsmball_setting_ptr(bAnimListElem *ale,
2212                                      eAnimChannel_Settings setting,
2213                                      short *type)
2214 {
2215   MetaBall *mb = (MetaBall *)ale->data;
2216
2217   /* clear extra return data first */
2218   *type = 0;
2219
2220   switch (setting) {
2221     case ACHANNEL_SETTING_EXPAND: /* expanded */
2222       return GET_ACF_FLAG_PTR(mb->flag2, type);
2223
2224     case ACHANNEL_SETTING_SELECT:  /* selected */
2225     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2226     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2227       if (mb->adt)
2228         return GET_ACF_FLAG_PTR(mb->adt->flag, type);
2229       return NULL;
2230
2231     default: /* unsupported */
2232       return NULL;
2233   }
2234 }
2235
2236 /* metaball expander type define */
2237 static bAnimChannelType ACF_DSMBALL = {
2238     "Metaball Expander",    /* type name */
2239     ACHANNEL_ROLE_EXPANDER, /* role */
2240
2241     acf_generic_dataexpand_color,    /* backdrop color */
2242     acf_generic_dataexpand_backdrop, /* backdrop */
2243     acf_generic_indention_1,         /* indent level */
2244     acf_generic_basic_offset,        /* offset */
2245
2246     acf_generic_idblock_name,      /* name */
2247     acf_generic_idblock_name_prop, /* name prop */
2248     acf_dsmball_icon,              /* icon */
2249
2250     acf_generic_dataexpand_setting_valid, /* has setting */
2251     acf_dsmball_setting_flag,             /* flag for setting */
2252     acf_dsmball_setting_ptr,              /* pointer for setting */
2253 };
2254
2255 /* Armature Expander  ------------------------------------------- */
2256
2257 // TODO: just get this from RNA?
2258 static int acf_dsarm_icon(bAnimListElem *UNUSED(ale))
2259 {
2260   return ICON_ARMATURE_DATA;
2261 }
2262
2263 /* get the appropriate flag(s) for the setting when it is valid  */
2264 static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac),
2265                                   eAnimChannel_Settings setting,
2266                                   bool *neg)
2267 {
2268   /* clear extra return data first */
2269   *neg = false;
2270
2271   switch (setting) {
2272     case ACHANNEL_SETTING_EXPAND: /* expanded */
2273       return ARM_DS_EXPAND;
2274
2275     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2276       return ADT_NLA_EVAL_OFF;
2277
2278     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2279       *neg = true;
2280       return ADT_CURVES_NOT_VISIBLE;
2281
2282     case ACHANNEL_SETTING_SELECT: /* selected */
2283       return ADT_UI_SELECTED;
2284
2285     default: /* unsupported */
2286       return 0;
2287   }
2288 }
2289
2290 /* get pointer to the setting */
2291 static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2292 {
2293   bArmature *arm = (bArmature *)ale->data;
2294
2295   /* clear extra return data first */
2296   *type = 0;
2297
2298   switch (setting) {
2299     case ACHANNEL_SETTING_EXPAND: /* expanded */
2300       return GET_ACF_FLAG_PTR(arm->flag, type);
2301
2302     case ACHANNEL_SETTING_SELECT:  /* selected */
2303     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2304     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2305       if (arm->adt)
2306         return GET_ACF_FLAG_PTR(arm->adt->flag, type);
2307       return NULL;
2308
2309     default: /* unsupported */
2310       return NULL;
2311   }
2312 }
2313
2314 /* metaball expander type define */
2315 static bAnimChannelType ACF_DSARM = {
2316     "Armature Expander",    /* type name */
2317     ACHANNEL_ROLE_EXPANDER, /* role */
2318
2319     acf_generic_dataexpand_color,    /* backdrop color */
2320     acf_generic_dataexpand_backdrop, /* backdrop */
2321     acf_generic_indention_1,         /* indent level */
2322     acf_generic_basic_offset,        /* offset */
2323
2324     acf_generic_idblock_name,      /* name */
2325     acf_generic_idblock_name_prop, /* name prop */
2326     acf_dsarm_icon,                /* icon */
2327
2328     acf_generic_dataexpand_setting_valid, /* has setting */
2329     acf_dsarm_setting_flag,               /* flag for setting */
2330     acf_dsarm_setting_ptr,                /* pointer for setting */
2331 };
2332
2333 /* NodeTree Expander  ------------------------------------------- */
2334
2335 // TODO: just get this from RNA?
2336 static int acf_dsntree_icon(bAnimListElem *UNUSED(ale))
2337 {
2338   return ICON_NODETREE;
2339 }
2340
2341 /* offset for nodetree expanders */
2342 static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale)
2343 {
2344   bNodeTree *ntree = (bNodeTree *)ale->data;
2345   short offset = acf_generic_basic_offset(ac, ale);
2346
2347   offset += acf_nodetree_rootType_offset(ntree);
2348
2349   return offset;
2350 }
2351
2352 /* get the appropriate flag(s) for the setting when it is valid  */
2353 static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac),
2354                                     eAnimChannel_Settings setting,
2355                                     bool *neg)
2356 {
2357   /* clear extra return data first */
2358   *neg = false;
2359
2360   switch (setting) {
2361     case ACHANNEL_SETTING_EXPAND: /* expanded */
2362       return NTREE_DS_EXPAND;
2363
2364     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2365       return ADT_NLA_EVAL_OFF;
2366
2367     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2368       *neg = true;
2369       return ADT_CURVES_NOT_VISIBLE;
2370
2371     case ACHANNEL_SETTING_SELECT: /* selected */
2372       return ADT_UI_SELECTED;
2373
2374     default: /* unsupported */
2375       return 0;
2376   }
2377 }
2378
2379 /* get pointer to the setting */
2380 static void *acf_dsntree_setting_ptr(bAnimListElem *ale,
2381                                      eAnimChannel_Settings setting,
2382                                      short *type)
2383 {
2384   bNodeTree *ntree = (bNodeTree *)ale->data;
2385
2386   /* clear extra return data first */
2387   *type = 0;
2388
2389   switch (setting) {
2390     case ACHANNEL_SETTING_EXPAND: /* expanded */
2391       return GET_ACF_FLAG_PTR(ntree->flag, type);
2392
2393     case ACHANNEL_SETTING_SELECT:  /* selected */
2394     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2395     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2396       if (ntree->adt)
2397         return GET_ACF_FLAG_PTR(ntree->adt->flag, type);
2398       return NULL;
2399
2400     default: /* unsupported */
2401       return NULL;
2402   }
2403 }
2404
2405 /* node tree expander type define */
2406 static bAnimChannelType ACF_DSNTREE = {
2407     "Node Tree Expander",   /* type name */
2408     ACHANNEL_ROLE_EXPANDER, /* role */
2409
2410     acf_generic_dataexpand_color,    /* backdrop color */
2411     acf_generic_dataexpand_backdrop, /* backdrop */
2412     acf_generic_indention_1,         /* indent level */
2413     acf_dsntree_offset,              /* offset */
2414
2415     acf_generic_idblock_name,      /* name */
2416     acf_generic_idblock_name_prop, /* name prop */
2417     acf_dsntree_icon,              /* icon */
2418
2419     acf_generic_dataexpand_setting_valid, /* has setting */
2420     acf_dsntree_setting_flag,             /* flag for setting */
2421     acf_dsntree_setting_ptr,              /* pointer for setting */
2422 };
2423
2424 /* LineStyle Expander  ------------------------------------------- */
2425
2426 /* TODO: just get this from RNA? */
2427 static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale))
2428 {
2429   return ICON_LINE_DATA;
2430 }
2431
2432 /* get the appropriate flag(s) for the setting when it is valid  */
2433 static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac),
2434                                         eAnimChannel_Settings setting,
2435                                         bool *neg)
2436 {
2437   /* clear extra return data first */
2438   *neg = false;
2439
2440   switch (setting) {
2441     case ACHANNEL_SETTING_EXPAND: /* expanded */
2442       return LS_DS_EXPAND;
2443
2444     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2445       return ADT_NLA_EVAL_OFF;
2446
2447     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2448       *neg = true;
2449       return ADT_CURVES_NOT_VISIBLE;
2450
2451     case ACHANNEL_SETTING_SELECT: /* selected */
2452       return ADT_UI_SELECTED;
2453
2454     default: /* unsupported */
2455       return 0;
2456   }
2457 }
2458
2459 /* get pointer to the setting */
2460 static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale,
2461                                          eAnimChannel_Settings setting,
2462                                          short *type)
2463 {
2464   FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
2465
2466   /* clear extra return data first */
2467   *type = 0;
2468
2469   switch (setting) {
2470     case ACHANNEL_SETTING_EXPAND: /* expanded */
2471       return GET_ACF_FLAG_PTR(linestyle->flag, type);
2472
2473     case ACHANNEL_SETTING_SELECT:  /* selected */
2474     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2475     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2476       if (linestyle->adt)
2477         return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
2478       return NULL;
2479
2480     default: /* unsupported */
2481       return NULL;
2482   }
2483 }
2484
2485 /* node tree expander type define */
2486 static bAnimChannelType ACF_DSLINESTYLE = {
2487     "Line Style Expander",  /* type name */
2488     ACHANNEL_ROLE_EXPANDER, /* role */
2489
2490     acf_generic_dataexpand_color,    /* backdrop color */
2491     acf_generic_dataexpand_backdrop, /* backdrop */
2492     acf_generic_indention_1,         /* indent level */
2493     acf_generic_basic_offset,        /* offset */
2494
2495     acf_generic_idblock_name,      /* name */
2496     acf_generic_idblock_name_prop, /* name prop */
2497     acf_dslinestyle_icon,          /* icon */
2498
2499     acf_generic_dataexpand_setting_valid, /* has setting */
2500     acf_dslinestyle_setting_flag,         /* flag for setting */
2501     acf_dslinestyle_setting_ptr,          /* pointer for setting */
2502 };
2503
2504 /* Mesh Expander  ------------------------------------------- */
2505
2506 // TODO: just get this from RNA?
2507 static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale))
2508 {
2509   return ICON_MESH_DATA;
2510 }
2511
2512 /* get the appropriate flag(s) for the setting when it is valid  */
2513 static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac),
2514                                    eAnimChannel_Settings setting,
2515                                    bool *neg)
2516 {
2517   /* clear extra return data first */
2518   *neg = false;
2519
2520   switch (setting) {
2521     case ACHANNEL_SETTING_EXPAND: /* expanded */
2522       return ME_DS_EXPAND;
2523
2524     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2525       return ADT_NLA_EVAL_OFF;
2526
2527     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2528       *neg = true;
2529       return ADT_CURVES_NOT_VISIBLE;
2530
2531     case ACHANNEL_SETTING_SELECT: /* selected */
2532       return ADT_UI_SELECTED;
2533
2534     default: /* unsupported */
2535       return 0;
2536   }
2537 }
2538
2539 /* get pointer to the setting */
2540 static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2541 {
2542   Mesh *me = (Mesh *)ale->data;
2543
2544   /* clear extra return data first */
2545   *type = 0;
2546
2547   switch (setting) {
2548     case ACHANNEL_SETTING_EXPAND: /* expanded */
2549       return GET_ACF_FLAG_PTR(me->flag, type);
2550
2551     case ACHANNEL_SETTING_SELECT:  /* selected */
2552     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2553     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2554       if (me->adt)
2555         return GET_ACF_FLAG_PTR(me->adt->flag, type);
2556       return NULL;
2557
2558     default: /* unsupported */
2559       return NULL;
2560   }
2561 }
2562
2563 /* node tree expander type define */
2564 static bAnimChannelType ACF_DSMESH = {
2565     "Mesh Expander",        /* type name */
2566     ACHANNEL_ROLE_EXPANDER, /* role */
2567
2568     acf_generic_dataexpand_color,    /* backdrop color */
2569     acf_generic_dataexpand_backdrop, /* backdrop */
2570     acf_generic_indention_1,
2571     /* indent level */        // XXX this only works for compositing
2572     acf_generic_basic_offset, /* offset */
2573
2574     acf_generic_idblock_name,      /* name */
2575     acf_generic_idblock_name_prop, /* name prop */
2576     acf_dsmesh_icon,               /* icon */
2577
2578     acf_generic_dataexpand_setting_valid, /* has setting */
2579     acf_dsmesh_setting_flag,              /* flag for setting */
2580     acf_dsmesh_setting_ptr,               /* pointer for setting */
2581 };
2582
2583 /* Lattice Expander  ------------------------------------------- */
2584
2585 // TODO: just get this from RNA?
2586 static int acf_dslat_icon(bAnimListElem *UNUSED(ale))
2587 {
2588   return ICON_LATTICE_DATA;
2589 }
2590
2591 /* get the appropriate flag(s) for the setting when it is valid  */
2592 static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac),
2593                                   eAnimChannel_Settings setting,
2594                                   bool *neg)
2595 {
2596   /* clear extra return data first */
2597   *neg = false;
2598
2599   switch (setting) {
2600     case ACHANNEL_SETTING_EXPAND: /* expanded */
2601       return LT_DS_EXPAND;
2602
2603     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2604       return ADT_NLA_EVAL_OFF;
2605
2606     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2607       *neg = true;
2608       return ADT_CURVES_NOT_VISIBLE;
2609
2610     case ACHANNEL_SETTING_SELECT: /* selected */
2611       return ADT_UI_SELECTED;
2612
2613     default: /* unsupported */
2614       return 0;
2615   }
2616 }
2617
2618 /* get pointer to the setting */
2619 static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2620 {
2621   Lattice *lt = (Lattice *)ale->data;
2622
2623   /* clear extra return data first */
2624   *type = 0;
2625
2626   switch (setting) {
2627     case ACHANNEL_SETTING_EXPAND: /* expanded */
2628       return GET_ACF_FLAG_PTR(lt->flag, type);
2629
2630     case ACHANNEL_SETTING_SELECT:  /* selected */
2631     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2632     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2633       if (lt->adt)
2634         return GET_ACF_FLAG_PTR(lt->adt->flag, type);
2635       return NULL;
2636
2637     default: /* unsupported */
2638       return NULL;
2639   }
2640 }
2641
2642 /* node tree expander type define */
2643 static bAnimChannelType ACF_DSLAT = {
2644     "Lattice Expander",     /* type name */
2645     ACHANNEL_ROLE_EXPANDER, /* role */
2646
2647     acf_generic_dataexpand_color,    /* backdrop color */
2648     acf_generic_dataexpand_backdrop, /* backdrop */
2649     acf_generic_indention_1,
2650     /* indent level */        // XXX this only works for compositing
2651     acf_generic_basic_offset, /* offset */
2652
2653     acf_generic_idblock_name,      /* name */
2654     acf_generic_idblock_name_prop, /* name prop */
2655     acf_dslat_icon,                /* icon */
2656
2657     acf_generic_dataexpand_setting_valid, /* has setting */
2658     acf_dslat_setting_flag,               /* flag for setting */
2659     acf_dslat_setting_ptr,                /* pointer for setting */
2660 };
2661
2662 /* Speaker Expander  ------------------------------------------- */
2663
2664 // TODO: just get this from RNA?
2665 static int acf_dsspk_icon(bAnimListElem *UNUSED(ale))
2666 {
2667   return ICON_SPEAKER;
2668 }
2669
2670 /* get the appropriate flag(s) for the setting when it is valid  */
2671 static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac),
2672                                   eAnimChannel_Settings setting,
2673                                   bool *neg)
2674 {
2675   /* clear extra return data first */
2676   *neg = false;
2677
2678   switch (setting) {
2679     case ACHANNEL_SETTING_EXPAND: /* expanded */
2680       return SPK_DS_EXPAND;
2681
2682     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2683       return ADT_NLA_EVAL_OFF;
2684
2685     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2686       *neg = true;
2687       return ADT_CURVES_NOT_VISIBLE;
2688
2689     case ACHANNEL_SETTING_SELECT: /* selected */
2690       return ADT_UI_SELECTED;
2691
2692     default: /* unsupported */
2693       return 0;
2694   }
2695 }
2696
2697 /* get pointer to the setting */
2698 static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2699 {
2700   Speaker *spk = (Speaker *)ale->data;
2701
2702   /* clear extra return data first */
2703   *type = 0;
2704
2705   switch (setting) {
2706     case ACHANNEL_SETTING_EXPAND: /* expanded */
2707       return GET_ACF_FLAG_PTR(spk->flag, type);
2708
2709     case ACHANNEL_SETTING_SELECT:  /* selected */
2710     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2711     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2712       if (spk->adt)
2713         return GET_ACF_FLAG_PTR(spk->adt->flag, type);
2714       return NULL;
2715
2716     default: /* unsupported */
2717       return NULL;
2718   }
2719 }
2720
2721 /* speaker expander type define */
2722 static bAnimChannelType ACF_DSSPK = {
2723     "Speaker Expander",     /* type name */
2724     ACHANNEL_ROLE_EXPANDER, /* role */
2725
2726     acf_generic_dataexpand_color,    /* backdrop color */
2727     acf_generic_dataexpand_backdrop, /* backdrop */
2728     acf_generic_indention_1,         /* indent level */
2729     acf_generic_basic_offset,        /* offset */
2730
2731     acf_generic_idblock_name,      /* name */
2732     acf_generic_idblock_name_prop, /* name prop */
2733     acf_dsspk_icon,                /* icon */
2734
2735     acf_generic_dataexpand_setting_valid, /* has setting */
2736     acf_dsspk_setting_flag,               /* flag for setting */
2737     acf_dsspk_setting_ptr,                /* pointer for setting */
2738 };
2739
2740 /* GPencil Expander  ------------------------------------------- */
2741
2742 // TODO: just get this from RNA?
2743 static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
2744 {
2745   return ICON_GREASEPENCIL;
2746 }
2747
2748 /* get the appropriate flag(s) for the setting when it is valid  */
2749 static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac),
2750                                       eAnimChannel_Settings setting,
2751                                       bool *neg)
2752 {
2753   /* clear extra return data first */
2754   *neg = false;
2755
2756   switch (setting) {
2757     case ACHANNEL_SETTING_EXPAND: /* expanded */
2758       return GP_DATA_EXPAND;
2759
2760     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2761       return ADT_NLA_EVAL_OFF;
2762
2763     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2764       *neg = true;
2765       return ADT_CURVES_NOT_VISIBLE;
2766
2767     case ACHANNEL_SETTING_SELECT: /* selected */
2768       return ADT_UI_SELECTED;
2769
2770     default: /* unsupported */
2771       return 0;
2772   }
2773 }
2774
2775 /* get pointer to the setting */
2776 static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale,
2777                                        eAnimChannel_Settings setting,
2778                                        short *type)
2779 {
2780   bGPdata *gpd = (bGPdata *)ale->data;
2781
2782   /* clear extra return data first */
2783   *type = 0;
2784
2785   switch (setting) {
2786     case ACHANNEL_SETTING_EXPAND: /* expanded */
2787       return GET_ACF_FLAG_PTR(gpd->flag, type);
2788
2789     case ACHANNEL_SETTING_SELECT:  /* selected */
2790     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2791     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2792       if (gpd->adt)
2793         return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
2794       return NULL;
2795
2796     default: /* unsupported */
2797       return NULL;
2798   }
2799 }
2800
2801 /* grease pencil expander type define */
2802 static bAnimChannelType ACF_DSGPENCIL = {
2803     "GPencil DS Expander",  /* type name */
2804     ACHANNEL_ROLE_EXPANDER, /* role */
2805
2806     acf_generic_dataexpand_color,    /* backdrop color */
2807     acf_generic_dataexpand_backdrop, /* backdrop */
2808     acf_generic_indention_1,         /* indent level */
2809     acf_generic_basic_offset,        /* offset */
2810
2811     acf_generic_idblock_name,      /* name */
2812     acf_generic_idblock_name_prop, /* name prop */
2813     acf_dsgpencil_icon,            /* icon */
2814
2815     acf_generic_dataexpand_setting_valid, /* has setting */
2816     acf_dsgpencil_setting_flag,           /* flag for setting */
2817     acf_dsgpencil_setting_ptr,            /* pointer for setting */
2818 };
2819
2820 /* World Expander  ------------------------------------------- */
2821
2822 // TODO: just get this from RNA?
2823 static int acf_dsmclip_icon(bAnimListElem *UNUSED(ale))
2824 {
2825   return ICON_SEQUENCE;
2826 }
2827
2828 /* get the appropriate flag(s) for the setting when it is valid  */
2829 static int acf_dsmclip_setting_flag(bAnimContext *UNUSED(ac),
2830                                     eAnimChannel_Settings setting,
2831                                     bool *neg)
2832 {
2833   /* clear extra return data first */
2834   *neg = false;
2835
2836   switch (setting) {
2837     case ACHANNEL_SETTING_EXPAND: /* expanded */
2838       return MCLIP_DATA_EXPAND;
2839
2840     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2841       return ADT_NLA_EVAL_OFF;
2842
2843     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2844       *neg = true;
2845       return ADT_CURVES_NOT_VISIBLE;
2846
2847     case ACHANNEL_SETTING_SELECT: /* selected */
2848       return ADT_UI_SELECTED;
2849
2850     default: /* unsupported */
2851       return 0;
2852   }
2853 }
2854
2855 /* get pointer to the setting */
2856 static void *acf_dsmclip_setting_ptr(bAnimListElem *ale,
2857                                      eAnimChannel_Settings setting,
2858                                      short *type)
2859 {
2860   MovieClip *clip = (MovieClip *)ale->data;
2861
2862   /* clear extra return data first */
2863   *type = 0;
2864
2865   switch (setting) {
2866     case ACHANNEL_SETTING_EXPAND: /* expanded */
2867       return GET_ACF_FLAG_PTR(clip->flag, type);
2868
2869     case ACHANNEL_SETTING_SELECT:  /* selected */
2870     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2871     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2872       if (clip->adt != NULL) {
2873         return GET_ACF_FLAG_PTR(clip->adt->flag, type);
2874       }
2875       return NULL;
2876
2877     default: /* unsupported */
2878       return NULL;
2879   }
2880 }
2881
2882 /* world expander type define */
2883 static bAnimChannelType ACF_DSMCLIP = {
2884     "Movieclip Expander",   /* type name */
2885     ACHANNEL_ROLE_EXPANDER, /* role */
2886
2887     acf_generic_dataexpand_color,    /* backdrop color */
2888     acf_generic_dataexpand_backdrop, /* backdrop */
2889     acf_generic_indention_1,         /* indent level */
2890     acf_generic_basic_offset,        /* offset */
2891
2892     acf_generic_idblock_name,     /* name */
2893     acf_generic_idfill_name_prop, /* name prop */
2894     acf_dsmclip_icon,             /* icon */
2895
2896     acf_generic_dataexpand_setting_valid, /* has setting */
2897     acf_dsmclip_setting_flag,             /* flag for setting */
2898     acf_dsmclip_setting_ptr,              /* pointer for setting */
2899 };
2900
2901 /* ShapeKey Entry  ------------------------------------------- */
2902
2903 /* name for ShapeKey */
2904 static void acf_shapekey_name(bAnimListElem *ale, char *name)
2905 {
2906   KeyBlock *kb = (KeyBlock *)ale->data;
2907
2908   /* just copy the name... */
2909   if (kb && name) {
2910     /* if the KeyBlock had a name, use it, otherwise use the index */
2911     if (kb->name[0])
2912       BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE);
2913     else
2914       BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index);
2915   }
2916 }
2917
2918 /* name property for ShapeKey entries */
2919 static bool acf_shapekey_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
2920 {
2921   KeyBlock *kb = (KeyBlock *)ale->data;
2922
2923   /* if the KeyBlock had a name, use it, otherwise use the index */
2924   if (kb && kb->name[0]) {
2925     RNA_pointer_create(ale->id, &RNA_ShapeKey, kb, ptr);
2926     *prop = RNA_struct_name_property(ptr->type);
2927
2928     return (*prop != NULL);
2929   }
2930
2931   return false;
2932 }
2933
2934 /* check if some setting exists for this channel */
2935 static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac),
2936                                        bAnimListElem *UNUSED(ale),
2937                                        eAnimChannel_Settings setting)
2938 {
2939   switch (setting) {
2940     case ACHANNEL_SETTING_SELECT:  /* selected */
2941     case ACHANNEL_SETTING_MUTE:    /* muted */
2942     case ACHANNEL_SETTING_PROTECT: /* protected */
2943       return true;
2944
2945     /* nothing else is supported */
2946     default:
2947       return false;
2948   }
2949 }
2950
2951 /* get the appropriate flag(s) for the setting when it is valid  */
2952 static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac),
2953                                      eAnimChannel_Settings setting,
2954                                      bool *neg)
2955 {
2956   /* clear extra return data first */
2957   *neg = false;
2958
2959   switch (setting) {
2960     case ACHANNEL_SETTING_MUTE: /* mute */
2961       return KEYBLOCK_MUTE;
2962
2963     case ACHANNEL_SETTING_SELECT: /* selected */
2964       return KEYBLOCK_SEL;
2965
2966     case ACHANNEL_SETTING_PROTECT: /* locked */
2967       return KEYBLOCK_LOCKED;
2968
2969     default: /* unsupported */
2970       return 0;
2971   }
2972 }
2973
2974 /* get pointer to the setting */
2975 static void *acf_shapekey_setting_ptr(bAnimListElem *ale,
2976                                       eAnimChannel_Settings setting,
2977                                       short *type)
2978 {
2979   KeyBlock *kb = (KeyBlock *)ale->data;
2980
2981   /* clear extra return data first */
2982   *type = 0;
2983
2984   switch (setting) {
2985     case ACHANNEL_SETTING_SELECT:  /* selected */
2986     case ACHANNEL_SETTING_MUTE:    /* muted */
2987     case ACHANNEL_SETTING_PROTECT: /* protected */
2988       return GET_ACF_FLAG_PTR(kb->flag, type);
2989
2990     default: /* unsupported */
2991       return NULL;
2992   }
2993 }
2994
2995 /* shapekey expander type define */
2996 static bAnimChannelType ACF_SHAPEKEY = {
2997     "Shape Key",           /* type name */
2998     ACHANNEL_ROLE_CHANNEL, /* role */
2999
3000     acf_generic_channel_color,    /* backdrop color */
3001     acf_generic_channel_backdrop, /* backdrop */
3002     acf_generic_indention_0,      /* indent level */
3003     acf_generic_basic_offset,     /* offset */
3004
3005     acf_shapekey_name,      /* name */
3006     acf_shapekey_name_prop, /* name prop */
3007     NULL,                   /* icon */
3008
3009     acf_shapekey_setting_valid, /* has setting */
3010     acf_shapekey_setting_flag,  /* flag for setting */
3011     acf_shapekey_setting_ptr,   /* pointer for setting */
3012 };
3013
3014 /* GPencil Datablock ------------------------------------------- */
3015
3016 /* get backdrop color for gpencil datablock widget */
3017 static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
3018 {
3019   /* these are ID-blocks, but not exactly standalone... */
3020   UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
3021 }
3022
3023 // TODO: just get this from RNA?
3024 static int acf_gpd_icon(bAnimListElem *UNUSED(ale))
3025 {
3026   return ICON_GREASEPENCIL;
3027 }
3028
3029 /* check if some setting exists for this channel */
3030 static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac),
3031                                   bAnimListElem *UNUSED(ale),
3032                                   eAnimChannel_Settings setting)
3033 {
3034   switch (setting) {
3035     /* only select and expand supported */
3036     case ACHANNEL_SETTING_SELECT:
3037     case ACHANNEL_SETTING_EXPAND:
3038       return true;
3039
3040     default:
3041       return false;
3042   }
3043 }
3044
3045 /* get the appropriate flag(s) for the setting when it is valid  */
3046 static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
3047 {
3048   /* clear extra return data first */
3049   *neg = false;
3050
3051   switch (setting) {
3052     case ACHANNEL_SETTING_SELECT: /* selected */
3053       return AGRP_SELECTED;
3054
3055     case ACHANNEL_SETTING_EXPAND: /* expanded */
3056       return GP_DATA_EXPAND;
3057
3058     default:
3059       /* these shouldn't happen */
3060       return 0;
3061   }
3062 }
3063
3064 /* get pointer to the setting */
3065 static void *acf_gpd_setting_ptr(bAnimListElem *ale,
3066                                  eAnimChannel_Settings UNUSED(setting),
3067                                  short *type)
3068 {
3069   bGPdata *gpd = (bGPdata *)ale->data;
3070
3071   /* all flags are just in gpd->flag for now... */
3072   return GET_ACF_FLAG_PTR(gpd->flag, type);
3073 }
3074
3075 /* gpencil datablock type define */
3076 static bAnimChannelType ACF_GPD = {
3077     "GPencil Datablock",    /* type name */
3078     ACHANNEL_ROLE_EXPANDER, /* role */
3079
3080     acf_gpd_color,            /* backdrop color */
3081     acf_group_backdrop,       /* backdrop */
3082     acf_generic_indention_0,  /* indent level */
3083     acf_generic_group_offset, /* offset */
3084
3085     acf_generic_idblock_name,     /* name */
3086     acf_generic_idfill_name_prop, /* name prop */
3087     acf_gpd_icon,                 /* icon */
3088
3089     acf_gpd_setting_valid, /* has setting */
3090     acf_gpd_setting_flag,  /* flag for setting */
3091     acf_gpd_setting_ptr,   /* pointer for setting */
3092 };
3093
3094 /* GPencil Layer ------------------------------------------- */
3095
3096 /* name for grease pencil layer entries */
3097 static void acf_gpl_name(bAnimListElem *ale, char *name)
3098 {
3099   bGPDlayer *gpl = (bGPDlayer *)ale->data;
3100
3101   if (gpl && name)
3102     BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
3103 }
3104
3105 /* name property for grease pencil layer entries */
3106 static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3107 {
3108   if (ale->data) {
3109     RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
3110     *prop = RNA_struct_name_property(ptr->type);
3111
3112     return (*prop != NULL);
3113   }
3114
3115   return false;
3116 }
3117
3118 /* check if some setting exists for this channel */
3119 static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac),
3120                                   bAnimListElem *UNUSED(ale),
3121                                   eAnimChannel_Settings setting)
3122 {
3123   switch (setting) {
3124     /* unsupported */
3125     case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
3126     case ACHANNEL_SETTING_SOLO:   /* nla editor only */
3127       return false;
3128
3129     /* always available */
3130     default:
3131       return true;
3132   }
3133 }
3134
3135 /* get the appropriate flag(s) for the setting when it is valid  */
3136 static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
3137 {
3138   /* clear extra return data first */
3139   *neg = false;
3140
3141   switch (setting) {
3142     case ACHANNEL_SETTING_SELECT: /* selected */
3143       return GP_LAYER_SELECT;
3144
3145     case ACHANNEL_SETTING_MUTE: /* animation muting - similar to frame lock... */
3146       return GP_LAYER_FRAMELOCK;
3147
3148     case ACHANNEL_SETTING_VISIBLE: /* visibility of the layers (NOT muting) */
3149       *neg = true;
3150       return GP_LAYER_HIDE;
3151
3152     case ACHANNEL_SETTING_PROTECT: /* protected */
3153       return GP_LAYER_LOCKED;
3154
3155     default: /* unsupported */
3156       return 0;
3157   }
3158 }
3159
3160 /* get pointer to the setting */
3161 static void *acf_gpl_setting_ptr(bAnimListElem *ale,
3162                                  eAnimChannel_Settings UNUSED(setting),
3163                                  short *type)
3164 {
3165   bGPDlayer *gpl = (bGPDlayer *)ale->data;
3166
3167   /* all flags are just in gpl->flag for now... */
3168   return GET_ACF_FLAG_PTR(gpl->flag, type);
3169 }
3170
3171 /* grease pencil layer type define */
3172 static bAnimChannelType ACF_GPL = {
3173     "GPencil Layer",       /* type name */
3174     ACHANNEL_ROLE_CHANNEL, /* role */
3175
3176     acf_gpencil_channel_color,      /* backdrop color */
3177     acf_generic_channel_backdrop,   /* backdrop */
3178     acf_generic_indention_flexible, /* indent level */
3179     acf_generic_group_offset,       /* offset */
3180
3181     acf_gpl_name,      /* name */
3182     acf_gpl_name_prop, /* name prop */
3183     NULL,              /* icon */
3184
3185     acf_gpl_setting_valid, /* has setting */
3186     acf_gpl_setting_flag,  /* flag for setting */
3187     acf_gpl_setting_ptr,   /* pointer for setting */
3188 };
3189
3190 /* Mask Datablock ------------------------------------------- */
3191
3192 /* get backdrop color for mask datablock widget */
3193 static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
3194 {
3195   /* these are ID-blocks, but not exactly standalone... */
3196   UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
3197 }
3198
3199 // TODO: just get this from RNA?
3200 static int acf_mask_icon(bAnimListElem *UNUSED(ale))
3201 {
3202   return ICON_MOD_MASK;
3203 }
3204
3205 /* check if some setting exists for this channel */
3206 static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac),
3207                                    bAnimListElem *UNUSED(ale),
3208                                    eAnimChannel_Settings setting)
3209 {
3210   switch (setting) {
3211     /* only select and expand supported */
3212     case ACHANNEL_SETTING_SELECT:
3213     case ACHANNEL_SETTING_EXPAND:
3214       return true;
3215
3216     default:
3217       return false;
3218   }
3219 }
3220
3221 /* get the appropriate flag(s) for the setting when it is valid  */
3222 static int acf_mask_setting_flag(bAnimContext *UNUSED(ac),
3223                                  eAnimChannel_Settings setting,
3224                                  bool *neg)
3225 {
3226   /* clear extra return data first */
3227   *neg = false;
3228
3229   switch (setting) {
3230     case ACHANNEL_SETTING_SELECT: /* selected */
3231       return AGRP_SELECTED;
3232
3233     case ACHANNEL_SETTING_EXPAND: /* expanded */
3234       return MASK_ANIMF_EXPAND;
3235
3236     default:
3237       /* this shouldn't happen */
3238       return 0;
3239   }
3240 }
3241
3242 /* get pointer to the setting */
3243 static void *acf_mask_setting_ptr(bAnimListElem *ale,
3244                                   eAnimChannel_Settings UNUSED(setting),
3245                                   short *type)
3246 {
3247   Mask *mask = (Mask *)ale->data;
3248
3249   /* all flags are just in mask->flag for now... */
3250   return GET_ACF_FLAG_PTR(mask->flag, type);
3251 }
3252
3253 /* mask datablock type define */
3254 static bAnimChannelType ACF_MASKDATA = {
3255     "Mask Datablock",       /* type name */
3256     ACHANNEL_ROLE_EXPANDER, /* role */
3257
3258     acf_mask_color,           /* backdrop color */
3259     acf_group_backdrop,       /* backdrop */
3260     acf_generic_indention_0,  /* indent level */
3261     acf_generic_group_offset, /* offset */
3262
3263     acf_generic_idblock_name,     /* name */
3264     acf_generic_idfill_name_prop, /* name prop */
3265     acf_mask_icon,                /* icon */
3266
3267     acf_mask_setting_valid, /* has setting */
3268     acf_mask_setting_flag,  /* flag for setting */
3269     acf_mask_setting_ptr,   /* pointer for setting */
3270 };
3271
3272 /* Mask Layer ------------------------------------------- */
3273
3274 /* name for grease pencil layer entries */
3275 static void acf_masklay_name(bAnimListElem *ale, char *name)
3276 {
3277   MaskLayer *masklay = (MaskLayer *)ale->data;
3278
3279   if (masklay && name)
3280     BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
3281 }
3282
3283 /* name property for grease pencil layer entries */
3284 static bool acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3285 {
3286   if (ale->data) {
3287     RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
3288     *prop = RNA_struct_name_property(ptr->type);
3289
3290     return (*prop != NULL);
3291   }
3292
3293   return false;
3294 }
3295
3296 /* check if some setting exists for this channel */
3297 static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac),
3298                                       bAnimListElem *UNUSED(ale),
3299                                       eAnimChannel_Settings setting)
3300 {
3301   switch (setting) {
3302     /* unsupported */
3303     case ACHANNEL_SETTING_EXPAND:  /* mask layers are more like F-Curves than groups */
3304     case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
3305     case ACHANNEL_SETTING_SOLO:    /* nla editor only */
3306       return false;
3307
3308     /* always available */
3309     default:
3310       return true;
3311   }
3312 }
3313
3314 /* get the appropriate flag(s) for the setting when it is valid  */
3315 static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac),
3316                                     eAnimChannel_Settings setting,
3317                                     bool *neg)
3318 {
3319   /* clear extra return data first */
3320   *neg = false;
3321
3322   switch (setting) {
3323     case ACHANNEL_SETTING_SELECT: /* selected */
3324       return MASK_LAYERFLAG_SELECT;
3325
3326     case ACHANNEL_SETTING_PROTECT: /* protected */
3327       return MASK_LAYERFLAG_LOCKED;
3328
3329     default: /* unsupported */
3330       return 0;
3331   }
3332 }
3333
3334 /* get pointer to the setting */
3335 static void *acf_masklay_setting_ptr(bAnimListElem *ale,
3336                                      eAnimChannel_Settings UNUSED(setting),
3337                                      short *type)
3338 {
3339   MaskLayer *masklay = (MaskLayer *)ale->data;
3340
3341   /* all flags are just in masklay->flag for now... */
3342   return GET_ACF_FLAG_PTR(masklay->flag, type);
3343 }
3344
3345 /* grease pencil layer type define */
3346 static bAnimChannelType ACF_MASKLAYER = {
3347     "Mask Layer",          /* type name */
3348     ACHANNEL_ROLE_CHANNEL, /* role */
3349
3350     acf_generic_channel_color,      /* backdrop color */
3351     acf_generic_channel_backdrop,   /* backdrop */
3352     acf_generic_indention_flexible, /* indent level */
3353     acf_generic_group_offset,       /* offset */
3354
3355     acf_masklay_name,      /* name */
3356     acf_masklay_name_prop, /* name prop */
3357     NULL,                  /* icon */
3358
3359     acf_masklay_setting_valid, /* has setting */
3360     acf_masklay_setting_flag,  /* flag for setting */
3361     acf_masklay_setting_ptr,   /* pointer for setting */
3362 };
3363
3364 /* NLA Track ----------------------------------------------- */
3365
3366 /* get backdrop color for nla track channels */
3367 static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
3368 {
3369   NlaTrack *nlt = (NlaTrack *)ale->data;
3370   AnimData *adt = ale->adt;
3371   bool nonSolo = false;
3372
3373   /* is track enabled for solo drawing? */
3374   if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
3375     if ((nlt->flag & NLATRACK_SOLO) == 0) {
3376       /* tag for special non-solo handling */
3377       nonSolo = true;
3378     }
3379   }
3380
3381   /* set color for nla track */
3382   UI_GetThemeColorShade3fv(TH_HEADER, ((nonSolo == false) ? 20 : -20), r_color);
3383 }
3384
3385 /* name for nla track entries */
3386 static void acf_nlatrack_name(bAnimListElem *ale, char *name)
3387 {
3388   NlaTrack *nlt = (NlaTrack *)ale->data;
3389
3390   if (nlt && name)
3391     BLI_strncpy(name, nlt->name, ANIM_CHAN_NAME_SIZE);
3392 }
3393
3394 /* name property for nla track entries */
3395 static bool acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3396 {
3397   if (ale->data) {
3398     RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
3399     *prop = RNA_struct_name_property(ptr->type);
3400
3401     return (*prop != NULL);
3402   }
3403
3404   return false;
3405 }
3406
3407 /* check if some setting exists for this channel */
3408 static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac),
3409                                        bAnimListElem *ale,
3410                                        eAnimChannel_Settings setting)
3411 {
3412   NlaTrack *nlt = (NlaTrack *)ale->data;
3413   AnimData *adt = ale->adt;
3414
3415   /* visibility of settings depends on various states... */
3416   switch (setting) {
3417     /* always supported */
3418     case ACHANNEL_SETTING_SELECT:
3419     case ACHANNEL_SETTING_SOLO:
3420       return true;
3421
3422     /* conditionally supported... */
3423     case ACHANNEL_SETTING_PROTECT:
3424     case ACHANNEL_SETTING_MUTE:
3425       /* if this track is active and we're tweaking it, don't draw these toggles */
3426       if (((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0) {
3427         /* is track enabled for solo drawing? */
3428         if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
3429           if (nlt->flag & NLATRACK_SOLO) {
3430             /* ok - we've got a solo track, and this is it */
3431             return true;
3432           }
3433           else {
3434             /* not ok - we've got a solo track, but this isn't it, so make it more obvious */
3435             return false;
3436           }
3437         }
3438
3439         /* ok - no tracks are solo'd, and this isn't being tweaked */
3440         return true;
3441       }
3442       else {
3443         /* unsupported - this track is being tweaked */
3444         return false;
3445       }
3446
3447     /* unsupported */
3448     default:
3449       return false;
3450   }
3451 }
3452
3453 /* get the appropriate flag(s) for the setting when it is valid  */
3454 static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac),
3455                                      eAnimChannel_Settings setting,
3456                                      bool *neg)
3457 {
3458   /* clear extra return data first */
3459   *neg = false;
3460
3461   switch (setting) {
3462     case ACHANNEL_SETTING_SELECT: /* selected */
3463       return NLATRACK_SELECTED;
3464
3465     case ACHANNEL_SETTING_MUTE: /* muted */
3466       return NLATRACK_MUTED;
3467
3468     case ACHANNEL_SETTING_PROTECT: /* protected */
3469       return NLATRACK_PROTECTED;
3470
3471     case ACHANNEL_SETTING_SOLO: /* solo */
3472       return NLATRACK_SOLO;
3473
3474     default: /* unsupported */
3475       return 0;
3476   }
3477 }
3478
3479 /* get pointer to the setting */
3480 static void *acf_nlatrack_setting_ptr(bAnimListElem *ale,
3481                                       eAnimChannel_Settings UNUSED(setting),
3482                                       short *type)
3483 {
3484   NlaTrack *nlt = (NlaTrack *)ale->data;
3485   return GET_ACF_FLAG_PTR(nlt->flag, type);
3486 }
3487
3488 /* nla track type define */
3489 static bAnimChannelType ACF_NLATRACK = {
3490     "NLA Track",           /* type name */
3491     ACHANNEL_ROLE_CHANNEL, /* role */
3492
3493     acf_nlatrack_color,             /* backdrop color */
3494     acf_generic_channel_backdrop,   /* backdrop */
3495     acf_generic_indention_flexible, /* indent level */
3496     acf_generic_group_offset,
3497     /* offset */  // XXX?
3498
3499     acf_nlatrack_name,      /* name */
3500     acf_nlatrack_name_prop, /* name prop */
3501     NULL,                   /* icon */
3502
3503     acf_nlatrack_setting_valid, /* has setting */
3504     acf_nlatrack_setting_flag,  /* flag for setting */
3505     acf_nlatrack_setting_ptr,   /* pointer for setting */
3506 };
3507
3508 /* NLA Action ----------------------------------------------- */
3509
3510 /* icon for action depends on whether it's in tweaking mode */
3511 static int acf_nlaaction_icon(bAnimListElem *ale)
3512 {
3513   AnimData *adt = ale->adt;
3514
3515   /* indicate tweaking-action state by changing the icon... */
3516   if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
3517     return ICON_ACTION_TWEAK;
3518   }
3519   else {
3520     return ICON_ACTION;
3521   }
3522 }
3523
3524 /* Backdrop color for nla action channel
3525  * Although this can't be used directly for NLA Action drawing,
3526  * it is still needed for use behind the RHS toggles
3527  */
3528 static void acf_nlaaction_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])