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