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_gpencil_types.h"
39 #include "DNA_hair_types.h"
40 #include "DNA_key_types.h"
41 #include "DNA_lattice_types.h"
42 #include "DNA_light_types.h"
43 #include "DNA_linestyle_types.h"
44 #include "DNA_mask_types.h"
45 #include "DNA_material_types.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_meta_types.h"
48 #include "DNA_node_types.h"
49 #include "DNA_object_types.h"
50 #include "DNA_particle_types.h"
51 #include "DNA_pointcloud_types.h"
52 #include "DNA_scene_types.h"
53 #include "DNA_screen_types.h"
54 #include "DNA_simulation_types.h"
55 #include "DNA_space_types.h"
56 #include "DNA_speaker_types.h"
57 #include "DNA_volume_types.h"
58 #include "DNA_world_types.h"
59 
60 #include "RNA_access.h"
61 
62 #include "BKE_anim_data.h"
63 #include "BKE_animsys.h"
64 #include "BKE_context.h"
65 #include "BKE_curve.h"
66 #include "BKE_gpencil.h"
67 #include "BKE_key.h"
68 #include "BKE_main.h"
69 #include "BKE_nla.h"
70 
71 #include "GPU_immediate.h"
72 #include "GPU_state.h"
73 
74 #include "DEG_depsgraph.h"
75 
76 #include "UI_interface.h"
77 #include "UI_interface_icons.h"
78 #include "UI_resources.h"
79 #include "UI_view2d.h"
80 
81 #include "ED_anim_api.h"
82 #include "ED_keyframing.h"
83 
84 #include "WM_api.h"
85 #include "WM_types.h"
86 
87 /* *********************************************** */
88 /* XXX constant defines to be moved elsewhere? */
89 
90 /* extra padding for lengths (to go under scrollers) */
91 #define EXTRA_SCROLL_PAD 100.0f
92 
93 /* size of indent steps */
94 #define INDENT_STEP_SIZE (0.35f * U.widget_unit)
95 
96 /* size of string buffers used for animation channel displayed names */
97 #define ANIM_CHAN_NAME_SIZE 256
98 
99 /* get the pointer used for some flag */
100 #define GET_ACF_FLAG_PTR(ptr, type) ((*(type) = sizeof((ptr))), &(ptr))
101 
102 /* *********************************************** */
103 /* Generic Functions (Type independent) */
104 
105 /* Draw Backdrop ---------------------------------- */
106 
107 /* get backdrop color for top-level widgets (Scene and Object only) */
acf_generic_root_color(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),float r_color[3])108 static void acf_generic_root_color(bAnimContext *UNUSED(ac),
109                                    bAnimListElem *UNUSED(ale),
110                                    float r_color[3])
111 {
112   /* darker blue for top-level widgets */
113   UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELOB, r_color);
114 }
115 
116 /* backdrop for top-level widgets (Scene and Object only) */
acf_generic_root_backdrop(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc)117 static void acf_generic_root_backdrop(bAnimContext *ac,
118                                       bAnimListElem *ale,
119                                       float yminc,
120                                       float ymaxc)
121 {
122   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
123   View2D *v2d = &ac->region->v2d;
124   short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
125   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
126   float color[3];
127 
128   /* set backdrop drawing color */
129   acf->get_backdrop_color(ac, ale, color);
130 
131   /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
132   UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT :
133                                            (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
134   UI_draw_roundbox_3fv_alpha(
135       true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
136 }
137 
138 /* get backdrop color for data expanders under top-level Scene/Object */
acf_generic_dataexpand_color(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),float r_color[3])139 static void acf_generic_dataexpand_color(bAnimContext *UNUSED(ac),
140                                          bAnimListElem *UNUSED(ale),
141                                          float r_color[3])
142 {
143   /* lighter color than top-level widget */
144   UI_GetThemeColor3fv(TH_DOPESHEET_CHANNELSUBOB, r_color);
145 }
146 
147 /* backdrop for data expanders under top-level Scene/Object */
acf_generic_dataexpand_backdrop(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc)148 static void acf_generic_dataexpand_backdrop(bAnimContext *ac,
149                                             bAnimListElem *ale,
150                                             float yminc,
151                                             float ymaxc)
152 {
153   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
154   View2D *v2d = &ac->region->v2d;
155   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
156   float color[3];
157 
158   uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
159 
160   /* set backdrop drawing color */
161   acf->get_backdrop_color(ac, ale, color);
162 
163   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
164   immUniformColor3fv(color);
165 
166   /* no rounded corner - just rectangular box */
167   immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
168 
169   immUnbindProgram();
170 }
171 
172 /* helper method to test if group colors should be drawn */
acf_show_channel_colors(bAnimContext * ac)173 static bool acf_show_channel_colors(bAnimContext *ac)
174 {
175   bool showGroupColors = false;
176 
177   if (ac->sl) {
178     switch (ac->spacetype) {
179       case SPACE_ACTION: {
180         SpaceAction *saction = (SpaceAction *)ac->sl;
181         showGroupColors = !(saction->flag & SACTION_NODRAWGCOLORS);
182 
183         break;
184       }
185       case SPACE_GRAPH: {
186         SpaceGraph *sipo = (SpaceGraph *)ac->sl;
187         showGroupColors = !(sipo->flag & SIPO_NODRAWGCOLORS);
188 
189         break;
190       }
191     }
192   }
193 
194   return showGroupColors;
195 }
196 
197 /* get backdrop color for generic channels */
acf_generic_channel_color(bAnimContext * ac,bAnimListElem * ale,float r_color[3])198 static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
199 {
200   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
201   bActionGroup *grp = NULL;
202   short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
203   bool showGroupColors = acf_show_channel_colors(ac);
204 
205   if (ale->type == ANIMTYPE_FCURVE) {
206     FCurve *fcu = (FCurve *)ale->data;
207     grp = fcu->grp;
208   }
209 
210   /* set color for normal channels
211    * - use 3 shades of color group/standard color for 3 indention level
212    * - only use group colors if allowed to, and if actually feasible
213    */
214   if (showGroupColors && (grp) && (grp->customCol)) {
215     uchar cp[3];
216 
217     if (indent == 2) {
218       copy_v3_v3_uchar(cp, grp->cs.solid);
219     }
220     else if (indent == 1) {
221       copy_v3_v3_uchar(cp, grp->cs.select);
222     }
223     else {
224       copy_v3_v3_uchar(cp, grp->cs.active);
225     }
226 
227     /* copy the colors over, transforming from bytes to floats */
228     rgb_uchar_to_float(r_color, cp);
229   }
230   else {
231     /* FIXME: what happens when the indention is 1 greater than what it should be
232      * (due to grouping)? */
233     int colOfs = 10 - 10 * indent;
234     UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
235   }
236 }
237 
238 /* get backdrop color for grease pencil channels */
acf_gpencil_channel_color(bAnimContext * ac,bAnimListElem * ale,float r_color[3])239 static void acf_gpencil_channel_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
240 {
241   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
242   short indent = (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
243   bool showGroupColors = acf_show_channel_colors(ac);
244 
245   if ((showGroupColors) && (ale->type == ANIMTYPE_GPLAYER)) {
246     bGPDlayer *gpl = (bGPDlayer *)ale->data;
247     copy_v3_v3(r_color, gpl->color);
248   }
249   else {
250     int colOfs = 10 - 10 * indent;
251     UI_GetThemeColorShade3fv(TH_SHADE2, colOfs, r_color);
252   }
253 }
254 
255 /* backdrop for generic channels */
acf_generic_channel_backdrop(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc)256 static void acf_generic_channel_backdrop(bAnimContext *ac,
257                                          bAnimListElem *ale,
258                                          float yminc,
259                                          float ymaxc)
260 {
261   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
262   View2D *v2d = &ac->region->v2d;
263   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
264   float color[3];
265 
266   uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
267 
268   /* set backdrop drawing color */
269   acf->get_backdrop_color(ac, ale, color);
270 
271   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
272   immUniformColor3fv(color);
273 
274   /* no rounded corners - just rectangular box */
275   immRectf(pos, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc);
276 
277   immUnbindProgram();
278 }
279 
280 /* Indention + Offset ------------------------------------------- */
281 
282 /* indention level is always the value in the name */
acf_generic_indention_0(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale))283 static short acf_generic_indention_0(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
284 {
285   return 0;
286 }
acf_generic_indention_1(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale))287 static short acf_generic_indention_1(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
288 {
289   return 1;
290 }
291 #if 0 /* XXX not used */
292 static short acf_generic_indention_2(bAnimContext *ac, bAnimListElem *ale)
293 {
294   return 2;
295 }
296 #endif
297 
298 /* indention which varies with the grouping status */
acf_generic_indention_flexible(bAnimContext * UNUSED (ac),bAnimListElem * ale)299 static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListElem *ale)
300 {
301   short indent = 0;
302 
303   /* grouped F-Curves need extra level of indention */
304   if (ale->type == ANIMTYPE_FCURVE) {
305     FCurve *fcu = (FCurve *)ale->data;
306 
307     /* TODO: we need some way of specifying that the indention color should be one less. */
308     if (fcu->grp) {
309       indent++;
310     }
311   }
312 
313   /* no indention */
314   return indent;
315 }
316 
317 /* basic offset for channels derived from indention */
acf_generic_basic_offset(bAnimContext * ac,bAnimListElem * ale)318 static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
319 {
320   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
321 
322   if (acf && acf->get_indent_level) {
323     return acf->get_indent_level(ac, ale) * INDENT_STEP_SIZE;
324   }
325   return 0;
326 }
327 
328 /* offset based on nodetree type */
acf_nodetree_rootType_offset(bNodeTree * ntree)329 static short acf_nodetree_rootType_offset(bNodeTree *ntree)
330 {
331   if (ntree) {
332     switch (ntree->type) {
333       case NTREE_SHADER:
334         /* 1 additional level (i.e. is indented one level in from material,
335          * so shift all right by one step)
336          */
337         return INDENT_STEP_SIZE;
338 
339       case NTREE_COMPOSIT:
340         /* no additional levels needed */
341         return 0;
342 
343       case NTREE_TEXTURE:
344         /* 2 additional levels */
345         return INDENT_STEP_SIZE * 2;
346     }
347   }
348 
349   /* unknown */
350   return 0;
351 }
352 
353 /* offset for groups + grouped entities */
acf_generic_group_offset(bAnimContext * ac,bAnimListElem * ale)354 static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
355 {
356   short offset = acf_generic_basic_offset(ac, ale);
357 
358   if (ale->id) {
359     /* texture animdata */
360     if (GS(ale->id->name) == ID_TE) {
361       offset += U.widget_unit;
362     }
363     /* materials and particles animdata */
364     else if (ELEM(GS(ale->id->name), ID_MA, ID_PA)) {
365       offset += (short)(0.7f * U.widget_unit);
366 
367       /* If not in Action Editor mode, action-groups (and their children)
368        * must carry some offset too. */
369     }
370     else if (ac->datatype != ANIMCONT_ACTION) {
371       offset += (short)(0.7f * U.widget_unit);
372     }
373 
374     /* nodetree animdata */
375     if (GS(ale->id->name) == ID_NT) {
376       offset += acf_nodetree_rootType_offset((bNodeTree *)ale->id);
377     }
378   }
379 
380   /* offset is just the normal type - i.e. based on indention */
381   return offset;
382 }
383 
384 /* Name ------------------------------------------- */
385 
386 /* name for ID block entries */
acf_generic_idblock_name(bAnimListElem * ale,char * name)387 static void acf_generic_idblock_name(bAnimListElem *ale, char *name)
388 {
389   ID *id = (ID *)ale->data; /* data pointed to should be an ID block */
390 
391   /* just copy the name... */
392   if (id && name) {
393     BLI_strncpy(name, id->name + 2, ANIM_CHAN_NAME_SIZE);
394   }
395 }
396 
397 /* name property for ID block entries */
acf_generic_idblock_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)398 static bool acf_generic_idblock_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
399 {
400   RNA_id_pointer_create(ale->data, ptr);
401   *prop = RNA_struct_name_property(ptr->type);
402 
403   return (*prop != NULL);
404 }
405 
406 /* name property for ID block entries which are just subheading "fillers" */
acf_generic_idfill_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)407 static bool acf_generic_idfill_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
408 {
409   /* actual ID we're representing is stored in ale->data not ale->id, as id gives the owner */
410   RNA_id_pointer_create(ale->data, ptr);
411   *prop = RNA_struct_name_property(ptr->type);
412 
413   return (*prop != NULL);
414 }
415 
416 /* Settings ------------------------------------------- */
417 
418 #if 0
419 /* channel type has no settings */
420 static bool acf_generic_none_setting_valid(bAnimContext *ac,
421                                            bAnimListElem *ale,
422                                            eAnimChannel_Settings setting)
423 {
424   return false;
425 }
426 #endif
427 
428 /* check if some setting exists for this object-based data-expander (datablock only) */
acf_generic_dataexpand_setting_valid(bAnimContext * ac,bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)429 static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac,
430                                                  bAnimListElem *UNUSED(ale),
431                                                  eAnimChannel_Settings setting)
432 {
433   switch (setting) {
434     /* expand is always supported */
435     case ACHANNEL_SETTING_EXPAND:
436       return true;
437 
438     /* mute is only supported for NLA */
439     case ACHANNEL_SETTING_MUTE:
440       return ((ac) && (ac->spacetype == SPACE_NLA));
441 
442     /* select is ok for most "ds*" channels (e.g. dsmat) */
443     case ACHANNEL_SETTING_SELECT:
444       return true;
445 
446     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
447       return true;
448 
449     /* other flags are never supported */
450     default:
451       return false;
452   }
453 }
454 
455 /* *********************************************** */
456 /* Type Specific Functions + Defines */
457 
458 /* Animation Summary ----------------------------------- */
459 
460 /* get backdrop color for summary widget */
acf_summary_color(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),float r_color[3])461 static void acf_summary_color(bAnimContext *UNUSED(ac),
462                               bAnimListElem *UNUSED(ale),
463                               float r_color[3])
464 {
465   /* reddish color - same as the 'action' line in NLA */
466   UI_GetThemeColor3fv(TH_ANIM_ACTIVE, r_color);
467 }
468 
469 /* backdrop for summary widget */
acf_summary_backdrop(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc)470 static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
471 {
472   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
473   View2D *v2d = &ac->region->v2d;
474   float color[3];
475 
476   /* set backdrop drawing color */
477   acf->get_backdrop_color(ac, ale, color);
478 
479   /* rounded corners on LHS only
480    * - top and bottom
481    * - special hack: make the top a bit higher, since we are first...
482    */
483   UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT);
484   UI_draw_roundbox_3fv_alpha(
485       true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
486 }
487 
488 /* name for summary entries */
acf_summary_name(bAnimListElem * UNUSED (ale),char * name)489 static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
490 {
491   if (name) {
492     BLI_strncpy(name, IFACE_("Summary"), ANIM_CHAN_NAME_SIZE);
493   }
494 }
495 
496 /* check if some setting exists for this channel */
acf_summary_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)497 static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac),
498                                       bAnimListElem *UNUSED(ale),
499                                       eAnimChannel_Settings setting)
500 {
501   /* only expanded is supported, as it is used for hiding all stuff which the summary covers */
502   return (setting == ACHANNEL_SETTING_EXPAND);
503 }
504 
505 /* get the appropriate flag(s) for the setting when it is valid  */
acf_summary_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)506 static int acf_summary_setting_flag(bAnimContext *UNUSED(ac),
507                                     eAnimChannel_Settings setting,
508                                     bool *neg)
509 {
510   if (setting == ACHANNEL_SETTING_EXPAND) {
511     /* expanded */
512     *neg = true;
513     return ADS_FLAG_SUMMARY_COLLAPSED;
514   }
515 
516   /* unsupported */
517   *neg = false;
518   return 0;
519 }
520 
521 /* get pointer to the setting */
acf_summary_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)522 static void *acf_summary_setting_ptr(bAnimListElem *ale,
523                                      eAnimChannel_Settings setting,
524                                      short *type)
525 {
526   bAnimContext *ac = (bAnimContext *)ale->data;
527 
528   /* if data is valid, return pointer to active dopesheet's relevant flag
529    * - this is restricted to DopeSheet/Action Editor only
530    */
531   if ((ac->sl) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
532     SpaceAction *saction = (SpaceAction *)ac->sl;
533     bDopeSheet *ads = &saction->ads;
534 
535     /* return pointer to DopeSheet's flag */
536     return GET_ACF_FLAG_PTR(ads->flag, type);
537   }
538 
539   /* can't return anything useful - unsupported */
540   *type = 0;
541   return NULL;
542 }
543 
544 /* all animation summary (DopeSheet only) type define */
545 static bAnimChannelType ACF_SUMMARY = {
546     "Summary",              /* type name */
547     ACHANNEL_ROLE_EXPANDER, /* role */
548 
549     acf_summary_color,       /* backdrop color */
550     acf_summary_backdrop,    /* backdrop */
551     acf_generic_indention_0, /* indent level */
552     NULL,                    /* offset */
553 
554     acf_summary_name, /* name */
555     NULL,             /* name prop */
556     NULL,             /* icon */
557 
558     acf_summary_setting_valid, /* has setting */
559     acf_summary_setting_flag,  /* flag for setting */
560     acf_summary_setting_ptr,   /* pointer for setting */
561 };
562 
563 /* Scene ------------------------------------------- */
564 
565 /* TODO: just get this from RNA? */
acf_scene_icon(bAnimListElem * UNUSED (ale))566 static int acf_scene_icon(bAnimListElem *UNUSED(ale))
567 {
568   return ICON_SCENE_DATA;
569 }
570 
571 /* check if some setting exists for this channel */
acf_scene_setting_valid(bAnimContext * ac,bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)572 static bool acf_scene_setting_valid(bAnimContext *ac,
573                                     bAnimListElem *UNUSED(ale),
574                                     eAnimChannel_Settings setting)
575 {
576   switch (setting) {
577     /* muted only in NLA */
578     case ACHANNEL_SETTING_MUTE:
579       return ((ac) && (ac->spacetype == SPACE_NLA));
580 
581     /* visible only in Graph Editor */
582     case ACHANNEL_SETTING_VISIBLE:
583       return ((ac) && (ac->spacetype == SPACE_GRAPH));
584 
585     /* only select and expand supported otherwise */
586     case ACHANNEL_SETTING_SELECT:
587     case ACHANNEL_SETTING_EXPAND:
588       return true;
589 
590     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
591       return false;
592 
593     default:
594       return false;
595   }
596 }
597 
598 /* get the appropriate flag(s) for the setting when it is valid  */
acf_scene_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)599 static int acf_scene_setting_flag(bAnimContext *UNUSED(ac),
600                                   eAnimChannel_Settings setting,
601                                   bool *neg)
602 {
603   /* clear extra return data first */
604   *neg = false;
605 
606   switch (setting) {
607     case ACHANNEL_SETTING_SELECT: /* selected */
608       return SCE_DS_SELECTED;
609 
610     case ACHANNEL_SETTING_EXPAND: /* expanded */
611       *neg = true;
612       return SCE_DS_COLLAPSED;
613 
614     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
615       return ADT_NLA_EVAL_OFF;
616 
617     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
618       *neg = true;
619       return ADT_CURVES_NOT_VISIBLE;
620 
621     default: /* unsupported */
622       return 0;
623   }
624 }
625 
626 /* get pointer to the setting */
acf_scene_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)627 static void *acf_scene_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
628 {
629   Scene *scene = (Scene *)ale->data;
630 
631   /* clear extra return data first */
632   *type = 0;
633 
634   switch (setting) {
635     case ACHANNEL_SETTING_SELECT: /* selected */
636       return GET_ACF_FLAG_PTR(scene->flag, type);
637 
638     case ACHANNEL_SETTING_EXPAND: /* expanded */
639       return GET_ACF_FLAG_PTR(scene->flag, type);
640 
641     case ACHANNEL_SETTING_MUTE:    /* mute (only in NLA) */
642     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
643       if (scene->adt) {
644         return GET_ACF_FLAG_PTR(scene->adt->flag, type);
645       }
646       return NULL;
647 
648     default: /* unsupported */
649       return NULL;
650   }
651 }
652 
653 /* scene type define */
654 static bAnimChannelType ACF_SCENE = {
655     "Scene",                /* type name */
656     ACHANNEL_ROLE_EXPANDER, /* role */
657 
658     acf_generic_root_color,    /* backdrop color */
659     acf_generic_root_backdrop, /* backdrop */
660     acf_generic_indention_0,   /* indent level */
661     NULL,                      /* offset */
662 
663     acf_generic_idblock_name,      /* name */
664     acf_generic_idblock_name_prop, /* name prop */
665     acf_scene_icon,                /* icon */
666 
667     acf_scene_setting_valid, /* has setting */
668     acf_scene_setting_flag,  /* flag for setting */
669     acf_scene_setting_ptr,   /* pointer for setting */
670 };
671 
672 /* Object ------------------------------------------- */
673 
acf_object_icon(bAnimListElem * ale)674 static int acf_object_icon(bAnimListElem *ale)
675 {
676   Base *base = (Base *)ale->data;
677   Object *ob = base->object;
678 
679   /* icon depends on object-type */
680   switch (ob->type) {
681     case OB_LAMP:
682       return ICON_OUTLINER_OB_LIGHT;
683     case OB_MESH:
684       return ICON_OUTLINER_OB_MESH;
685     case OB_CAMERA:
686       return ICON_OUTLINER_OB_CAMERA;
687     case OB_CURVE:
688       return ICON_OUTLINER_OB_CURVE;
689     case OB_MBALL:
690       return ICON_OUTLINER_OB_META;
691     case OB_LATTICE:
692       return ICON_OUTLINER_OB_LATTICE;
693     case OB_SPEAKER:
694       return ICON_OUTLINER_OB_SPEAKER;
695     case OB_LIGHTPROBE:
696       return ICON_OUTLINER_OB_LIGHTPROBE;
697     case OB_ARMATURE:
698       return ICON_OUTLINER_OB_ARMATURE;
699     case OB_FONT:
700       return ICON_OUTLINER_OB_FONT;
701     case OB_SURF:
702       return ICON_OUTLINER_OB_SURFACE;
703     case OB_HAIR:
704       return ICON_OUTLINER_OB_HAIR;
705     case OB_POINTCLOUD:
706       return ICON_OUTLINER_OB_POINTCLOUD;
707     case OB_VOLUME:
708       return ICON_OUTLINER_OB_VOLUME;
709     case OB_EMPTY:
710       return ICON_OUTLINER_OB_EMPTY;
711     case OB_GPENCIL:
712       return ICON_OUTLINER_OB_GREASEPENCIL;
713     default:
714       return ICON_OBJECT_DATA;
715   }
716 }
717 
718 /* name for object */
acf_object_name(bAnimListElem * ale,char * name)719 static void acf_object_name(bAnimListElem *ale, char *name)
720 {
721   Base *base = (Base *)ale->data;
722   Object *ob = base->object;
723 
724   /* just copy the name... */
725   if (ob && name) {
726     BLI_strncpy(name, ob->id.name + 2, ANIM_CHAN_NAME_SIZE);
727   }
728 }
729 
730 /* name property for object */
acf_object_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)731 static bool acf_object_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
732 {
733   RNA_id_pointer_create(ale->id, ptr);
734   *prop = RNA_struct_name_property(ptr->type);
735 
736   return (*prop != NULL);
737 }
738 
739 /* check if some setting exists for this channel */
acf_object_setting_valid(bAnimContext * ac,bAnimListElem * ale,eAnimChannel_Settings setting)740 static bool acf_object_setting_valid(bAnimContext *ac,
741                                      bAnimListElem *ale,
742                                      eAnimChannel_Settings setting)
743 {
744   Base *base = (Base *)ale->data;
745   Object *ob = base->object;
746 
747   switch (setting) {
748     /* muted only in NLA */
749     case ACHANNEL_SETTING_MUTE:
750       return ((ac) && (ac->spacetype == SPACE_NLA));
751 
752     /* visible only in Graph Editor */
753     case ACHANNEL_SETTING_VISIBLE:
754       return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
755 
756     /* only select and expand supported otherwise */
757     case ACHANNEL_SETTING_SELECT:
758     case ACHANNEL_SETTING_EXPAND:
759       return true;
760 
761     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
762       return ((ac) && (ac->spacetype == SPACE_GRAPH) && (ob->adt));
763 
764     default:
765       return false;
766   }
767 }
768 
769 /* get the appropriate flag(s) for the setting when it is valid  */
acf_object_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)770 static int acf_object_setting_flag(bAnimContext *UNUSED(ac),
771                                    eAnimChannel_Settings setting,
772                                    bool *neg)
773 {
774   /* clear extra return data first */
775   *neg = false;
776 
777   switch (setting) {
778     case ACHANNEL_SETTING_SELECT: /* selected */
779       return BASE_SELECTED;
780 
781     case ACHANNEL_SETTING_EXPAND: /* expanded */
782       *neg = 1;
783       return OB_ADS_COLLAPSED;
784 
785     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
786       return ADT_NLA_EVAL_OFF;
787 
788     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
789       *neg = true;
790       return ADT_CURVES_NOT_VISIBLE;
791 
792     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
793       return ADT_CURVES_ALWAYS_VISIBLE;
794 
795     default: /* unsupported */
796       return 0;
797   }
798 }
799 
800 /* get pointer to the setting */
acf_object_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)801 static void *acf_object_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
802 {
803   Base *base = (Base *)ale->data;
804   Object *ob = base->object;
805 
806   /* clear extra return data first */
807   *type = 0;
808 
809   switch (setting) {
810     case ACHANNEL_SETTING_SELECT: /* selected */
811       return GET_ACF_FLAG_PTR(base->flag, type);
812 
813     case ACHANNEL_SETTING_EXPAND:                 /* expanded */
814       return GET_ACF_FLAG_PTR(ob->nlaflag, type); /* XXX */
815 
816     case ACHANNEL_SETTING_MUTE:    /* mute (only in NLA) */
817     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
818     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
819       if (ob->adt) {
820         return GET_ACF_FLAG_PTR(ob->adt->flag, type);
821       }
822       return NULL;
823 
824     default: /* unsupported */
825       return NULL;
826   }
827 }
828 
829 /* object type define */
830 static bAnimChannelType ACF_OBJECT = {
831     "Object",               /* type name */
832     ACHANNEL_ROLE_EXPANDER, /* role */
833 
834     acf_generic_root_color,    /* backdrop color */
835     acf_generic_root_backdrop, /* backdrop */
836     acf_generic_indention_0,   /* indent level */
837     NULL,                      /* offset */
838 
839     acf_object_name,      /* name */
840     acf_object_name_prop, /* name prop */
841     acf_object_icon,      /* icon */
842 
843     acf_object_setting_valid, /* has setting */
844     acf_object_setting_flag,  /* flag for setting */
845     acf_object_setting_ptr,   /* pointer for setting */
846 };
847 
848 /* Group ------------------------------------------- */
849 
850 /* get backdrop color for group widget */
acf_group_color(bAnimContext * ac,bAnimListElem * ale,float r_color[3])851 static void acf_group_color(bAnimContext *ac, bAnimListElem *ale, float r_color[3])
852 {
853   bActionGroup *agrp = (bActionGroup *)ale->data;
854   bool showGroupColors = acf_show_channel_colors(ac);
855 
856   if (showGroupColors && agrp->customCol) {
857     uchar cp[3];
858 
859     /* highlight only for active */
860     if (ale->flag & AGRP_ACTIVE) {
861       copy_v3_v3_uchar(cp, agrp->cs.select);
862     }
863     else {
864       copy_v3_v3_uchar(cp, agrp->cs.solid);
865     }
866 
867     /* copy the colors over, transforming from bytes to floats */
868     rgb_uchar_to_float(r_color, cp);
869   }
870   else {
871     /* highlight only for active */
872     if (ale->flag & AGRP_ACTIVE) {
873       UI_GetThemeColor3fv(TH_GROUP_ACTIVE, r_color);
874     }
875     else {
876       UI_GetThemeColor3fv(TH_GROUP, r_color);
877     }
878   }
879 }
880 
881 /* backdrop for group widget */
acf_group_backdrop(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc)882 static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
883 {
884   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
885   View2D *v2d = &ac->region->v2d;
886   short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
887   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
888   float color[3];
889 
890   /* set backdrop drawing color */
891   acf->get_backdrop_color(ac, ale, color);
892 
893   /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
894   UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
895   UI_draw_roundbox_3fv_alpha(
896       true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f);
897 }
898 
899 /* name for group entries */
acf_group_name(bAnimListElem * ale,char * name)900 static void acf_group_name(bAnimListElem *ale, char *name)
901 {
902   bActionGroup *agrp = (bActionGroup *)ale->data;
903 
904   /* just copy the name... */
905   if (agrp && name) {
906     BLI_strncpy(name, agrp->name, ANIM_CHAN_NAME_SIZE);
907   }
908 }
909 
910 /* name property for group entries */
acf_group_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)911 static bool acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
912 {
913   RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
914   *prop = RNA_struct_name_property(ptr->type);
915 
916   return (*prop != NULL);
917 }
918 
919 /* check if some setting exists for this channel */
acf_group_setting_valid(bAnimContext * ac,bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)920 static bool acf_group_setting_valid(bAnimContext *ac,
921                                     bAnimListElem *UNUSED(ale),
922                                     eAnimChannel_Settings setting)
923 {
924   /* for now, all settings are supported, though some are only conditionally */
925   switch (setting) {
926     /* unsupported */
927     case ACHANNEL_SETTING_SOLO:   /* Only available in NLA Editor for tracks */
928     case ACHANNEL_SETTING_PINNED: /* Only for NLA actions */
929       return false;
930 
931     /* conditionally supported */
932     case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
933       return (ac->spacetype == SPACE_GRAPH);
934 
935     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
936       return (ac->spacetype == SPACE_GRAPH);
937 
938     default: /* always supported */
939       return true;
940   }
941 }
942 
943 /* get the appropriate flag(s) for the setting when it is valid  */
acf_group_setting_flag(bAnimContext * ac,eAnimChannel_Settings setting,bool * neg)944 static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
945 {
946   /* clear extra return data first */
947   *neg = false;
948 
949   switch (setting) {
950     case ACHANNEL_SETTING_SELECT: /* selected */
951       return AGRP_SELECTED;
952 
953     case ACHANNEL_SETTING_EXPAND: /* expanded */
954     {
955       /* NOTE: Graph Editor uses a different flag to everywhere else for this,
956        * allowing different collapsing of groups there, since sharing the flag
957        * proved to be a hazard for workflows...
958        */
959       return (ac->spacetype == SPACE_GRAPH) ? AGRP_EXPANDED_G : /* Graph Editor case */
960                  AGRP_EXPANDED;                                 /* DopeSheet and elsewhere */
961     }
962 
963     case ACHANNEL_SETTING_MUTE: /* muted */
964       return AGRP_MUTED;
965 
966     case ACHANNEL_SETTING_MOD_OFF: /* muted */
967       *neg = 1;
968       return AGRP_MODIFIERS_OFF;
969 
970     case ACHANNEL_SETTING_PROTECT: /* protected */
971       return AGRP_PROTECTED;
972 
973     case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
974       *neg = 1;
975       return AGRP_NOTVISIBLE;
976 
977     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
978       return ADT_CURVES_ALWAYS_VISIBLE;
979 
980     default:
981       /* this shouldn't happen */
982       return 0;
983   }
984 }
985 
986 /* get pointer to the setting */
acf_group_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)987 static void *acf_group_setting_ptr(bAnimListElem *ale,
988                                    eAnimChannel_Settings UNUSED(setting),
989                                    short *type)
990 {
991   bActionGroup *agrp = (bActionGroup *)ale->data;
992 
993   /* all flags are just in agrp->flag for now... */
994   return GET_ACF_FLAG_PTR(agrp->flag, type);
995 }
996 
997 /* group type define */
998 static bAnimChannelType ACF_GROUP = {
999     "Group",               /* type name */
1000     ACHANNEL_ROLE_CHANNEL, /* role */
1001 
1002     acf_group_color,          /* backdrop color */
1003     acf_group_backdrop,       /* backdrop */
1004     acf_generic_indention_0,  /* indent level */
1005     acf_generic_group_offset, /* offset */
1006 
1007     acf_group_name,      /* name */
1008     acf_group_name_prop, /* name prop */
1009     NULL,                /* icon */
1010 
1011     acf_group_setting_valid, /* has setting */
1012     acf_group_setting_flag,  /* flag for setting */
1013     acf_group_setting_ptr,   /* pointer for setting */
1014 };
1015 
1016 /* F-Curve ------------------------------------------- */
1017 
1018 /* name for fcurve entries */
acf_fcurve_name(bAnimListElem * ale,char * name)1019 static void acf_fcurve_name(bAnimListElem *ale, char *name)
1020 {
1021   getname_anim_fcurve(name, ale->id, ale->data);
1022 }
1023 
1024 /* "name" property for fcurve entries */
acf_fcurve_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)1025 static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
1026 {
1027   FCurve *fcu = (FCurve *)ale->data;
1028 
1029   /* Ctrl-Click Usability Convenience Hack:
1030    * For disabled F-Curves, allow access to the RNA Path
1031    * as our "name" so that user can perform quick fixes
1032    */
1033   if (fcu->flag & FCURVE_DISABLED) {
1034     RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
1035     *prop = RNA_struct_find_property(ptr, "data_path");
1036   }
1037   else {
1038     /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */
1039     *prop = NULL;
1040   }
1041 
1042   return (*prop != NULL);
1043 }
1044 
1045 /* check if some setting exists for this channel */
acf_fcurve_setting_valid(bAnimContext * ac,bAnimListElem * ale,eAnimChannel_Settings setting)1046 static bool acf_fcurve_setting_valid(bAnimContext *ac,
1047                                      bAnimListElem *ale,
1048                                      eAnimChannel_Settings setting)
1049 {
1050   FCurve *fcu = (FCurve *)ale->data;
1051 
1052   switch (setting) {
1053     /* unsupported */
1054     case ACHANNEL_SETTING_SOLO:   /* Solo Flag is only for NLA */
1055     case ACHANNEL_SETTING_EXPAND: /* F-Curves are not containers */
1056     case ACHANNEL_SETTING_PINNED: /* This is only for NLA Actions */
1057       return false;
1058 
1059     /* conditionally available */
1060     case ACHANNEL_SETTING_PROTECT: /* Protection is only valid when there's keyframes */
1061       if (fcu->bezt) {
1062         return true;
1063       }
1064       else {
1065         return false; /* NOTE: in this special case, we need to draw ICON_ZOOMOUT */
1066       }
1067 
1068     case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
1069       return (ac->spacetype == SPACE_GRAPH);
1070 
1071     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
1072       return false;
1073 
1074     /* always available */
1075     default:
1076       return true;
1077   }
1078 }
1079 
1080 /* get the appropriate flag(s) for the setting when it is valid  */
acf_fcurve_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1081 static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac),
1082                                    eAnimChannel_Settings setting,
1083                                    bool *neg)
1084 {
1085   /* clear extra return data first */
1086   *neg = false;
1087 
1088   switch (setting) {
1089     case ACHANNEL_SETTING_SELECT: /* selected */
1090       return FCURVE_SELECTED;
1091 
1092     case ACHANNEL_SETTING_MUTE: /* muted */
1093       return FCURVE_MUTED;
1094 
1095     case ACHANNEL_SETTING_PROTECT: /* protected */
1096       return FCURVE_PROTECTED;
1097 
1098     case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
1099       return FCURVE_VISIBLE;
1100 
1101     case ACHANNEL_SETTING_MOD_OFF:
1102       *neg = 1;
1103       return FCURVE_MOD_OFF;
1104 
1105     default: /* unsupported */
1106       return 0;
1107   }
1108 }
1109 
1110 /* get pointer to the setting */
acf_fcurve_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)1111 static void *acf_fcurve_setting_ptr(bAnimListElem *ale,
1112                                     eAnimChannel_Settings UNUSED(setting),
1113                                     short *type)
1114 {
1115   FCurve *fcu = (FCurve *)ale->data;
1116 
1117   /* all flags are just in agrp->flag for now... */
1118   return GET_ACF_FLAG_PTR(fcu->flag, type);
1119 }
1120 
1121 /* fcurve type define */
1122 static bAnimChannelType ACF_FCURVE = {
1123     "F-Curve",             /* type name */
1124     ACHANNEL_ROLE_CHANNEL, /* role */
1125 
1126     acf_generic_channel_color,    /* backdrop color */
1127     acf_generic_channel_backdrop, /* backdrop */
1128     acf_generic_indention_flexible,
1129     /* indent level */        /* XXX rename this to f-curves only? */
1130     acf_generic_group_offset, /* offset */
1131 
1132     acf_fcurve_name,      /* name */
1133     acf_fcurve_name_prop, /* name prop */
1134     NULL,                 /* icon */
1135 
1136     acf_fcurve_setting_valid, /* has setting */
1137     acf_fcurve_setting_flag,  /* flag for setting */
1138     acf_fcurve_setting_ptr,   /* pointer for setting */
1139 };
1140 
1141 /* NLA Control FCurves Expander ----------------------- */
1142 
1143 /* get backdrop color for nla controls widget */
acf_nla_controls_color(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),float r_color[3])1144 static void acf_nla_controls_color(bAnimContext *UNUSED(ac),
1145                                    bAnimListElem *UNUSED(ale),
1146                                    float r_color[3])
1147 {
1148   /* TODO: give this its own theme setting? */
1149   UI_GetThemeColorShade3fv(TH_GROUP, 55, r_color);
1150 }
1151 
1152 /* backdrop for nla controls expander widget */
acf_nla_controls_backdrop(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc)1153 static void acf_nla_controls_backdrop(bAnimContext *ac,
1154                                       bAnimListElem *ale,
1155                                       float yminc,
1156                                       float ymaxc)
1157 {
1158   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
1159   View2D *v2d = &ac->region->v2d;
1160   short expanded = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_EXPAND) != 0;
1161   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
1162   float color[3];
1163 
1164   /* set backdrop drawing color */
1165   acf->get_backdrop_color(ac, ale, color);
1166 
1167   /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */
1168   UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT));
1169   UI_draw_roundbox_3fv_alpha(
1170       true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f);
1171 }
1172 
1173 /* name for nla controls expander entries */
acf_nla_controls_name(bAnimListElem * UNUSED (ale),char * name)1174 static void acf_nla_controls_name(bAnimListElem *UNUSED(ale), char *name)
1175 {
1176   BLI_strncpy(name, IFACE_("NLA Strip Controls"), ANIM_CHAN_NAME_SIZE);
1177 }
1178 
1179 /* check if some setting exists for this channel */
acf_nla_controls_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)1180 static bool acf_nla_controls_setting_valid(bAnimContext *UNUSED(ac),
1181                                            bAnimListElem *UNUSED(ale),
1182                                            eAnimChannel_Settings setting)
1183 {
1184   /* for now, all settings are supported, though some are only conditionally */
1185   switch (setting) {
1186     /* supported */
1187     case ACHANNEL_SETTING_EXPAND:
1188       return true;
1189 
1190       /* TODO: selected? */
1191 
1192     default: /* unsupported */
1193       return false;
1194   }
1195 }
1196 
1197 /* get the appropriate flag(s) for the setting when it is valid  */
acf_nla_controls_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1198 static int acf_nla_controls_setting_flag(bAnimContext *UNUSED(ac),
1199                                          eAnimChannel_Settings setting,
1200                                          bool *neg)
1201 {
1202   /* clear extra return data first */
1203   *neg = false;
1204 
1205   switch (setting) {
1206     case ACHANNEL_SETTING_EXPAND: /* expanded */
1207       *neg = true;
1208       return ADT_NLA_SKEYS_COLLAPSED;
1209 
1210     default:
1211       /* this shouldn't happen */
1212       return 0;
1213   }
1214 }
1215 
1216 /* get pointer to the setting */
acf_nla_controls_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)1217 static void *acf_nla_controls_setting_ptr(bAnimListElem *ale,
1218                                           eAnimChannel_Settings UNUSED(setting),
1219                                           short *type)
1220 {
1221   AnimData *adt = (AnimData *)ale->data;
1222 
1223   /* all flags are just in adt->flag for now... */
1224   return GET_ACF_FLAG_PTR(adt->flag, type);
1225 }
1226 
acf_nla_controls_icon(bAnimListElem * UNUSED (ale))1227 static int acf_nla_controls_icon(bAnimListElem *UNUSED(ale))
1228 {
1229   return ICON_NLA;
1230 }
1231 
1232 /* NLA Control FCurves Expander type define */
1233 static bAnimChannelType ACF_NLACONTROLS = {
1234     "NLA Controls Expander", /* type name */
1235     ACHANNEL_ROLE_EXPANDER,  /* role */
1236 
1237     acf_nla_controls_color,    /* backdrop color */
1238     acf_nla_controls_backdrop, /* backdrop */
1239     acf_generic_indention_0,   /* indent level */
1240     acf_generic_group_offset,  /* offset */
1241 
1242     acf_nla_controls_name, /* name */
1243     NULL,                  /* name prop */
1244     acf_nla_controls_icon, /* icon */
1245 
1246     acf_nla_controls_setting_valid, /* has setting */
1247     acf_nla_controls_setting_flag,  /* flag for setting */
1248     acf_nla_controls_setting_ptr,   /* pointer for setting */
1249 };
1250 
1251 /* NLA Control F-Curve -------------------------------- */
1252 
1253 /* name for nla control fcurve entries */
acf_nla_curve_name(bAnimListElem * ale,char * name)1254 static void acf_nla_curve_name(bAnimListElem *ale, char *name)
1255 {
1256   NlaStrip *strip = ale->owner;
1257   FCurve *fcu = ale->data;
1258   PropertyRNA *prop;
1259 
1260   /* try to get RNA property that this shortened path (relative to the strip) refers to */
1261   prop = RNA_struct_type_find_property(&RNA_NlaStrip, fcu->rna_path);
1262   if (prop) {
1263     /* "name" of this strip displays the UI identifier + the name of the NlaStrip */
1264     BLI_snprintf(name, 256, "%s (%s)", RNA_property_ui_name(prop), strip->name);
1265   }
1266   else {
1267     /* unknown property... */
1268     BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index);
1269   }
1270 }
1271 
1272 /* NLA Control F-Curve type define */
1273 static bAnimChannelType ACF_NLACURVE = {
1274     "NLA Control F-Curve", /* type name */
1275     ACHANNEL_ROLE_CHANNEL, /* role */
1276 
1277     acf_generic_channel_color,    /* backdrop color */
1278     acf_generic_channel_backdrop, /* backdrop */
1279     acf_generic_indention_1,      /* indent level */
1280     acf_generic_group_offset,     /* offset */
1281 
1282     acf_nla_curve_name,   /* name */
1283     acf_fcurve_name_prop, /* name prop */
1284     NULL,                 /* icon */
1285 
1286     acf_fcurve_setting_valid, /* has setting */
1287     acf_fcurve_setting_flag,  /* flag for setting */
1288     acf_fcurve_setting_ptr,   /* pointer for setting */
1289 };
1290 
1291 /* Object Action Expander  ------------------------------------------- */
1292 
1293 /* TODO: just get this from RNA? */
acf_fillactd_icon(bAnimListElem * UNUSED (ale))1294 static int acf_fillactd_icon(bAnimListElem *UNUSED(ale))
1295 {
1296   return ICON_ACTION;
1297 }
1298 
1299 /* check if some setting exists for this channel */
acf_fillactd_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)1300 static bool acf_fillactd_setting_valid(bAnimContext *UNUSED(ac),
1301                                        bAnimListElem *UNUSED(ale),
1302                                        eAnimChannel_Settings setting)
1303 {
1304   switch (setting) {
1305     /* only select and expand supported */
1306     case ACHANNEL_SETTING_SELECT:
1307     case ACHANNEL_SETTING_EXPAND:
1308       return true;
1309 
1310     default:
1311       return false;
1312   }
1313 }
1314 
1315 /* get the appropriate flag(s) for the setting when it is valid  */
acf_fillactd_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1316 static int acf_fillactd_setting_flag(bAnimContext *UNUSED(ac),
1317                                      eAnimChannel_Settings setting,
1318                                      bool *neg)
1319 {
1320   /* clear extra return data first */
1321   *neg = false;
1322 
1323   switch (setting) {
1324     case ACHANNEL_SETTING_SELECT: /* selected */
1325       return ADT_UI_SELECTED;
1326 
1327     case ACHANNEL_SETTING_EXPAND: /* expanded */
1328       *neg = true;
1329       return ACT_COLLAPSED;
1330 
1331     default: /* unsupported */
1332       return 0;
1333   }
1334 }
1335 
1336 /* get pointer to the setting */
acf_fillactd_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1337 static void *acf_fillactd_setting_ptr(bAnimListElem *ale,
1338                                       eAnimChannel_Settings setting,
1339                                       short *type)
1340 {
1341   bAction *act = (bAction *)ale->data;
1342   AnimData *adt = ale->adt;
1343 
1344   /* clear extra return data first */
1345   *type = 0;
1346 
1347   switch (setting) {
1348     case ACHANNEL_SETTING_SELECT: /* selected */
1349       if (adt) {
1350         return GET_ACF_FLAG_PTR(adt->flag, type);
1351       }
1352       return NULL;
1353 
1354     case ACHANNEL_SETTING_EXPAND: /* expanded */
1355       return GET_ACF_FLAG_PTR(act->flag, type);
1356 
1357     default: /* unsupported */
1358       return NULL;
1359   }
1360 }
1361 
1362 /* object action expander type define */
1363 static bAnimChannelType ACF_FILLACTD = {
1364     "Ob-Action Filler",     /* type name */
1365     ACHANNEL_ROLE_EXPANDER, /* role */
1366 
1367     acf_generic_dataexpand_color,    /* backdrop color */
1368     acf_generic_dataexpand_backdrop, /* backdrop */
1369     acf_generic_indention_1,         /* indent level */
1370     acf_generic_basic_offset,        /* offset */
1371 
1372     acf_generic_idblock_name,     /* name */
1373     acf_generic_idfill_name_prop, /* name prop */
1374     acf_fillactd_icon,            /* icon */
1375 
1376     acf_fillactd_setting_valid, /* has setting */
1377     acf_fillactd_setting_flag,  /* flag for setting */
1378     acf_fillactd_setting_ptr,   /* pointer for setting */
1379 };
1380 
1381 /* Drivers Expander  ------------------------------------------- */
1382 
1383 /* TODO: just get this from RNA? */
acf_filldrivers_icon(bAnimListElem * UNUSED (ale))1384 static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
1385 {
1386   return ICON_DRIVER;
1387 }
1388 
acf_filldrivers_name(bAnimListElem * UNUSED (ale),char * name)1389 static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
1390 {
1391   BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE);
1392 }
1393 
1394 /* check if some setting exists for this channel */
1395 /* TODO: this could be made more generic */
acf_filldrivers_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)1396 static bool acf_filldrivers_setting_valid(bAnimContext *UNUSED(ac),
1397                                           bAnimListElem *UNUSED(ale),
1398                                           eAnimChannel_Settings setting)
1399 {
1400   switch (setting) {
1401     /* only expand supported */
1402     case ACHANNEL_SETTING_EXPAND:
1403       return true;
1404 
1405     default:
1406       return false;
1407   }
1408 }
1409 
1410 /* get the appropriate flag(s) for the setting when it is valid  */
acf_filldrivers_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1411 static int acf_filldrivers_setting_flag(bAnimContext *UNUSED(ac),
1412                                         eAnimChannel_Settings setting,
1413                                         bool *neg)
1414 {
1415   /* clear extra return data first */
1416   *neg = false;
1417 
1418   switch (setting) {
1419     case ACHANNEL_SETTING_EXPAND: /* expanded */
1420       *neg = true;
1421       return ADT_DRIVERS_COLLAPSED;
1422 
1423     default: /* unsupported */
1424       return 0;
1425   }
1426 }
1427 
1428 /* get pointer to the setting */
acf_filldrivers_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1429 static void *acf_filldrivers_setting_ptr(bAnimListElem *ale,
1430                                          eAnimChannel_Settings setting,
1431                                          short *type)
1432 {
1433   AnimData *adt = (AnimData *)ale->data;
1434 
1435   /* clear extra return data first */
1436   *type = 0;
1437 
1438   switch (setting) {
1439     case ACHANNEL_SETTING_EXPAND: /* expanded */
1440       return GET_ACF_FLAG_PTR(adt->flag, type);
1441 
1442     default: /* unsupported */
1443       return NULL;
1444   }
1445 }
1446 
1447 /* drivers expander type define */
1448 static bAnimChannelType ACF_FILLDRIVERS = {
1449     "Drivers Filler",       /* type name */
1450     ACHANNEL_ROLE_EXPANDER, /* role */
1451 
1452     acf_generic_dataexpand_color,    /* backdrop color */
1453     acf_generic_dataexpand_backdrop, /* backdrop */
1454     acf_generic_indention_1,         /* indent level */
1455     acf_generic_basic_offset,        /* offset */
1456 
1457     acf_filldrivers_name, /* name */
1458     NULL,                 /* name prop */
1459     acf_filldrivers_icon, /* icon */
1460 
1461     acf_filldrivers_setting_valid, /* has setting */
1462     acf_filldrivers_setting_flag,  /* flag for setting */
1463     acf_filldrivers_setting_ptr,   /* pointer for setting */
1464 };
1465 
1466 /* Material Expander  ------------------------------------------- */
1467 
1468 /* TODO: just get this from RNA? */
acf_dsmat_icon(bAnimListElem * UNUSED (ale))1469 static int acf_dsmat_icon(bAnimListElem *UNUSED(ale))
1470 {
1471   return ICON_MATERIAL_DATA;
1472 }
1473 
1474 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsmat_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1475 static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac),
1476                                   eAnimChannel_Settings setting,
1477                                   bool *neg)
1478 {
1479   /* clear extra return data first */
1480   *neg = false;
1481 
1482   switch (setting) {
1483     case ACHANNEL_SETTING_EXPAND: /* expanded */
1484       return MA_DS_EXPAND;
1485 
1486     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1487       return ADT_NLA_EVAL_OFF;
1488 
1489     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1490       *neg = true;
1491       return ADT_CURVES_NOT_VISIBLE;
1492 
1493     case ACHANNEL_SETTING_SELECT: /* selected */
1494       return ADT_UI_SELECTED;
1495 
1496     default: /* unsupported */
1497       return 0;
1498   }
1499 }
1500 
1501 /* get pointer to the setting */
acf_dsmat_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1502 static void *acf_dsmat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1503 {
1504   Material *ma = (Material *)ale->data;
1505 
1506   /* clear extra return data first */
1507   *type = 0;
1508 
1509   switch (setting) {
1510     case ACHANNEL_SETTING_EXPAND: /* expanded */
1511       return GET_ACF_FLAG_PTR(ma->flag, type);
1512 
1513     case ACHANNEL_SETTING_SELECT:  /* selected */
1514     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1515     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1516       if (ma->adt) {
1517         return GET_ACF_FLAG_PTR(ma->adt->flag, type);
1518       }
1519       return NULL;
1520 
1521     default: /* unsupported */
1522       return NULL;
1523   }
1524 }
1525 
1526 /* material expander type define */
1527 static bAnimChannelType ACF_DSMAT = {
1528     "Material Data Expander", /* type name */
1529     ACHANNEL_ROLE_EXPANDER,   /* role */
1530 
1531     acf_generic_dataexpand_color,    /* backdrop color */
1532     acf_generic_dataexpand_backdrop, /* backdrop */
1533     acf_generic_indention_1,         /* indent level */
1534     acf_generic_basic_offset,        /* offset */
1535 
1536     acf_generic_idblock_name,      /* name */
1537     acf_generic_idblock_name_prop, /* name prop */
1538     acf_dsmat_icon,                /* icon */
1539 
1540     acf_generic_dataexpand_setting_valid, /* has setting */
1541     acf_dsmat_setting_flag,               /* flag for setting */
1542     acf_dsmat_setting_ptr,                /* pointer for setting */
1543 };
1544 
1545 /* Light Expander  ------------------------------------------- */
1546 
1547 /* TODO: just get this from RNA? */
acf_dslight_icon(bAnimListElem * UNUSED (ale))1548 static int acf_dslight_icon(bAnimListElem *UNUSED(ale))
1549 {
1550   return ICON_LIGHT_DATA;
1551 }
1552 
1553 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dslight_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1554 static int acf_dslight_setting_flag(bAnimContext *UNUSED(ac),
1555                                     eAnimChannel_Settings setting,
1556                                     bool *neg)
1557 {
1558   /* clear extra return data first */
1559   *neg = false;
1560 
1561   switch (setting) {
1562     case ACHANNEL_SETTING_EXPAND: /* expanded */
1563       return LA_DS_EXPAND;
1564 
1565     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1566       return ADT_NLA_EVAL_OFF;
1567 
1568     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1569       *neg = true;
1570       return ADT_CURVES_NOT_VISIBLE;
1571 
1572     case ACHANNEL_SETTING_SELECT: /* selected */
1573       return ADT_UI_SELECTED;
1574 
1575     default: /* unsupported */
1576       return 0;
1577   }
1578 }
1579 
1580 /* get pointer to the setting */
acf_dslight_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1581 static void *acf_dslight_setting_ptr(bAnimListElem *ale,
1582                                      eAnimChannel_Settings setting,
1583                                      short *type)
1584 {
1585   Light *la = (Light *)ale->data;
1586 
1587   /* clear extra return data first */
1588   *type = 0;
1589 
1590   switch (setting) {
1591     case ACHANNEL_SETTING_EXPAND: /* expanded */
1592       return GET_ACF_FLAG_PTR(la->flag, type);
1593 
1594     case ACHANNEL_SETTING_SELECT:  /* selected */
1595     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1596     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1597       if (la->adt) {
1598         return GET_ACF_FLAG_PTR(la->adt->flag, type);
1599       }
1600       return NULL;
1601 
1602     default: /* unsupported */
1603       return NULL;
1604   }
1605 }
1606 
1607 /* light expander type define */
1608 static bAnimChannelType ACF_DSLIGHT = {
1609     "Light Expander",       /* type name */
1610     ACHANNEL_ROLE_EXPANDER, /* role */
1611 
1612     acf_generic_dataexpand_color,    /* backdrop color */
1613     acf_generic_dataexpand_backdrop, /* backdrop */
1614     acf_generic_indention_1,         /* indent level */
1615     acf_generic_basic_offset,        /* offset */
1616 
1617     acf_generic_idblock_name,      /* name */
1618     acf_generic_idblock_name_prop, /* name prop */
1619     acf_dslight_icon,              /* icon */
1620 
1621     acf_generic_dataexpand_setting_valid, /* has setting */
1622     acf_dslight_setting_flag,             /* flag for setting */
1623     acf_dslight_setting_ptr,              /* pointer for setting */
1624 };
1625 
1626 /* Texture Expander  ------------------------------------------- */
1627 
1628 /* TODO: just get this from RNA? */
acf_dstex_icon(bAnimListElem * UNUSED (ale))1629 static int acf_dstex_icon(bAnimListElem *UNUSED(ale))
1630 {
1631   return ICON_TEXTURE_DATA;
1632 }
1633 
1634 /* offset for texture expanders */
1635 /* FIXME: soon to be obsolete? */
acf_dstex_offset(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale))1636 static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
1637 {
1638   return 14; /* XXX: simply include this in indention instead? */
1639 }
1640 
1641 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dstex_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1642 static int acf_dstex_setting_flag(bAnimContext *UNUSED(ac),
1643                                   eAnimChannel_Settings setting,
1644                                   bool *neg)
1645 {
1646   /* clear extra return data first */
1647   *neg = false;
1648 
1649   switch (setting) {
1650     case ACHANNEL_SETTING_EXPAND: /* expanded */
1651       return TEX_DS_EXPAND;
1652 
1653     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1654       return ADT_NLA_EVAL_OFF;
1655 
1656     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1657       *neg = true;
1658       return ADT_CURVES_NOT_VISIBLE;
1659 
1660     case ACHANNEL_SETTING_SELECT: /* selected */
1661       return ADT_UI_SELECTED;
1662 
1663     default: /* unsupported */
1664       return 0;
1665   }
1666 }
1667 
1668 /* get pointer to the setting */
acf_dstex_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1669 static void *acf_dstex_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1670 {
1671   Tex *tex = (Tex *)ale->data;
1672 
1673   /* clear extra return data first */
1674   *type = 0;
1675 
1676   switch (setting) {
1677     case ACHANNEL_SETTING_EXPAND: /* expanded */
1678       return GET_ACF_FLAG_PTR(tex->flag, type);
1679 
1680     case ACHANNEL_SETTING_SELECT:  /* selected */
1681     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1682     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1683       if (tex->adt) {
1684         return GET_ACF_FLAG_PTR(tex->adt->flag, type);
1685       }
1686       return NULL;
1687 
1688     default: /* unsupported */
1689       return NULL;
1690   }
1691 }
1692 
1693 /* texture expander type define */
1694 static bAnimChannelType ACF_DSTEX = {
1695     "Texture Data Expander", /* type name */
1696     ACHANNEL_ROLE_EXPANDER,  /* role */
1697 
1698     acf_generic_dataexpand_color,    /* backdrop color */
1699     acf_generic_dataexpand_backdrop, /* backdrop */
1700     acf_generic_indention_1,         /* indent level */
1701     acf_dstex_offset,                /* offset */
1702 
1703     acf_generic_idblock_name,     /* name */
1704     acf_generic_idfill_name_prop, /* name prop */
1705     acf_dstex_icon,               /* icon */
1706 
1707     acf_generic_dataexpand_setting_valid, /* has setting */
1708     acf_dstex_setting_flag,               /* flag for setting */
1709     acf_dstex_setting_ptr,                /* pointer for setting */
1710 };
1711 
1712 /* Camera Expander  ------------------------------------------- */
1713 
1714 /* TODO: just get this from RNA? */
acf_dscachefile_icon(bAnimListElem * ale)1715 static int acf_dscachefile_icon(bAnimListElem *ale)
1716 {
1717   UNUSED_VARS(ale);
1718   return ICON_FILE;
1719 }
1720 
1721 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dscachefile_setting_flag(bAnimContext * ac,eAnimChannel_Settings setting,bool * neg)1722 static int acf_dscachefile_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
1723 {
1724   /* clear extra return data first */
1725   *neg = false;
1726 
1727   switch (setting) {
1728     case ACHANNEL_SETTING_EXPAND: /* expanded */
1729       return CACHEFILE_DS_EXPAND;
1730 
1731     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1732       return ADT_NLA_EVAL_OFF;
1733 
1734     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1735       *neg = true;
1736       return ADT_CURVES_NOT_VISIBLE;
1737 
1738     case ACHANNEL_SETTING_SELECT: /* selected */
1739       return ADT_UI_SELECTED;
1740 
1741     default: /* unsupported */
1742       return 0;
1743   }
1744 
1745   UNUSED_VARS(ac);
1746 }
1747 
1748 /* get pointer to the setting */
acf_dscachefile_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1749 static void *acf_dscachefile_setting_ptr(bAnimListElem *ale,
1750                                          eAnimChannel_Settings setting,
1751                                          short *type)
1752 {
1753   CacheFile *cache_file = (CacheFile *)ale->data;
1754 
1755   /* clear extra return data first */
1756   *type = 0;
1757 
1758   switch (setting) {
1759     case ACHANNEL_SETTING_EXPAND: /* expanded */
1760       return GET_ACF_FLAG_PTR(cache_file->flag, type);
1761 
1762     case ACHANNEL_SETTING_SELECT:  /* selected */
1763     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1764     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1765       if (cache_file->adt) {
1766         return GET_ACF_FLAG_PTR(cache_file->adt->flag, type);
1767       }
1768 
1769       return NULL;
1770 
1771     default: /* unsupported */
1772       return NULL;
1773   }
1774 }
1775 
1776 /* CacheFile expander type define. */
1777 static bAnimChannelType ACF_DSCACHEFILE = {
1778     "Cache File Expander",  /* type name */
1779     ACHANNEL_ROLE_EXPANDER, /* role */
1780 
1781     acf_generic_dataexpand_color,    /* backdrop color */
1782     acf_generic_dataexpand_backdrop, /* backdrop */
1783     acf_generic_indention_1,         /* indent level */
1784     acf_generic_basic_offset,        /* offset */
1785 
1786     acf_generic_idblock_name,     /* name */
1787     acf_generic_idfill_name_prop, /* name prop */
1788     acf_dscachefile_icon,         /* icon */
1789 
1790     acf_generic_dataexpand_setting_valid, /* has setting */
1791     acf_dscachefile_setting_flag,         /* flag for setting */
1792     acf_dscachefile_setting_ptr,          /* pointer for setting */
1793 };
1794 
1795 /* Camera Expander  ------------------------------------------- */
1796 
1797 /* TODO: just get this from RNA? */
acf_dscam_icon(bAnimListElem * UNUSED (ale))1798 static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
1799 {
1800   return ICON_CAMERA_DATA;
1801 }
1802 
1803 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dscam_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1804 static int acf_dscam_setting_flag(bAnimContext *UNUSED(ac),
1805                                   eAnimChannel_Settings setting,
1806                                   bool *neg)
1807 {
1808   /* clear extra return data first */
1809   *neg = false;
1810 
1811   switch (setting) {
1812     case ACHANNEL_SETTING_EXPAND: /* expanded */
1813       return CAM_DS_EXPAND;
1814 
1815     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1816       return ADT_NLA_EVAL_OFF;
1817 
1818     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1819       *neg = true;
1820       return ADT_CURVES_NOT_VISIBLE;
1821 
1822     case ACHANNEL_SETTING_SELECT: /* selected */
1823       return ADT_UI_SELECTED;
1824 
1825     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
1826       return ADT_CURVES_ALWAYS_VISIBLE;
1827 
1828     default: /* unsupported */
1829       return 0;
1830   }
1831 }
1832 
1833 /* get pointer to the setting */
acf_dscam_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1834 static void *acf_dscam_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1835 {
1836   Camera *ca = (Camera *)ale->data;
1837 
1838   /* clear extra return data first */
1839   *type = 0;
1840 
1841   switch (setting) {
1842     case ACHANNEL_SETTING_EXPAND: /* expanded */
1843       return GET_ACF_FLAG_PTR(ca->flag, type);
1844 
1845     case ACHANNEL_SETTING_SELECT:  /* selected */
1846     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1847     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1848     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
1849       if (ca->adt) {
1850         return GET_ACF_FLAG_PTR(ca->adt->flag, type);
1851       }
1852       return NULL;
1853 
1854     default: /* unsupported */
1855       return NULL;
1856   }
1857 }
1858 
1859 /* camera expander type define */
1860 static bAnimChannelType ACF_DSCAM = {
1861     "Camera Expander",      /* type name */
1862     ACHANNEL_ROLE_EXPANDER, /* role */
1863 
1864     acf_generic_dataexpand_color,    /* backdrop color */
1865     acf_generic_dataexpand_backdrop, /* backdrop */
1866     acf_generic_indention_1,         /* indent level */
1867     acf_generic_basic_offset,        /* offset */
1868 
1869     acf_generic_idblock_name,     /* name */
1870     acf_generic_idfill_name_prop, /* name prop */
1871     acf_dscam_icon,               /* icon */
1872 
1873     acf_generic_dataexpand_setting_valid, /* has setting */
1874     acf_dscam_setting_flag,               /* flag for setting */
1875     acf_dscam_setting_ptr,                /* pointer for setting */
1876 };
1877 
1878 /* Curve Expander  ------------------------------------------- */
1879 
1880 /* TODO: just get this from RNA? */
acf_dscur_icon(bAnimListElem * ale)1881 static int acf_dscur_icon(bAnimListElem *ale)
1882 {
1883   Curve *cu = (Curve *)ale->data;
1884   short obtype = BKE_curve_type_get(cu);
1885 
1886   switch (obtype) {
1887     case OB_FONT:
1888       return ICON_FONT_DATA;
1889     case OB_SURF:
1890       return ICON_SURFACE_DATA;
1891     default:
1892       return ICON_CURVE_DATA;
1893   }
1894 }
1895 
1896 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dscur_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1897 static int acf_dscur_setting_flag(bAnimContext *UNUSED(ac),
1898                                   eAnimChannel_Settings setting,
1899                                   bool *neg)
1900 {
1901   /* clear extra return data first */
1902   *neg = false;
1903 
1904   switch (setting) {
1905     case ACHANNEL_SETTING_EXPAND: /* expanded */
1906       return CU_DS_EXPAND;
1907 
1908     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
1909       return ADT_NLA_EVAL_OFF;
1910 
1911     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
1912       *neg = true;
1913       return ADT_CURVES_NOT_VISIBLE;
1914 
1915     case ACHANNEL_SETTING_SELECT: /* selected */
1916       return ADT_UI_SELECTED;
1917 
1918     default: /* unsupported */
1919       return 0;
1920   }
1921 }
1922 
1923 /* get pointer to the setting */
acf_dscur_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)1924 static void *acf_dscur_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
1925 {
1926   Curve *cu = (Curve *)ale->data;
1927 
1928   /* clear extra return data first */
1929   *type = 0;
1930 
1931   switch (setting) {
1932     case ACHANNEL_SETTING_EXPAND: /* expanded */
1933       return GET_ACF_FLAG_PTR(cu->flag, type);
1934 
1935     case ACHANNEL_SETTING_SELECT:  /* selected */
1936     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
1937     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
1938       if (cu->adt) {
1939         return GET_ACF_FLAG_PTR(cu->adt->flag, type);
1940       }
1941       return NULL;
1942 
1943     default: /* unsupported */
1944       return NULL;
1945   }
1946 }
1947 
1948 /* curve expander type define */
1949 static bAnimChannelType ACF_DSCUR = {
1950     "Curve Expander",       /* type name */
1951     ACHANNEL_ROLE_EXPANDER, /* role */
1952 
1953     acf_generic_dataexpand_color,    /* backdrop color */
1954     acf_generic_dataexpand_backdrop, /* backdrop */
1955     acf_generic_indention_1,         /* indent level */
1956     acf_generic_basic_offset,        /* offset */
1957 
1958     acf_generic_idblock_name,      /* name */
1959     acf_generic_idblock_name_prop, /* name prop */
1960     acf_dscur_icon,                /* icon */
1961 
1962     acf_generic_dataexpand_setting_valid, /* has setting */
1963     acf_dscur_setting_flag,               /* flag for setting */
1964     acf_dscur_setting_ptr,                /* pointer for setting */
1965 };
1966 
1967 /* Shape Key Expander  ------------------------------------------- */
1968 
1969 /* TODO: just get this from RNA? */
acf_dsskey_icon(bAnimListElem * UNUSED (ale))1970 static int acf_dsskey_icon(bAnimListElem *UNUSED(ale))
1971 {
1972   return ICON_SHAPEKEY_DATA;
1973 }
1974 
1975 /* check if some setting exists for this channel */
acf_dsskey_setting_valid(bAnimContext * ac,bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)1976 static bool acf_dsskey_setting_valid(bAnimContext *ac,
1977                                      bAnimListElem *UNUSED(ale),
1978                                      eAnimChannel_Settings setting)
1979 {
1980   switch (setting) {
1981     case ACHANNEL_SETTING_SELECT:
1982     case ACHANNEL_SETTING_EXPAND:
1983       return true;
1984 
1985     /* mute is only supported for NLA */
1986     case ACHANNEL_SETTING_MUTE:
1987       return ((ac) && (ac->spacetype == SPACE_NLA));
1988 
1989     default:
1990       return false;
1991   }
1992 }
1993 
1994 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsskey_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)1995 static int acf_dsskey_setting_flag(bAnimContext *UNUSED(ac),
1996                                    eAnimChannel_Settings setting,
1997                                    bool *neg)
1998 {
1999   /* clear extra return data first */
2000   *neg = false;
2001 
2002   switch (setting) {
2003     case ACHANNEL_SETTING_EXPAND: /* expanded */
2004       return KEY_DS_EXPAND;
2005 
2006     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2007       return ADT_NLA_EVAL_OFF;
2008 
2009     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2010       *neg = true;
2011       return ADT_CURVES_NOT_VISIBLE;
2012 
2013     case ACHANNEL_SETTING_SELECT: /* selected */
2014       return ADT_UI_SELECTED;
2015 
2016     default: /* unsupported */
2017       return 0;
2018   }
2019 }
2020 
2021 /* get pointer to the setting */
acf_dsskey_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2022 static void *acf_dsskey_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2023 {
2024   Key *key = (Key *)ale->data;
2025 
2026   /* clear extra return data first */
2027   *type = 0;
2028 
2029   switch (setting) {
2030     case ACHANNEL_SETTING_EXPAND: /* expanded */
2031       return GET_ACF_FLAG_PTR(key->flag, type);
2032 
2033     case ACHANNEL_SETTING_SELECT:  /* selected */
2034     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2035     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2036       if (key->adt) {
2037         return GET_ACF_FLAG_PTR(key->adt->flag, type);
2038       }
2039       return NULL;
2040 
2041     default: /* unsupported */
2042       return NULL;
2043   }
2044 }
2045 
2046 /* shapekey expander type define */
2047 static bAnimChannelType ACF_DSSKEY = {
2048     "Shape Key Expander",   /* type name */
2049     ACHANNEL_ROLE_EXPANDER, /* role */
2050 
2051     acf_generic_dataexpand_color,    /* backdrop color */
2052     acf_generic_dataexpand_backdrop, /* backdrop */
2053     acf_generic_indention_1,         /* indent level */
2054     acf_generic_basic_offset,        /* offset */
2055 
2056     acf_generic_idblock_name,      /* name */
2057     acf_generic_idblock_name_prop, /* name prop */
2058     acf_dsskey_icon,               /* icon */
2059 
2060     acf_dsskey_setting_valid, /* has setting */
2061     acf_dsskey_setting_flag,  /* flag for setting */
2062     acf_dsskey_setting_ptr,   /* pointer for setting */
2063 };
2064 
2065 /* World Expander  ------------------------------------------- */
2066 
2067 /* TODO: just get this from RNA? */
acf_dswor_icon(bAnimListElem * UNUSED (ale))2068 static int acf_dswor_icon(bAnimListElem *UNUSED(ale))
2069 {
2070   return ICON_WORLD_DATA;
2071 }
2072 
2073 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dswor_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2074 static int acf_dswor_setting_flag(bAnimContext *UNUSED(ac),
2075                                   eAnimChannel_Settings setting,
2076                                   bool *neg)
2077 {
2078   /* clear extra return data first */
2079   *neg = false;
2080 
2081   switch (setting) {
2082     case ACHANNEL_SETTING_EXPAND: /* expanded */
2083       return WO_DS_EXPAND;
2084 
2085     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2086       return ADT_NLA_EVAL_OFF;
2087 
2088     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2089       *neg = true;
2090       return ADT_CURVES_NOT_VISIBLE;
2091 
2092     case ACHANNEL_SETTING_SELECT: /* selected */
2093       return ADT_UI_SELECTED;
2094 
2095     default: /* unsupported */
2096       return 0;
2097   }
2098 }
2099 
2100 /* get pointer to the setting */
acf_dswor_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2101 static void *acf_dswor_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2102 {
2103   World *wo = (World *)ale->data;
2104 
2105   /* clear extra return data first */
2106   *type = 0;
2107 
2108   switch (setting) {
2109     case ACHANNEL_SETTING_EXPAND: /* expanded */
2110       return GET_ACF_FLAG_PTR(wo->flag, type);
2111 
2112     case ACHANNEL_SETTING_SELECT:  /* selected */
2113     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2114     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2115       if (wo->adt) {
2116         return GET_ACF_FLAG_PTR(wo->adt->flag, type);
2117       }
2118       return NULL;
2119 
2120     default: /* unsupported */
2121       return NULL;
2122   }
2123 }
2124 
2125 /* world expander type define */
2126 static bAnimChannelType ACF_DSWOR = {
2127     "World Expander",       /* type name */
2128     ACHANNEL_ROLE_EXPANDER, /* role */
2129 
2130     acf_generic_dataexpand_color,    /* backdrop color */
2131     acf_generic_dataexpand_backdrop, /* backdrop */
2132     acf_generic_indention_1,         /* indent level */
2133     acf_generic_basic_offset,        /* offset */
2134 
2135     acf_generic_idblock_name,     /* name */
2136     acf_generic_idfill_name_prop, /* name prop */
2137     acf_dswor_icon,               /* icon */
2138 
2139     acf_generic_dataexpand_setting_valid, /* has setting */
2140     acf_dswor_setting_flag,               /* flag for setting */
2141     acf_dswor_setting_ptr,                /* pointer for setting */
2142 };
2143 
2144 /* Particle Expander  ------------------------------------------- */
2145 
2146 /* TODO: just get this from RNA? */
acf_dspart_icon(bAnimListElem * UNUSED (ale))2147 static int acf_dspart_icon(bAnimListElem *UNUSED(ale))
2148 {
2149   return ICON_PARTICLE_DATA;
2150 }
2151 
2152 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dspart_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2153 static int acf_dspart_setting_flag(bAnimContext *UNUSED(ac),
2154                                    eAnimChannel_Settings setting,
2155                                    bool *neg)
2156 {
2157   /* clear extra return data first */
2158   *neg = false;
2159 
2160   switch (setting) {
2161     case ACHANNEL_SETTING_EXPAND: /* expanded */
2162       return PART_DS_EXPAND;
2163 
2164     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2165       return ADT_NLA_EVAL_OFF;
2166 
2167     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2168       *neg = true;
2169       return ADT_CURVES_NOT_VISIBLE;
2170 
2171     case ACHANNEL_SETTING_SELECT: /* selected */
2172       return ADT_UI_SELECTED;
2173 
2174     default: /* unsupported */
2175       return 0;
2176   }
2177 }
2178 
2179 /* get pointer to the setting */
acf_dspart_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2180 static void *acf_dspart_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2181 {
2182   ParticleSettings *part = (ParticleSettings *)ale->data;
2183 
2184   /* clear extra return data first */
2185   *type = 0;
2186 
2187   switch (setting) {
2188     case ACHANNEL_SETTING_EXPAND: /* expanded */
2189       return GET_ACF_FLAG_PTR(part->flag, type);
2190 
2191     case ACHANNEL_SETTING_SELECT:  /* selected */
2192     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2193     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2194       if (part->adt) {
2195         return GET_ACF_FLAG_PTR(part->adt->flag, type);
2196       }
2197       return NULL;
2198 
2199     default: /* unsupported */
2200       return NULL;
2201   }
2202 }
2203 
2204 /* particle expander type define */
2205 static bAnimChannelType ACF_DSPART = {
2206     "Particle Data Expander", /* type name */
2207     ACHANNEL_ROLE_EXPANDER,   /* role */
2208 
2209     acf_generic_dataexpand_color,    /* backdrop color */
2210     acf_generic_dataexpand_backdrop, /* backdrop */
2211     acf_generic_indention_1,         /* indent level */
2212     acf_generic_basic_offset,        /* offset */
2213 
2214     acf_generic_idblock_name,      /* name */
2215     acf_generic_idblock_name_prop, /* name prop */
2216     acf_dspart_icon,               /* icon */
2217 
2218     acf_generic_dataexpand_setting_valid, /* has setting */
2219     acf_dspart_setting_flag,              /* flag for setting */
2220     acf_dspart_setting_ptr,               /* pointer for setting */
2221 };
2222 
2223 /* MetaBall Expander  ------------------------------------------- */
2224 
2225 /* TODO: just get this from RNA? */
acf_dsmball_icon(bAnimListElem * UNUSED (ale))2226 static int acf_dsmball_icon(bAnimListElem *UNUSED(ale))
2227 {
2228   return ICON_META_DATA;
2229 }
2230 
2231 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsmball_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2232 static int acf_dsmball_setting_flag(bAnimContext *UNUSED(ac),
2233                                     eAnimChannel_Settings setting,
2234                                     bool *neg)
2235 {
2236   /* clear extra return data first */
2237   *neg = false;
2238 
2239   switch (setting) {
2240     case ACHANNEL_SETTING_EXPAND: /* expanded */
2241       return MB_DS_EXPAND;
2242 
2243     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2244       return ADT_NLA_EVAL_OFF;
2245 
2246     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2247       *neg = true;
2248       return ADT_CURVES_NOT_VISIBLE;
2249 
2250     case ACHANNEL_SETTING_SELECT: /* selected */
2251       return ADT_UI_SELECTED;
2252 
2253     default: /* unsupported */
2254       return 0;
2255   }
2256 }
2257 
2258 /* get pointer to the setting */
acf_dsmball_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2259 static void *acf_dsmball_setting_ptr(bAnimListElem *ale,
2260                                      eAnimChannel_Settings setting,
2261                                      short *type)
2262 {
2263   MetaBall *mb = (MetaBall *)ale->data;
2264 
2265   /* clear extra return data first */
2266   *type = 0;
2267 
2268   switch (setting) {
2269     case ACHANNEL_SETTING_EXPAND: /* expanded */
2270       return GET_ACF_FLAG_PTR(mb->flag2, type);
2271 
2272     case ACHANNEL_SETTING_SELECT:  /* selected */
2273     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2274     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2275       if (mb->adt) {
2276         return GET_ACF_FLAG_PTR(mb->adt->flag, type);
2277       }
2278       return NULL;
2279 
2280     default: /* unsupported */
2281       return NULL;
2282   }
2283 }
2284 
2285 /* metaball expander type define */
2286 static bAnimChannelType ACF_DSMBALL = {
2287     "Metaball Expander",    /* type name */
2288     ACHANNEL_ROLE_EXPANDER, /* role */
2289 
2290     acf_generic_dataexpand_color,    /* backdrop color */
2291     acf_generic_dataexpand_backdrop, /* backdrop */
2292     acf_generic_indention_1,         /* indent level */
2293     acf_generic_basic_offset,        /* offset */
2294 
2295     acf_generic_idblock_name,      /* name */
2296     acf_generic_idblock_name_prop, /* name prop */
2297     acf_dsmball_icon,              /* icon */
2298 
2299     acf_generic_dataexpand_setting_valid, /* has setting */
2300     acf_dsmball_setting_flag,             /* flag for setting */
2301     acf_dsmball_setting_ptr,              /* pointer for setting */
2302 };
2303 
2304 /* Armature Expander  ------------------------------------------- */
2305 
2306 /* TODO: just get this from RNA? */
acf_dsarm_icon(bAnimListElem * UNUSED (ale))2307 static int acf_dsarm_icon(bAnimListElem *UNUSED(ale))
2308 {
2309   return ICON_ARMATURE_DATA;
2310 }
2311 
2312 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsarm_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2313 static int acf_dsarm_setting_flag(bAnimContext *UNUSED(ac),
2314                                   eAnimChannel_Settings setting,
2315                                   bool *neg)
2316 {
2317   /* clear extra return data first */
2318   *neg = false;
2319 
2320   switch (setting) {
2321     case ACHANNEL_SETTING_EXPAND: /* expanded */
2322       return ARM_DS_EXPAND;
2323 
2324     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2325       return ADT_NLA_EVAL_OFF;
2326 
2327     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2328       *neg = true;
2329       return ADT_CURVES_NOT_VISIBLE;
2330 
2331     case ACHANNEL_SETTING_SELECT: /* selected */
2332       return ADT_UI_SELECTED;
2333 
2334     default: /* unsupported */
2335       return 0;
2336   }
2337 }
2338 
2339 /* get pointer to the setting */
acf_dsarm_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2340 static void *acf_dsarm_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2341 {
2342   bArmature *arm = (bArmature *)ale->data;
2343 
2344   /* clear extra return data first */
2345   *type = 0;
2346 
2347   switch (setting) {
2348     case ACHANNEL_SETTING_EXPAND: /* expanded */
2349       return GET_ACF_FLAG_PTR(arm->flag, type);
2350 
2351     case ACHANNEL_SETTING_SELECT:  /* selected */
2352     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2353     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2354       if (arm->adt) {
2355         return GET_ACF_FLAG_PTR(arm->adt->flag, type);
2356       }
2357       return NULL;
2358 
2359     default: /* unsupported */
2360       return NULL;
2361   }
2362 }
2363 
2364 /* metaball expander type define */
2365 static bAnimChannelType ACF_DSARM = {
2366     "Armature Expander",    /* type name */
2367     ACHANNEL_ROLE_EXPANDER, /* role */
2368 
2369     acf_generic_dataexpand_color,    /* backdrop color */
2370     acf_generic_dataexpand_backdrop, /* backdrop */
2371     acf_generic_indention_1,         /* indent level */
2372     acf_generic_basic_offset,        /* offset */
2373 
2374     acf_generic_idblock_name,      /* name */
2375     acf_generic_idblock_name_prop, /* name prop */
2376     acf_dsarm_icon,                /* icon */
2377 
2378     acf_generic_dataexpand_setting_valid, /* has setting */
2379     acf_dsarm_setting_flag,               /* flag for setting */
2380     acf_dsarm_setting_ptr,                /* pointer for setting */
2381 };
2382 
2383 /* NodeTree Expander  ------------------------------------------- */
2384 
2385 /* TODO: just get this from RNA? */
acf_dsntree_icon(bAnimListElem * UNUSED (ale))2386 static int acf_dsntree_icon(bAnimListElem *UNUSED(ale))
2387 {
2388   return ICON_NODETREE;
2389 }
2390 
2391 /* offset for nodetree expanders */
acf_dsntree_offset(bAnimContext * ac,bAnimListElem * ale)2392 static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale)
2393 {
2394   bNodeTree *ntree = (bNodeTree *)ale->data;
2395   short offset = acf_generic_basic_offset(ac, ale);
2396 
2397   offset += acf_nodetree_rootType_offset(ntree);
2398 
2399   return offset;
2400 }
2401 
2402 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsntree_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2403 static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac),
2404                                     eAnimChannel_Settings setting,
2405                                     bool *neg)
2406 {
2407   /* clear extra return data first */
2408   *neg = false;
2409 
2410   switch (setting) {
2411     case ACHANNEL_SETTING_EXPAND: /* expanded */
2412       return NTREE_DS_EXPAND;
2413 
2414     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2415       return ADT_NLA_EVAL_OFF;
2416 
2417     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2418       *neg = true;
2419       return ADT_CURVES_NOT_VISIBLE;
2420 
2421     case ACHANNEL_SETTING_SELECT: /* selected */
2422       return ADT_UI_SELECTED;
2423 
2424     default: /* unsupported */
2425       return 0;
2426   }
2427 }
2428 
2429 /* get pointer to the setting */
acf_dsntree_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2430 static void *acf_dsntree_setting_ptr(bAnimListElem *ale,
2431                                      eAnimChannel_Settings setting,
2432                                      short *type)
2433 {
2434   bNodeTree *ntree = (bNodeTree *)ale->data;
2435 
2436   /* clear extra return data first */
2437   *type = 0;
2438 
2439   switch (setting) {
2440     case ACHANNEL_SETTING_EXPAND: /* expanded */
2441       return GET_ACF_FLAG_PTR(ntree->flag, type);
2442 
2443     case ACHANNEL_SETTING_SELECT:  /* selected */
2444     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2445     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2446       if (ntree->adt) {
2447         return GET_ACF_FLAG_PTR(ntree->adt->flag, type);
2448       }
2449       return NULL;
2450 
2451     default: /* unsupported */
2452       return NULL;
2453   }
2454 }
2455 
2456 /* node tree expander type define */
2457 static bAnimChannelType ACF_DSNTREE = {
2458     "Node Tree Expander",   /* type name */
2459     ACHANNEL_ROLE_EXPANDER, /* role */
2460 
2461     acf_generic_dataexpand_color,    /* backdrop color */
2462     acf_generic_dataexpand_backdrop, /* backdrop */
2463     acf_generic_indention_1,         /* indent level */
2464     acf_dsntree_offset,              /* offset */
2465 
2466     acf_generic_idblock_name,      /* name */
2467     acf_generic_idblock_name_prop, /* name prop */
2468     acf_dsntree_icon,              /* icon */
2469 
2470     acf_generic_dataexpand_setting_valid, /* has setting */
2471     acf_dsntree_setting_flag,             /* flag for setting */
2472     acf_dsntree_setting_ptr,              /* pointer for setting */
2473 };
2474 
2475 /* LineStyle Expander  ------------------------------------------- */
2476 
2477 /* TODO: just get this from RNA? */
acf_dslinestyle_icon(bAnimListElem * UNUSED (ale))2478 static int acf_dslinestyle_icon(bAnimListElem *UNUSED(ale))
2479 {
2480   return ICON_LINE_DATA;
2481 }
2482 
2483 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dslinestyle_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2484 static int acf_dslinestyle_setting_flag(bAnimContext *UNUSED(ac),
2485                                         eAnimChannel_Settings setting,
2486                                         bool *neg)
2487 {
2488   /* clear extra return data first */
2489   *neg = false;
2490 
2491   switch (setting) {
2492     case ACHANNEL_SETTING_EXPAND: /* expanded */
2493       return LS_DS_EXPAND;
2494 
2495     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2496       return ADT_NLA_EVAL_OFF;
2497 
2498     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2499       *neg = true;
2500       return ADT_CURVES_NOT_VISIBLE;
2501 
2502     case ACHANNEL_SETTING_SELECT: /* selected */
2503       return ADT_UI_SELECTED;
2504 
2505     default: /* unsupported */
2506       return 0;
2507   }
2508 }
2509 
2510 /* get pointer to the setting */
acf_dslinestyle_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2511 static void *acf_dslinestyle_setting_ptr(bAnimListElem *ale,
2512                                          eAnimChannel_Settings setting,
2513                                          short *type)
2514 {
2515   FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ale->data;
2516 
2517   /* clear extra return data first */
2518   *type = 0;
2519 
2520   switch (setting) {
2521     case ACHANNEL_SETTING_EXPAND: /* expanded */
2522       return GET_ACF_FLAG_PTR(linestyle->flag, type);
2523 
2524     case ACHANNEL_SETTING_SELECT:  /* selected */
2525     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2526     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2527       if (linestyle->adt) {
2528         return GET_ACF_FLAG_PTR(linestyle->adt->flag, type);
2529       }
2530       return NULL;
2531 
2532     default: /* unsupported */
2533       return NULL;
2534   }
2535 }
2536 
2537 /* node tree expander type define */
2538 static bAnimChannelType ACF_DSLINESTYLE = {
2539     "Line Style Expander",  /* type name */
2540     ACHANNEL_ROLE_EXPANDER, /* role */
2541 
2542     acf_generic_dataexpand_color,    /* backdrop color */
2543     acf_generic_dataexpand_backdrop, /* backdrop */
2544     acf_generic_indention_1,         /* indent level */
2545     acf_generic_basic_offset,        /* offset */
2546 
2547     acf_generic_idblock_name,      /* name */
2548     acf_generic_idblock_name_prop, /* name prop */
2549     acf_dslinestyle_icon,          /* icon */
2550 
2551     acf_generic_dataexpand_setting_valid, /* has setting */
2552     acf_dslinestyle_setting_flag,         /* flag for setting */
2553     acf_dslinestyle_setting_ptr,          /* pointer for setting */
2554 };
2555 
2556 /* Mesh Expander  ------------------------------------------- */
2557 
2558 /* TODO: just get this from RNA? */
acf_dsmesh_icon(bAnimListElem * UNUSED (ale))2559 static int acf_dsmesh_icon(bAnimListElem *UNUSED(ale))
2560 {
2561   return ICON_MESH_DATA;
2562 }
2563 
2564 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsmesh_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2565 static int acf_dsmesh_setting_flag(bAnimContext *UNUSED(ac),
2566                                    eAnimChannel_Settings setting,
2567                                    bool *neg)
2568 {
2569   /* clear extra return data first */
2570   *neg = false;
2571 
2572   switch (setting) {
2573     case ACHANNEL_SETTING_EXPAND: /* expanded */
2574       return ME_DS_EXPAND;
2575 
2576     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2577       return ADT_NLA_EVAL_OFF;
2578 
2579     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2580       *neg = true;
2581       return ADT_CURVES_NOT_VISIBLE;
2582 
2583     case ACHANNEL_SETTING_SELECT: /* selected */
2584       return ADT_UI_SELECTED;
2585 
2586     default: /* unsupported */
2587       return 0;
2588   }
2589 }
2590 
2591 /* get pointer to the setting */
acf_dsmesh_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2592 static void *acf_dsmesh_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2593 {
2594   Mesh *me = (Mesh *)ale->data;
2595 
2596   /* clear extra return data first */
2597   *type = 0;
2598 
2599   switch (setting) {
2600     case ACHANNEL_SETTING_EXPAND: /* expanded */
2601       return GET_ACF_FLAG_PTR(me->flag, type);
2602 
2603     case ACHANNEL_SETTING_SELECT:  /* selected */
2604     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2605     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2606       if (me->adt) {
2607         return GET_ACF_FLAG_PTR(me->adt->flag, type);
2608       }
2609       return NULL;
2610 
2611     default: /* unsupported */
2612       return NULL;
2613   }
2614 }
2615 
2616 /* node tree expander type define */
2617 static bAnimChannelType ACF_DSMESH = {
2618     "Mesh Expander",        /* type name */
2619     ACHANNEL_ROLE_EXPANDER, /* role */
2620 
2621     acf_generic_dataexpand_color,    /* backdrop color */
2622     acf_generic_dataexpand_backdrop, /* backdrop */
2623     acf_generic_indention_1,
2624     /* indent level */        /* XXX this only works for compositing */
2625     acf_generic_basic_offset, /* offset */
2626 
2627     acf_generic_idblock_name,      /* name */
2628     acf_generic_idblock_name_prop, /* name prop */
2629     acf_dsmesh_icon,               /* icon */
2630 
2631     acf_generic_dataexpand_setting_valid, /* has setting */
2632     acf_dsmesh_setting_flag,              /* flag for setting */
2633     acf_dsmesh_setting_ptr,               /* pointer for setting */
2634 };
2635 
2636 /* Lattice Expander  ------------------------------------------- */
2637 
2638 /* TODO: just get this from RNA? */
acf_dslat_icon(bAnimListElem * UNUSED (ale))2639 static int acf_dslat_icon(bAnimListElem *UNUSED(ale))
2640 {
2641   return ICON_LATTICE_DATA;
2642 }
2643 
2644 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dslat_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2645 static int acf_dslat_setting_flag(bAnimContext *UNUSED(ac),
2646                                   eAnimChannel_Settings setting,
2647                                   bool *neg)
2648 {
2649   /* clear extra return data first */
2650   *neg = false;
2651 
2652   switch (setting) {
2653     case ACHANNEL_SETTING_EXPAND: /* expanded */
2654       return LT_DS_EXPAND;
2655 
2656     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2657       return ADT_NLA_EVAL_OFF;
2658 
2659     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2660       *neg = true;
2661       return ADT_CURVES_NOT_VISIBLE;
2662 
2663     case ACHANNEL_SETTING_SELECT: /* selected */
2664       return ADT_UI_SELECTED;
2665 
2666     default: /* unsupported */
2667       return 0;
2668   }
2669 }
2670 
2671 /* get pointer to the setting */
acf_dslat_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2672 static void *acf_dslat_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2673 {
2674   Lattice *lt = (Lattice *)ale->data;
2675 
2676   /* clear extra return data first */
2677   *type = 0;
2678 
2679   switch (setting) {
2680     case ACHANNEL_SETTING_EXPAND: /* expanded */
2681       return GET_ACF_FLAG_PTR(lt->flag, type);
2682 
2683     case ACHANNEL_SETTING_SELECT:  /* selected */
2684     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2685     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2686       if (lt->adt) {
2687         return GET_ACF_FLAG_PTR(lt->adt->flag, type);
2688       }
2689       return NULL;
2690 
2691     default: /* unsupported */
2692       return NULL;
2693   }
2694 }
2695 
2696 /* node tree expander type define */
2697 static bAnimChannelType ACF_DSLAT = {
2698     "Lattice Expander",     /* type name */
2699     ACHANNEL_ROLE_EXPANDER, /* role */
2700 
2701     acf_generic_dataexpand_color,    /* backdrop color */
2702     acf_generic_dataexpand_backdrop, /* backdrop */
2703     acf_generic_indention_1,
2704     /* indent level */        /* XXX this only works for compositing */
2705     acf_generic_basic_offset, /* offset */
2706 
2707     acf_generic_idblock_name,      /* name */
2708     acf_generic_idblock_name_prop, /* name prop */
2709     acf_dslat_icon,                /* icon */
2710 
2711     acf_generic_dataexpand_setting_valid, /* has setting */
2712     acf_dslat_setting_flag,               /* flag for setting */
2713     acf_dslat_setting_ptr,                /* pointer for setting */
2714 };
2715 
2716 /* Speaker Expander  ------------------------------------------- */
2717 
2718 /* TODO: just get this from RNA? */
acf_dsspk_icon(bAnimListElem * UNUSED (ale))2719 static int acf_dsspk_icon(bAnimListElem *UNUSED(ale))
2720 {
2721   return ICON_SPEAKER;
2722 }
2723 
2724 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsspk_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2725 static int acf_dsspk_setting_flag(bAnimContext *UNUSED(ac),
2726                                   eAnimChannel_Settings setting,
2727                                   bool *neg)
2728 {
2729   /* clear extra return data first */
2730   *neg = false;
2731 
2732   switch (setting) {
2733     case ACHANNEL_SETTING_EXPAND: /* expanded */
2734       return SPK_DS_EXPAND;
2735 
2736     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2737       return ADT_NLA_EVAL_OFF;
2738 
2739     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2740       *neg = true;
2741       return ADT_CURVES_NOT_VISIBLE;
2742 
2743     case ACHANNEL_SETTING_SELECT: /* selected */
2744       return ADT_UI_SELECTED;
2745 
2746     default: /* unsupported */
2747       return 0;
2748   }
2749 }
2750 
2751 /* get pointer to the setting */
acf_dsspk_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2752 static void *acf_dsspk_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2753 {
2754   Speaker *spk = (Speaker *)ale->data;
2755 
2756   /* clear extra return data first */
2757   *type = 0;
2758 
2759   switch (setting) {
2760     case ACHANNEL_SETTING_EXPAND: /* expanded */
2761       return GET_ACF_FLAG_PTR(spk->flag, type);
2762 
2763     case ACHANNEL_SETTING_SELECT:  /* selected */
2764     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2765     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2766       if (spk->adt) {
2767         return GET_ACF_FLAG_PTR(spk->adt->flag, type);
2768       }
2769       return NULL;
2770 
2771     default: /* unsupported */
2772       return NULL;
2773   }
2774 }
2775 
2776 /* speaker expander type define */
2777 static bAnimChannelType ACF_DSSPK = {
2778     "Speaker Expander",     /* type name */
2779     ACHANNEL_ROLE_EXPANDER, /* role */
2780 
2781     acf_generic_dataexpand_color,    /* backdrop color */
2782     acf_generic_dataexpand_backdrop, /* backdrop */
2783     acf_generic_indention_1,         /* indent level */
2784     acf_generic_basic_offset,        /* offset */
2785 
2786     acf_generic_idblock_name,      /* name */
2787     acf_generic_idblock_name_prop, /* name prop */
2788     acf_dsspk_icon,                /* icon */
2789 
2790     acf_generic_dataexpand_setting_valid, /* has setting */
2791     acf_dsspk_setting_flag,               /* flag for setting */
2792     acf_dsspk_setting_ptr,                /* pointer for setting */
2793 };
2794 
2795 /* Hair Expander  ------------------------------------------- */
2796 
2797 /* TODO: just get this from RNA? */
acf_dshair_icon(bAnimListElem * UNUSED (ale))2798 static int acf_dshair_icon(bAnimListElem *UNUSED(ale))
2799 {
2800   return ICON_HAIR_DATA;
2801 }
2802 
2803 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dshair_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2804 static int acf_dshair_setting_flag(bAnimContext *UNUSED(ac),
2805                                    eAnimChannel_Settings setting,
2806                                    bool *neg)
2807 {
2808   /* clear extra return data first */
2809   *neg = false;
2810 
2811   switch (setting) {
2812     case ACHANNEL_SETTING_EXPAND: /* expanded */
2813       return VO_DS_EXPAND;
2814 
2815     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2816       return ADT_NLA_EVAL_OFF;
2817 
2818     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2819       *neg = true;
2820       return ADT_CURVES_NOT_VISIBLE;
2821 
2822     case ACHANNEL_SETTING_SELECT: /* selected */
2823       return ADT_UI_SELECTED;
2824 
2825     default: /* unsupported */
2826       return 0;
2827   }
2828 }
2829 
2830 /* get pointer to the setting */
acf_dshair_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2831 static void *acf_dshair_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
2832 {
2833   Hair *hair = (Hair *)ale->data;
2834 
2835   /* clear extra return data first */
2836   *type = 0;
2837 
2838   switch (setting) {
2839     case ACHANNEL_SETTING_EXPAND: /* expanded */
2840       return GET_ACF_FLAG_PTR(hair->flag, type);
2841 
2842     case ACHANNEL_SETTING_SELECT:  /* selected */
2843     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2844     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2845       if (hair->adt) {
2846         return GET_ACF_FLAG_PTR(hair->adt->flag, type);
2847       }
2848       return NULL;
2849 
2850     default: /* unsupported */
2851       return NULL;
2852   }
2853 }
2854 
2855 /* hair expander type define */
2856 static bAnimChannelType ACF_DSHAIR = {
2857     "Hair Expander",        /* type name */
2858     ACHANNEL_ROLE_EXPANDER, /* role */
2859 
2860     acf_generic_dataexpand_color,    /* backdrop color */
2861     acf_generic_dataexpand_backdrop, /* backdrop */
2862     acf_generic_indention_1,         /* indent level */
2863     acf_generic_basic_offset,        /* offset */
2864 
2865     acf_generic_idblock_name,      /* name */
2866     acf_generic_idblock_name_prop, /* name prop */
2867     acf_dshair_icon,               /* icon */
2868 
2869     acf_generic_dataexpand_setting_valid, /* has setting */
2870     acf_dshair_setting_flag,              /* flag for setting */
2871     acf_dshair_setting_ptr                /* pointer for setting */
2872 };
2873 
2874 /* PointCloud Expander  ------------------------------------------- */
2875 
2876 /* TODO: just get this from RNA? */
acf_dspointcloud_icon(bAnimListElem * UNUSED (ale))2877 static int acf_dspointcloud_icon(bAnimListElem *UNUSED(ale))
2878 {
2879   return ICON_POINTCLOUD_DATA;
2880 }
2881 
2882 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dspointcloud_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2883 static int acf_dspointcloud_setting_flag(bAnimContext *UNUSED(ac),
2884                                          eAnimChannel_Settings setting,
2885                                          bool *neg)
2886 {
2887   /* clear extra return data first */
2888   *neg = false;
2889 
2890   switch (setting) {
2891     case ACHANNEL_SETTING_EXPAND: /* expanded */
2892       return VO_DS_EXPAND;
2893 
2894     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2895       return ADT_NLA_EVAL_OFF;
2896 
2897     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2898       *neg = true;
2899       return ADT_CURVES_NOT_VISIBLE;
2900 
2901     case ACHANNEL_SETTING_SELECT: /* selected */
2902       return ADT_UI_SELECTED;
2903 
2904     default: /* unsupported */
2905       return 0;
2906   }
2907 }
2908 
2909 /* get pointer to the setting */
acf_dspointcloud_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2910 static void *acf_dspointcloud_setting_ptr(bAnimListElem *ale,
2911                                           eAnimChannel_Settings setting,
2912                                           short *type)
2913 {
2914   PointCloud *pointcloud = (PointCloud *)ale->data;
2915 
2916   /* clear extra return data first */
2917   *type = 0;
2918 
2919   switch (setting) {
2920     case ACHANNEL_SETTING_EXPAND: /* expanded */
2921       return GET_ACF_FLAG_PTR(pointcloud->flag, type);
2922 
2923     case ACHANNEL_SETTING_SELECT:  /* selected */
2924     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
2925     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
2926       if (pointcloud->adt) {
2927         return GET_ACF_FLAG_PTR(pointcloud->adt->flag, type);
2928       }
2929       return NULL;
2930 
2931     default: /* unsupported */
2932       return NULL;
2933   }
2934 }
2935 
2936 /* pointcloud expander type define */
2937 static bAnimChannelType ACF_DSPOINTCLOUD = {
2938     "PointCloud Expander",  /* type name */
2939     ACHANNEL_ROLE_EXPANDER, /* role */
2940 
2941     acf_generic_dataexpand_color,    /* backdrop color */
2942     acf_generic_dataexpand_backdrop, /* backdrop */
2943     acf_generic_indention_1,         /* indent level */
2944     acf_generic_basic_offset,        /* offset */
2945 
2946     acf_generic_idblock_name,      /* name */
2947     acf_generic_idblock_name_prop, /* name prop */
2948     acf_dspointcloud_icon,         /* icon */
2949 
2950     acf_generic_dataexpand_setting_valid, /* has setting */
2951     acf_dspointcloud_setting_flag,        /* flag for setting */
2952     acf_dspointcloud_setting_ptr          /* pointer for setting */
2953 };
2954 
2955 /* Volume Expander  ------------------------------------------- */
2956 
2957 /* TODO: just get this from RNA? */
acf_dsvolume_icon(bAnimListElem * UNUSED (ale))2958 static int acf_dsvolume_icon(bAnimListElem *UNUSED(ale))
2959 {
2960   return ICON_VOLUME_DATA;
2961 }
2962 
2963 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsvolume_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)2964 static int acf_dsvolume_setting_flag(bAnimContext *UNUSED(ac),
2965                                      eAnimChannel_Settings setting,
2966                                      bool *neg)
2967 {
2968   /* clear extra return data first */
2969   *neg = false;
2970 
2971   switch (setting) {
2972     case ACHANNEL_SETTING_EXPAND: /* expanded */
2973       return VO_DS_EXPAND;
2974 
2975     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
2976       return ADT_NLA_EVAL_OFF;
2977 
2978     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
2979       *neg = true;
2980       return ADT_CURVES_NOT_VISIBLE;
2981 
2982     case ACHANNEL_SETTING_SELECT: /* selected */
2983       return ADT_UI_SELECTED;
2984 
2985     default: /* unsupported */
2986       return 0;
2987   }
2988 }
2989 
2990 /* get pointer to the setting */
acf_dsvolume_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)2991 static void *acf_dsvolume_setting_ptr(bAnimListElem *ale,
2992                                       eAnimChannel_Settings setting,
2993                                       short *type)
2994 {
2995   Volume *volume = (Volume *)ale->data;
2996 
2997   /* clear extra return data first */
2998   *type = 0;
2999 
3000   switch (setting) {
3001     case ACHANNEL_SETTING_EXPAND: /* expanded */
3002       return GET_ACF_FLAG_PTR(volume->flag, type);
3003 
3004     case ACHANNEL_SETTING_SELECT:  /* selected */
3005     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
3006     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
3007       if (volume->adt) {
3008         return GET_ACF_FLAG_PTR(volume->adt->flag, type);
3009       }
3010       return NULL;
3011 
3012     default: /* unsupported */
3013       return NULL;
3014   }
3015 }
3016 
3017 /* volume expander type define */
3018 static bAnimChannelType ACF_DSVOLUME = {
3019     "Volume Expander",      /* type name */
3020     ACHANNEL_ROLE_EXPANDER, /* role */
3021 
3022     acf_generic_dataexpand_color,    /* backdrop color */
3023     acf_generic_dataexpand_backdrop, /* backdrop */
3024     acf_generic_indention_1,         /* indent level */
3025     acf_generic_basic_offset,        /* offset */
3026 
3027     acf_generic_idblock_name,      /* name */
3028     acf_generic_idblock_name_prop, /* name prop */
3029     acf_dsvolume_icon,             /* icon */
3030 
3031     acf_generic_dataexpand_setting_valid, /* has setting */
3032     acf_dsvolume_setting_flag,            /* flag for setting */
3033     acf_dsvolume_setting_ptr              /* pointer for setting */
3034 };
3035 
3036 /* Simulation Expander ----------------------------------------- */
3037 
acf_dssimulation_icon(bAnimListElem * UNUSED (ale))3038 static int acf_dssimulation_icon(bAnimListElem *UNUSED(ale))
3039 {
3040   /* TODO: Use correct icon. */
3041   return ICON_PHYSICS;
3042 }
3043 
acf_dssimulation_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3044 static int acf_dssimulation_setting_flag(bAnimContext *UNUSED(ac),
3045                                          eAnimChannel_Settings setting,
3046                                          bool *neg)
3047 {
3048   /* clear extra return data first */
3049   *neg = false;
3050 
3051   switch (setting) {
3052     case ACHANNEL_SETTING_EXPAND: /* expanded */
3053       return SIM_DS_EXPAND;
3054 
3055     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
3056       return ADT_NLA_EVAL_OFF;
3057 
3058     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
3059       *neg = true;
3060       return ADT_CURVES_NOT_VISIBLE;
3061 
3062     case ACHANNEL_SETTING_SELECT: /* selected */
3063       return ADT_UI_SELECTED;
3064 
3065     default: /* unsupported */
3066       return 0;
3067   }
3068 }
3069 
acf_dssimulation_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)3070 static void *acf_dssimulation_setting_ptr(bAnimListElem *ale,
3071                                           eAnimChannel_Settings setting,
3072                                           short *type)
3073 {
3074   Simulation *simulation = (Simulation *)ale->data;
3075 
3076   /* clear extra return data first */
3077   *type = 0;
3078 
3079   switch (setting) {
3080     case ACHANNEL_SETTING_EXPAND: /* expanded */
3081       return GET_ACF_FLAG_PTR(simulation->flag, type);
3082 
3083     case ACHANNEL_SETTING_SELECT:  /* selected */
3084     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
3085     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
3086       if (simulation->adt) {
3087         return GET_ACF_FLAG_PTR(simulation->adt->flag, type);
3088       }
3089       return NULL;
3090 
3091     default: /* unsupported */
3092       return NULL;
3093   }
3094 }
3095 
3096 static bAnimChannelType ACF_DSSIMULATION = {
3097     "Simulation Expander",  /* type name */
3098     ACHANNEL_ROLE_EXPANDER, /* role */
3099 
3100     acf_generic_dataexpand_color,    /* backdrop color */
3101     acf_generic_dataexpand_backdrop, /* backdrop */
3102     acf_generic_indention_1,         /* indent level */
3103     acf_generic_basic_offset,        /* offset */
3104 
3105     acf_generic_idblock_name,      /* name */
3106     acf_generic_idblock_name_prop, /* name prop */
3107     acf_dssimulation_icon,         /* icon */
3108 
3109     acf_generic_dataexpand_setting_valid, /* has setting */
3110     acf_dssimulation_setting_flag,        /* flag for setting */
3111     acf_dssimulation_setting_ptr          /* pointer for setting */
3112 };
3113 
3114 /* GPencil Expander  ------------------------------------------- */
3115 
3116 /* TODO: just get this from RNA? */
acf_dsgpencil_icon(bAnimListElem * UNUSED (ale))3117 static int acf_dsgpencil_icon(bAnimListElem *UNUSED(ale))
3118 {
3119   return ICON_GREASEPENCIL;
3120 }
3121 
3122 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsgpencil_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3123 static int acf_dsgpencil_setting_flag(bAnimContext *UNUSED(ac),
3124                                       eAnimChannel_Settings setting,
3125                                       bool *neg)
3126 {
3127   /* clear extra return data first */
3128   *neg = false;
3129 
3130   switch (setting) {
3131     case ACHANNEL_SETTING_EXPAND: /* expanded */
3132       return GP_DATA_EXPAND;
3133 
3134     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
3135       return ADT_NLA_EVAL_OFF;
3136 
3137     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
3138       *neg = true;
3139       return ADT_CURVES_NOT_VISIBLE;
3140 
3141     case ACHANNEL_SETTING_SELECT: /* selected */
3142       return ADT_UI_SELECTED;
3143 
3144     default: /* unsupported */
3145       return 0;
3146   }
3147 }
3148 
3149 /* get pointer to the setting */
acf_dsgpencil_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)3150 static void *acf_dsgpencil_setting_ptr(bAnimListElem *ale,
3151                                        eAnimChannel_Settings setting,
3152                                        short *type)
3153 {
3154   bGPdata *gpd = (bGPdata *)ale->data;
3155 
3156   /* clear extra return data first */
3157   *type = 0;
3158 
3159   switch (setting) {
3160     case ACHANNEL_SETTING_EXPAND: /* expanded */
3161       return GET_ACF_FLAG_PTR(gpd->flag, type);
3162 
3163     case ACHANNEL_SETTING_SELECT:  /* selected */
3164     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
3165     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
3166       if (gpd->adt) {
3167         return GET_ACF_FLAG_PTR(gpd->adt->flag, type);
3168       }
3169       return NULL;
3170 
3171     default: /* unsupported */
3172       return NULL;
3173   }
3174 }
3175 
3176 /* grease pencil expander type define */
3177 static bAnimChannelType ACF_DSGPENCIL = {
3178     "GPencil DS Expander",  /* type name */
3179     ACHANNEL_ROLE_EXPANDER, /* role */
3180 
3181     acf_generic_dataexpand_color,    /* backdrop color */
3182     acf_generic_dataexpand_backdrop, /* backdrop */
3183     acf_generic_indention_1,         /* indent level */
3184     acf_generic_basic_offset,        /* offset */
3185 
3186     acf_generic_idblock_name,      /* name */
3187     acf_generic_idblock_name_prop, /* name prop */
3188     acf_dsgpencil_icon,            /* icon */
3189 
3190     acf_generic_dataexpand_setting_valid, /* has setting */
3191     acf_dsgpencil_setting_flag,           /* flag for setting */
3192     acf_dsgpencil_setting_ptr,            /* pointer for setting */
3193 };
3194 
3195 /* World Expander  ------------------------------------------- */
3196 
3197 /* TODO: just get this from RNA? */
acf_dsmclip_icon(bAnimListElem * UNUSED (ale))3198 static int acf_dsmclip_icon(bAnimListElem *UNUSED(ale))
3199 {
3200   return ICON_SEQUENCE;
3201 }
3202 
3203 /* get the appropriate flag(s) for the setting when it is valid  */
acf_dsmclip_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3204 static int acf_dsmclip_setting_flag(bAnimContext *UNUSED(ac),
3205                                     eAnimChannel_Settings setting,
3206                                     bool *neg)
3207 {
3208   /* clear extra return data first */
3209   *neg = false;
3210 
3211   switch (setting) {
3212     case ACHANNEL_SETTING_EXPAND: /* expanded */
3213       return MCLIP_DATA_EXPAND;
3214 
3215     case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
3216       return ADT_NLA_EVAL_OFF;
3217 
3218     case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
3219       *neg = true;
3220       return ADT_CURVES_NOT_VISIBLE;
3221 
3222     case ACHANNEL_SETTING_SELECT: /* selected */
3223       return ADT_UI_SELECTED;
3224 
3225     default: /* unsupported */
3226       return 0;
3227   }
3228 }
3229 
3230 /* get pointer to the setting */
acf_dsmclip_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)3231 static void *acf_dsmclip_setting_ptr(bAnimListElem *ale,
3232                                      eAnimChannel_Settings setting,
3233                                      short *type)
3234 {
3235   MovieClip *clip = (MovieClip *)ale->data;
3236 
3237   /* clear extra return data first */
3238   *type = 0;
3239 
3240   switch (setting) {
3241     case ACHANNEL_SETTING_EXPAND: /* expanded */
3242       return GET_ACF_FLAG_PTR(clip->flag, type);
3243 
3244     case ACHANNEL_SETTING_SELECT:  /* selected */
3245     case ACHANNEL_SETTING_MUTE:    /* muted (for NLA only) */
3246     case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
3247       if (clip->adt != NULL) {
3248         return GET_ACF_FLAG_PTR(clip->adt->flag, type);
3249       }
3250       return NULL;
3251 
3252     default: /* unsupported */
3253       return NULL;
3254   }
3255 }
3256 
3257 /* world expander type define */
3258 static bAnimChannelType ACF_DSMCLIP = {
3259     "Movieclip Expander",   /* type name */
3260     ACHANNEL_ROLE_EXPANDER, /* role */
3261 
3262     acf_generic_dataexpand_color,    /* backdrop color */
3263     acf_generic_dataexpand_backdrop, /* backdrop */
3264     acf_generic_indention_1,         /* indent level */
3265     acf_generic_basic_offset,        /* offset */
3266 
3267     acf_generic_idblock_name,     /* name */
3268     acf_generic_idfill_name_prop, /* name prop */
3269     acf_dsmclip_icon,             /* icon */
3270 
3271     acf_generic_dataexpand_setting_valid, /* has setting */
3272     acf_dsmclip_setting_flag,             /* flag for setting */
3273     acf_dsmclip_setting_ptr,              /* pointer for setting */
3274 };
3275 
3276 /* ShapeKey Entry  ------------------------------------------- */
3277 
3278 /* name for ShapeKey */
acf_shapekey_name(bAnimListElem * ale,char * name)3279 static void acf_shapekey_name(bAnimListElem *ale, char *name)
3280 {
3281   KeyBlock *kb = (KeyBlock *)ale->data;
3282 
3283   /* just copy the name... */
3284   if (kb && name) {
3285     /* if the KeyBlock had a name, use it, otherwise use the index */
3286     if (kb->name[0]) {
3287       BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE);
3288     }
3289     else {
3290       BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index);
3291     }
3292   }
3293 }
3294 
3295 /* name property for ShapeKey entries */
acf_shapekey_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)3296 static bool acf_shapekey_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3297 {
3298   KeyBlock *kb = (KeyBlock *)ale->data;
3299 
3300   /* if the KeyBlock had a name, use it, otherwise use the index */
3301   if (kb && kb->name[0]) {
3302     RNA_pointer_create(ale->id, &RNA_ShapeKey, kb, ptr);
3303     *prop = RNA_struct_name_property(ptr->type);
3304 
3305     return (*prop != NULL);
3306   }
3307 
3308   return false;
3309 }
3310 
3311 /* check if some setting exists for this channel */
acf_shapekey_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)3312 static bool acf_shapekey_setting_valid(bAnimContext *UNUSED(ac),
3313                                        bAnimListElem *UNUSED(ale),
3314                                        eAnimChannel_Settings setting)
3315 {
3316   switch (setting) {
3317     case ACHANNEL_SETTING_SELECT:  /* selected */
3318     case ACHANNEL_SETTING_MUTE:    /* muted */
3319     case ACHANNEL_SETTING_PROTECT: /* protected */
3320       return true;
3321 
3322     /* nothing else is supported */
3323     default:
3324       return false;
3325   }
3326 }
3327 
3328 /* get the appropriate flag(s) for the setting when it is valid  */
acf_shapekey_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3329 static int acf_shapekey_setting_flag(bAnimContext *UNUSED(ac),
3330                                      eAnimChannel_Settings setting,
3331                                      bool *neg)
3332 {
3333   /* clear extra return data first */
3334   *neg = false;
3335 
3336   switch (setting) {
3337     case ACHANNEL_SETTING_MUTE: /* mute */
3338       return KEYBLOCK_MUTE;
3339 
3340     case ACHANNEL_SETTING_SELECT: /* selected */
3341       return KEYBLOCK_SEL;
3342 
3343     case ACHANNEL_SETTING_PROTECT: /* locked */
3344       return KEYBLOCK_LOCKED;
3345 
3346     default: /* unsupported */
3347       return 0;
3348   }
3349 }
3350 
3351 /* get pointer to the setting */
acf_shapekey_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings setting,short * type)3352 static void *acf_shapekey_setting_ptr(bAnimListElem *ale,
3353                                       eAnimChannel_Settings setting,
3354                                       short *type)
3355 {
3356   KeyBlock *kb = (KeyBlock *)ale->data;
3357 
3358   /* clear extra return data first */
3359   *type = 0;
3360 
3361   switch (setting) {
3362     case ACHANNEL_SETTING_SELECT:  /* selected */
3363     case ACHANNEL_SETTING_MUTE:    /* muted */
3364     case ACHANNEL_SETTING_PROTECT: /* protected */
3365       return GET_ACF_FLAG_PTR(kb->flag, type);
3366 
3367     default: /* unsupported */
3368       return NULL;
3369   }
3370 }
3371 
3372 /* shapekey expander type define */
3373 static bAnimChannelType ACF_SHAPEKEY = {
3374     "Shape Key",           /* type name */
3375     ACHANNEL_ROLE_CHANNEL, /* role */
3376 
3377     acf_generic_channel_color,    /* backdrop color */
3378     acf_generic_channel_backdrop, /* backdrop */
3379     acf_generic_indention_0,      /* indent level */
3380     acf_generic_basic_offset,     /* offset */
3381 
3382     acf_shapekey_name,      /* name */
3383     acf_shapekey_name_prop, /* name prop */
3384     NULL,                   /* icon */
3385 
3386     acf_shapekey_setting_valid, /* has setting */
3387     acf_shapekey_setting_flag,  /* flag for setting */
3388     acf_shapekey_setting_ptr,   /* pointer for setting */
3389 };
3390 
3391 /* GPencil Datablock ------------------------------------------- */
3392 
3393 /* get backdrop color for gpencil datablock widget */
acf_gpd_color(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),float r_color[3])3394 static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
3395 {
3396   /* these are ID-blocks, but not exactly standalone... */
3397   UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
3398 }
3399 
3400 /* TODO: just get this from RNA? */
acf_gpd_icon(bAnimListElem * UNUSED (ale))3401 static int acf_gpd_icon(bAnimListElem *UNUSED(ale))
3402 {
3403   return ICON_GREASEPENCIL;
3404 }
3405 
3406 /* check if some setting exists for this channel */
acf_gpd_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)3407 static bool acf_gpd_setting_valid(bAnimContext *UNUSED(ac),
3408                                   bAnimListElem *UNUSED(ale),
3409                                   eAnimChannel_Settings setting)
3410 {
3411   switch (setting) {
3412     /* only select and expand supported */
3413     case ACHANNEL_SETTING_SELECT:
3414     case ACHANNEL_SETTING_EXPAND:
3415       return true;
3416 
3417     default:
3418       return false;
3419   }
3420 }
3421 
3422 /* get the appropriate flag(s) for the setting when it is valid  */
acf_gpd_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3423 static int acf_gpd_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
3424 {
3425   /* clear extra return data first */
3426   *neg = false;
3427 
3428   switch (setting) {
3429     case ACHANNEL_SETTING_SELECT: /* selected */
3430       return AGRP_SELECTED;
3431 
3432     case ACHANNEL_SETTING_EXPAND: /* expanded */
3433       return GP_DATA_EXPAND;
3434 
3435     default:
3436       /* these shouldn't happen */
3437       return 0;
3438   }
3439 }
3440 
3441 /* get pointer to the setting */
acf_gpd_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)3442 static void *acf_gpd_setting_ptr(bAnimListElem *ale,
3443                                  eAnimChannel_Settings UNUSED(setting),
3444                                  short *type)
3445 {
3446   bGPdata *gpd = (bGPdata *)ale->data;
3447 
3448   /* all flags are just in gpd->flag for now... */
3449   return GET_ACF_FLAG_PTR(gpd->flag, type);
3450 }
3451 
3452 /* gpencil datablock type define */
3453 static bAnimChannelType ACF_GPD = {
3454     "GPencil Datablock",    /* type name */
3455     ACHANNEL_ROLE_EXPANDER, /* role */
3456 
3457     acf_gpd_color,            /* backdrop color */
3458     acf_group_backdrop,       /* backdrop */
3459     acf_generic_indention_0,  /* indent level */
3460     acf_generic_group_offset, /* offset */
3461 
3462     acf_generic_idblock_name,     /* name */
3463     acf_generic_idfill_name_prop, /* name prop */
3464     acf_gpd_icon,                 /* icon */
3465 
3466     acf_gpd_setting_valid, /* has setting */
3467     acf_gpd_setting_flag,  /* flag for setting */
3468     acf_gpd_setting_ptr,   /* pointer for setting */
3469 };
3470 
3471 /* GPencil Layer ------------------------------------------- */
3472 
3473 /* name for grease pencil layer entries */
acf_gpl_name(bAnimListElem * ale,char * name)3474 static void acf_gpl_name(bAnimListElem *ale, char *name)
3475 {
3476   bGPDlayer *gpl = (bGPDlayer *)ale->data;
3477 
3478   if (gpl && name) {
3479     BLI_strncpy(name, gpl->info, ANIM_CHAN_NAME_SIZE);
3480   }
3481 }
3482 
3483 /* name property for grease pencil layer entries */
acf_gpl_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)3484 static bool acf_gpl_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3485 {
3486   if (ale->data) {
3487     RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, ptr);
3488     *prop = RNA_struct_name_property(ptr->type);
3489 
3490     return (*prop != NULL);
3491   }
3492 
3493   return false;
3494 }
3495 
3496 /* check if some setting exists for this channel */
acf_gpl_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)3497 static bool acf_gpl_setting_valid(bAnimContext *UNUSED(ac),
3498                                   bAnimListElem *UNUSED(ale),
3499                                   eAnimChannel_Settings setting)
3500 {
3501   switch (setting) {
3502     /* unsupported */
3503     case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */
3504     case ACHANNEL_SETTING_SOLO:   /* nla editor only */
3505     case ACHANNEL_SETTING_MOD_OFF:
3506     case ACHANNEL_SETTING_PINNED: /* nla actions only */
3507       return false;
3508 
3509     /* always available */
3510     default:
3511       return true;
3512   }
3513 }
3514 
3515 /* get the appropriate flag(s) for the setting when it is valid  */
acf_gpl_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3516 static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
3517 {
3518   /* clear extra return data first */
3519   *neg = false;
3520 
3521   switch (setting) {
3522     case ACHANNEL_SETTING_SELECT: /* selected */
3523       return GP_LAYER_SELECT;
3524 
3525     case ACHANNEL_SETTING_MUTE: /* animation muting - similar to frame lock... */
3526       return GP_LAYER_FRAMELOCK;
3527 
3528     case ACHANNEL_SETTING_VISIBLE: /* visibility of the layers (NOT muting) */
3529       *neg = true;
3530       return GP_LAYER_HIDE;
3531 
3532     case ACHANNEL_SETTING_PROTECT: /* protected */
3533       return GP_LAYER_LOCKED;
3534 
3535     default: /* unsupported */
3536       return 0;
3537   }
3538 }
3539 
3540 /* get pointer to the setting */
acf_gpl_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)3541 static void *acf_gpl_setting_ptr(bAnimListElem *ale,
3542                                  eAnimChannel_Settings UNUSED(setting),
3543                                  short *type)
3544 {
3545   bGPDlayer *gpl = (bGPDlayer *)ale->data;
3546 
3547   /* all flags are just in gpl->flag for now... */
3548   return GET_ACF_FLAG_PTR(gpl->flag, type);
3549 }
3550 
3551 /* grease pencil layer type define */
3552 static bAnimChannelType ACF_GPL = {
3553     "GPencil Layer",       /* type name */
3554     ACHANNEL_ROLE_CHANNEL, /* role */
3555 
3556     acf_gpencil_channel_color,      /* backdrop color */
3557     acf_generic_channel_backdrop,   /* backdrop */
3558     acf_generic_indention_flexible, /* indent level */
3559     acf_generic_group_offset,       /* offset */
3560 
3561     acf_gpl_name,      /* name */
3562     acf_gpl_name_prop, /* name prop */
3563     NULL,              /* icon */
3564 
3565     acf_gpl_setting_valid, /* has setting */
3566     acf_gpl_setting_flag,  /* flag for setting */
3567     acf_gpl_setting_ptr,   /* pointer for setting */
3568 };
3569 
3570 /* Mask Datablock ------------------------------------------- */
3571 
3572 /* get backdrop color for mask datablock widget */
acf_mask_color(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),float r_color[3])3573 static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
3574 {
3575   /* these are ID-blocks, but not exactly standalone... */
3576   UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
3577 }
3578 
3579 /* TODO: just get this from RNA? */
acf_mask_icon(bAnimListElem * UNUSED (ale))3580 static int acf_mask_icon(bAnimListElem *UNUSED(ale))
3581 {
3582   return ICON_MOD_MASK;
3583 }
3584 
3585 /* check if some setting exists for this channel */
acf_mask_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)3586 static bool acf_mask_setting_valid(bAnimContext *UNUSED(ac),
3587                                    bAnimListElem *UNUSED(ale),
3588                                    eAnimChannel_Settings setting)
3589 {
3590   switch (setting) {
3591     /* only select and expand supported */
3592     case ACHANNEL_SETTING_SELECT:
3593     case ACHANNEL_SETTING_EXPAND:
3594       return true;
3595 
3596     default:
3597       return false;
3598   }
3599 }
3600 
3601 /* get the appropriate flag(s) for the setting when it is valid  */
acf_mask_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3602 static int acf_mask_setting_flag(bAnimContext *UNUSED(ac),
3603                                  eAnimChannel_Settings setting,
3604                                  bool *neg)
3605 {
3606   /* clear extra return data first */
3607   *neg = false;
3608 
3609   switch (setting) {
3610     case ACHANNEL_SETTING_SELECT: /* selected */
3611       return AGRP_SELECTED;
3612 
3613     case ACHANNEL_SETTING_EXPAND: /* expanded */
3614       return MASK_ANIMF_EXPAND;
3615 
3616     default:
3617       /* this shouldn't happen */
3618       return 0;
3619   }
3620 }
3621 
3622 /* get pointer to the setting */
acf_mask_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)3623 static void *acf_mask_setting_ptr(bAnimListElem *ale,
3624                                   eAnimChannel_Settings UNUSED(setting),
3625                                   short *type)
3626 {
3627   Mask *mask = (Mask *)ale->data;
3628 
3629   /* all flags are just in mask->flag for now... */
3630   return GET_ACF_FLAG_PTR(mask->flag, type);
3631 }
3632 
3633 /* mask datablock type define */
3634 static bAnimChannelType ACF_MASKDATA = {
3635     "Mask Datablock",       /* type name */
3636     ACHANNEL_ROLE_EXPANDER, /* role */
3637 
3638     acf_mask_color,           /* backdrop color */
3639     acf_group_backdrop,       /* backdrop */
3640     acf_generic_indention_0,  /* indent level */
3641     acf_generic_group_offset, /* offset */
3642 
3643     acf_generic_idblock_name,     /* name */
3644     acf_generic_idfill_name_prop, /* name prop */
3645     acf_mask_icon,                /* icon */
3646 
3647     acf_mask_setting_valid, /* has setting */
3648     acf_mask_setting_flag,  /* flag for setting */
3649     acf_mask_setting_ptr,   /* pointer for setting */
3650 };
3651 
3652 /* Mask Layer ------------------------------------------- */
3653 
3654 /* name for grease pencil layer entries */
acf_masklay_name(bAnimListElem * ale,char * name)3655 static void acf_masklay_name(bAnimListElem *ale, char *name)
3656 {
3657   MaskLayer *masklay = (MaskLayer *)ale->data;
3658 
3659   if (masklay && name) {
3660     BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
3661   }
3662 }
3663 
3664 /* name property for grease pencil layer entries */
acf_masklay_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)3665 static bool acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3666 {
3667   if (ale->data) {
3668     RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
3669     *prop = RNA_struct_name_property(ptr->type);
3670 
3671     return (*prop != NULL);
3672   }
3673 
3674   return false;
3675 }
3676 
3677 /* check if some setting exists for this channel */
acf_masklay_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * UNUSED (ale),eAnimChannel_Settings setting)3678 static bool acf_masklay_setting_valid(bAnimContext *UNUSED(ac),
3679                                       bAnimListElem *UNUSED(ale),
3680                                       eAnimChannel_Settings setting)
3681 {
3682   switch (setting) {
3683     /* unsupported */
3684     case ACHANNEL_SETTING_EXPAND:  /* mask layers are more like F-Curves than groups */
3685     case ACHANNEL_SETTING_VISIBLE: /* graph editor only */
3686     case ACHANNEL_SETTING_SOLO:    /* nla editor only */
3687     case ACHANNEL_SETTING_MOD_OFF:
3688     case ACHANNEL_SETTING_PINNED: /* nla actions only */
3689     case ACHANNEL_SETTING_MUTE:
3690       return false;
3691 
3692     /* always available */
3693     default:
3694       return true;
3695   }
3696 }
3697 
3698 /* get the appropriate flag(s) for the setting when it is valid  */
acf_masklay_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3699 static int acf_masklay_setting_flag(bAnimContext *UNUSED(ac),
3700                                     eAnimChannel_Settings setting,
3701                                     bool *neg)
3702 {
3703   /* clear extra return data first */
3704   *neg = false;
3705 
3706   switch (setting) {
3707     case ACHANNEL_SETTING_SELECT: /* selected */
3708       return MASK_LAYERFLAG_SELECT;
3709 
3710     case ACHANNEL_SETTING_PROTECT: /* protected */
3711       return MASK_LAYERFLAG_LOCKED;
3712 
3713     default: /* unsupported */
3714       return 0;
3715   }
3716 }
3717 
3718 /* get pointer to the setting */
acf_masklay_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)3719 static void *acf_masklay_setting_ptr(bAnimListElem *ale,
3720                                      eAnimChannel_Settings UNUSED(setting),
3721                                      short *type)
3722 {
3723   MaskLayer *masklay = (MaskLayer *)ale->data;
3724 
3725   /* all flags are just in masklay->flag for now... */
3726   return GET_ACF_FLAG_PTR(masklay->flag, type);
3727 }
3728 
3729 /* grease pencil layer type define */
3730 static bAnimChannelType ACF_MASKLAYER = {
3731     "Mask Layer",          /* type name */
3732     ACHANNEL_ROLE_CHANNEL, /* role */
3733 
3734     acf_generic_channel_color,      /* backdrop color */
3735     acf_generic_channel_backdrop,   /* backdrop */
3736     acf_generic_indention_flexible, /* indent level */
3737     acf_generic_group_offset,       /* offset */
3738 
3739     acf_masklay_name,      /* name */
3740     acf_masklay_name_prop, /* name prop */
3741     NULL,                  /* icon */
3742 
3743     acf_masklay_setting_valid, /* has setting */
3744     acf_masklay_setting_flag,  /* flag for setting */
3745     acf_masklay_setting_ptr,   /* pointer for setting */
3746 };
3747 
3748 /* NLA Track ----------------------------------------------- */
3749 
3750 /* get backdrop color for nla track channels */
acf_nlatrack_color(bAnimContext * UNUSED (ac),bAnimListElem * ale,float r_color[3])3751 static void acf_nlatrack_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
3752 {
3753   NlaTrack *nlt = (NlaTrack *)ale->data;
3754   AnimData *adt = ale->adt;
3755   bool nonSolo = false;
3756 
3757   /* is track enabled for solo drawing? */
3758   if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
3759     if ((nlt->flag & NLATRACK_SOLO) == 0) {
3760       /* tag for special non-solo handling */
3761       nonSolo = true;
3762     }
3763   }
3764 
3765   /* set color for nla track */
3766   UI_GetThemeColorShade3fv(TH_NLA_TRACK, ((nonSolo == false) ? 20 : -20), r_color);
3767 }
3768 
3769 /* name for nla track entries */
acf_nlatrack_name(bAnimListElem * ale,char * name)3770 static void acf_nlatrack_name(bAnimListElem *ale, char *name)
3771 {
3772   NlaTrack *nlt = (NlaTrack *)ale->data;
3773 
3774   if (nlt && name) {
3775     BLI_strncpy(name, nlt->name, ANIM_CHAN_NAME_SIZE);
3776   }
3777 }
3778 
3779 /* name property for nla track entries */
acf_nlatrack_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)3780 static bool acf_nlatrack_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3781 {
3782   if (ale->data) {
3783     RNA_pointer_create(ale->id, &RNA_NlaTrack, ale->data, ptr);
3784     *prop = RNA_struct_name_property(ptr->type);
3785 
3786     return (*prop != NULL);
3787   }
3788 
3789   return false;
3790 }
3791 
3792 /* check if some setting exists for this channel */
acf_nlatrack_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * ale,eAnimChannel_Settings setting)3793 static bool acf_nlatrack_setting_valid(bAnimContext *UNUSED(ac),
3794                                        bAnimListElem *ale,
3795                                        eAnimChannel_Settings setting)
3796 {
3797   NlaTrack *nlt = (NlaTrack *)ale->data;
3798   AnimData *adt = ale->adt;
3799 
3800   /* visibility of settings depends on various states... */
3801   switch (setting) {
3802     /* always supported */
3803     case ACHANNEL_SETTING_SELECT:
3804     case ACHANNEL_SETTING_SOLO:
3805       return true;
3806 
3807     /* conditionally supported... */
3808     case ACHANNEL_SETTING_PROTECT:
3809     case ACHANNEL_SETTING_MUTE:
3810       /* if this track is active and we're tweaking it, don't draw these toggles */
3811       if (((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0) {
3812         /* is track enabled for solo drawing? */
3813         if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
3814           if (nlt->flag & NLATRACK_SOLO) {
3815             /* ok - we've got a solo track, and this is it */
3816             return true;
3817           }
3818           /* not ok - we've got a solo track, but this isn't it, so make it more obvious */
3819           return false;
3820         }
3821 
3822         /* ok - no tracks are solo'd, and this isn't being tweaked */
3823         return true;
3824       }
3825       /* unsupported - this track is being tweaked */
3826       return false;
3827 
3828     /* unsupported */
3829     default:
3830       return false;
3831   }
3832 }
3833 
3834 /* get the appropriate flag(s) for the setting when it is valid  */
acf_nlatrack_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)3835 static int acf_nlatrack_setting_flag(bAnimContext *UNUSED(ac),
3836                                      eAnimChannel_Settings setting,
3837                                      bool *neg)
3838 {
3839   /* clear extra return data first */
3840   *neg = false;
3841 
3842   switch (setting) {
3843     case ACHANNEL_SETTING_SELECT: /* selected */
3844       return NLATRACK_SELECTED;
3845 
3846     case ACHANNEL_SETTING_MUTE: /* muted */
3847       return NLATRACK_MUTED;
3848 
3849     case ACHANNEL_SETTING_PROTECT: /* protected */
3850       return NLATRACK_PROTECTED;
3851 
3852     case ACHANNEL_SETTING_SOLO: /* solo */
3853       return NLATRACK_SOLO;
3854 
3855     default: /* unsupported */
3856       return 0;
3857   }
3858 }
3859 
3860 /* get pointer to the setting */
acf_nlatrack_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)3861 static void *acf_nlatrack_setting_ptr(bAnimListElem *ale,
3862                                       eAnimChannel_Settings UNUSED(setting),
3863                                       short *type)
3864 {
3865   NlaTrack *nlt = (NlaTrack *)ale->data;
3866   return GET_ACF_FLAG_PTR(nlt->flag, type);
3867 }
3868 
3869 /* nla track type define */
3870 static bAnimChannelType ACF_NLATRACK = {
3871     "NLA Track",           /* type name */
3872     ACHANNEL_ROLE_CHANNEL, /* role */
3873 
3874     acf_nlatrack_color,             /* backdrop color */
3875     acf_generic_channel_backdrop,   /* backdrop */
3876     acf_generic_indention_flexible, /* indent level */
3877     acf_generic_group_offset,
3878     /* offset */ /* XXX? */
3879 
3880     acf_nlatrack_name,      /* name */
3881     acf_nlatrack_name_prop, /* name prop */
3882     NULL,                   /* icon */
3883 
3884     acf_nlatrack_setting_valid, /* has setting */
3885     acf_nlatrack_setting_flag,  /* flag for setting */
3886     acf_nlatrack_setting_ptr,   /* pointer for setting */
3887 };
3888 
3889 /* NLA Action ----------------------------------------------- */
3890 
3891 /* icon for action depends on whether it's in tweaking mode */
acf_nlaaction_icon(bAnimListElem * ale)3892 static int acf_nlaaction_icon(bAnimListElem *ale)
3893 {
3894   AnimData *adt = ale->adt;
3895 
3896   /* indicate tweaking-action state by changing the icon... */
3897   if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
3898     return ICON_ACTION_TWEAK;
3899   }
3900 
3901   return ICON_ACTION;
3902 }
3903 
3904 /* Backdrop color for nla action channel
3905  * Although this can't be used directly for NLA Action drawing,
3906  * it is still needed for use behind the RHS toggles
3907  */
acf_nlaaction_color(bAnimContext * UNUSED (ac),bAnimListElem * ale,float r_color[3])3908 static void acf_nlaaction_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float r_color[3])
3909 {
3910   float color[4];
3911 
3912   /* Action Line
3913    *   The alpha values action_get_color returns are only useful for drawing
3914    *   strips backgrounds but here we're doing channel list backgrounds instead
3915    *   so we ignore that and use our own when needed
3916    */
3917   nla_action_get_color(ale->adt, (bAction *)ale->data, color);
3918 
3919   /* NOTE: since the return types only allow rgb, we cannot do the alpha-blending we'd
3920    * like for the solo-drawing case. Hence, this method isn't actually used for drawing
3921    * most of the channel...
3922    */
3923   copy_v3_v3(r_color, color);
3924 }
3925 
3926 /* backdrop for nla action channel */
acf_nlaaction_backdrop(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc)3927 static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc)
3928 {
3929   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
3930   View2D *v2d = &ac->region->v2d;
3931   AnimData *adt = ale->adt;
3932   short offset = (acf->get_offset) ? acf->get_offset(ac, ale) : 0;
3933   float color[4];
3934 
3935   /* Action Line
3936    *   The alpha values action_get_color returns are only useful for drawing
3937    *   strips backgrounds but here we're doing channel list backgrounds instead
3938    *   so we ignore that and use our own when needed
3939    */
3940   nla_action_get_color(adt, (bAction *)ale->data, color);
3941 
3942   if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
3943     color[3] = 1.0f;
3944   }
3945   else {
3946     color[3] = (adt && (adt->flag & ADT_NLA_SOLO_TRACK)) ? 0.3f : 1.0f;
3947   }
3948 
3949   /* only on top left corner, to show that this channel sits on top of the preceding ones
3950    * while still linking into the action line strip to the right
3951    */
3952   UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT);
3953 
3954   /* draw slightly shifted up vertically to look like it has more separation from other channels,
3955    * but we then need to slightly shorten it so that it doesn't look like it overlaps
3956    */
3957   UI_draw_roundbox_4fv(true,
3958                        offset,
3959                        yminc + NLACHANNEL_SKIP,
3960                        (float)v2d->cur.xmax,
3961                        ymaxc + NLACHANNEL_SKIP - 1,
3962                        8,
3963                        color);
3964 }
3965 
3966 /* name for nla action entries */
acf_nlaaction_name(bAnimListElem * ale,char * name)3967 static void acf_nlaaction_name(bAnimListElem *ale, char *name)
3968 {
3969   bAction *act = (bAction *)ale->data;
3970 
3971   if (name) {
3972     if (act) {
3973       /* TODO: add special decoration when doing this in tweaking mode? */
3974       BLI_strncpy(name, act->id.name + 2, ANIM_CHAN_NAME_SIZE);
3975     }
3976     else {
3977       BLI_strncpy(name, "<No Action>", ANIM_CHAN_NAME_SIZE);
3978     }
3979   }
3980 }
3981 
3982 /* name property for nla action entries */
acf_nlaaction_name_prop(bAnimListElem * ale,PointerRNA * ptr,PropertyRNA ** prop)3983 static bool acf_nlaaction_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
3984 {
3985   if (ale->data) {
3986     RNA_pointer_create(ale->id, &RNA_Action, ale->data, ptr);
3987     *prop = RNA_struct_name_property(ptr->type);
3988 
3989     return (*prop != NULL);
3990   }
3991 
3992   return false;
3993 }
3994 
3995 /* check if some setting exists for this channel */
acf_nlaaction_setting_valid(bAnimContext * UNUSED (ac),bAnimListElem * ale,eAnimChannel_Settings setting)3996 static bool acf_nlaaction_setting_valid(bAnimContext *UNUSED(ac),
3997                                         bAnimListElem *ale,
3998                                         eAnimChannel_Settings setting)
3999 {
4000   AnimData *adt = ale->adt;
4001 
4002   /* visibility of settings depends on various states... */
4003   switch (setting) {
4004     /* conditionally supported */
4005     case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
4006       if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
4007         /* this should only appear in tweakmode */
4008         return true;
4009       }
4010       else {
4011         return false;
4012       }
4013 
4014     /* unsupported */
4015     default:
4016       return false;
4017   }
4018 }
4019 
4020 /* get the appropriate flag(s) for the setting when it is valid  */
acf_nlaaction_setting_flag(bAnimContext * UNUSED (ac),eAnimChannel_Settings setting,bool * neg)4021 static int acf_nlaaction_setting_flag(bAnimContext *UNUSED(ac),
4022                                       eAnimChannel_Settings setting,
4023                                       bool *neg)
4024 {
4025   /* clear extra return data first */
4026   *neg = false;
4027 
4028   switch (setting) {
4029     case ACHANNEL_SETTING_PINNED: /* pinned - map/unmap */
4030       *neg = true;                /* XXX */
4031       return ADT_NLA_EDIT_NOMAP;
4032 
4033     default: /* unsupported */
4034       return 0;
4035   }
4036 }
4037 
4038 /* get pointer to the setting */
acf_nlaaction_setting_ptr(bAnimListElem * ale,eAnimChannel_Settings UNUSED (setting),short * type)4039 static void *acf_nlaaction_setting_ptr(bAnimListElem *ale,
4040                                        eAnimChannel_Settings UNUSED(setting),
4041                                        short *type)
4042 {
4043   AnimData *adt = ale->adt;
4044   return GET_ACF_FLAG_PTR(adt->flag, type);
4045 }
4046 
4047 /* nla action type define */
4048 static bAnimChannelType ACF_NLAACTION = {
4049     "NLA Active Action",   /* type name */
4050     ACHANNEL_ROLE_CHANNEL, /* role */
4051 
4052     acf_nlaaction_color,            /* backdrop color (NOTE: the backdrop handles this too,
4053                                      * since it needs special hacks). */
4054     acf_nlaaction_backdrop,         /* backdrop */
4055     acf_generic_indention_flexible, /* indent level */
4056     acf_generic_group_offset,
4057     /* offset */ /* XXX? */
4058 
4059     acf_nlaaction_name,      /* name */
4060     acf_nlaaction_name_prop, /* name prop */
4061     acf_nlaaction_icon,      /* icon */
4062 
4063     acf_nlaaction_setting_valid, /* has setting */
4064     acf_nlaaction_setting_flag,  /* flag for setting */
4065     acf_nlaaction_setting_ptr,   /* pointer for setting */
4066 };
4067 
4068 /* *********************************************** */
4069 /* Type Registration and General Access */
4070 
4071 /* These globals only ever get directly accessed in this file */
4072 static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES];
4073 static short ACF_INIT = 1; /* when non-zero, the list needs to be updated */
4074 
4075 /* Initialize type info definitions */
ANIM_init_channel_typeinfo_data(void)4076 static void ANIM_init_channel_typeinfo_data(void)
4077 {
4078   int type = 0;
4079 
4080   /* start initializing if necessary... */
4081   if (ACF_INIT) {
4082     ACF_INIT = 0;
4083 
4084     /* NOTE: need to keep the order of these synchronized with the definition of
4085      * channel types (eAnim_ChannelType) in ED_anim_api.h
4086      */
4087     animchannelTypeInfo[type++] = NULL; /* None */
4088     animchannelTypeInfo[type++] = NULL; /* AnimData */
4089     animchannelTypeInfo[type++] = NULL; /* Special */
4090 
4091     animchannelTypeInfo[type++] = &ACF_SUMMARY; /* Motion Summary */
4092 
4093     animchannelTypeInfo[type++] = &ACF_SCENE;  /* Scene */
4094     animchannelTypeInfo[type++] = &ACF_OBJECT; /* Object */
4095     animchannelTypeInfo[type++] = &ACF_GROUP;  /* Group */
4096     animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */
4097 
4098     animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
4099     animchannelTypeInfo[type++] = &ACF_NLACURVE;    /* NLA Control FCurve Channel */
4100 
4101     animchannelTypeInfo[type++] = &ACF_FILLACTD;    /* Object Action Expander */
4102     animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
4103 
4104     animchannelTypeInfo[type++] = &ACF_DSMAT;        /* Material Channel */
4105     animchannelTypeInfo[type++] = &ACF_DSLIGHT;      /* Light Channel */
4106     animchannelTypeInfo[type++] = &ACF_DSCAM;        /* Camera Channel */
4107     animchannelTypeInfo[type++] = &ACF_DSCACHEFILE;  /* CacheFile Channel */
4108     animchannelTypeInfo[type++] = &ACF_DSCUR;        /* Curve Channel */
4109     animchannelTypeInfo[type++] = &ACF_DSSKEY;       /* ShapeKey Channel */
4110     animchannelTypeInfo[type++] = &ACF_DSWOR;        /* World Channel */
4111     animchannelTypeInfo[type++] = &ACF_DSNTREE;      /* NodeTree Channel */
4112     animchannelTypeInfo[type++] = &ACF_DSPART;       /* Particle Channel */
4113     animchannelTypeInfo[type++] = &ACF_DSMBALL;      /* MetaBall Channel */
4114     animchannelTypeInfo[type++] = &ACF_DSARM;        /* Armature Channel */
4115     animchannelTypeInfo[type++] = &ACF_DSMESH;       /* Mesh Channel */
4116     animchannelTypeInfo[type++] = &ACF_DSTEX;        /* Texture Channel */
4117     animchannelTypeInfo[type++] = &ACF_DSLAT;        /* Lattice Channel */
4118     animchannelTypeInfo[type++] = &ACF_DSLINESTYLE;  /* LineStyle Channel */
4119     animchannelTypeInfo[type++] = &ACF_DSSPK;        /* Speaker Channel */
4120     animchannelTypeInfo[type++] = &ACF_DSGPENCIL;    /* GreasePencil Channel */
4121     animchannelTypeInfo[type++] = &ACF_DSMCLIP;      /* MovieClip Channel */
4122     animchannelTypeInfo[type++] = &ACF_DSHAIR;       /* Hair Channel */
4123     animchannelTypeInfo[type++] = &ACF_DSPOINTCLOUD; /* PointCloud Channel */
4124     animchannelTypeInfo[type++] = &ACF_DSVOLUME;     /* Volume Channel */
4125     animchannelTypeInfo[type++] = &ACF_DSSIMULATION; /* Simulation Channel */
4126 
4127     animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */
4128 
4129     animchannelTypeInfo[type++] = &ACF_GPD; /* Grease Pencil Datablock */
4130     animchannelTypeInfo[type++] = &ACF_GPL; /* Grease Pencil Layer */
4131 
4132     animchannelTypeInfo[type++] = &ACF_MASKDATA;  /* Mask Datablock */
4133     animchannelTypeInfo[type++] = &ACF_MASKLAYER; /* Mask Layer */
4134 
4135     animchannelTypeInfo[type++] = &ACF_NLATRACK;  /* NLA Track */
4136     animchannelTypeInfo[type++] = &ACF_NLAACTION; /* NLA Action */
4137   }
4138 }
4139 
4140 /* Get type info from given channel type */
ANIM_channel_get_typeinfo(bAnimListElem * ale)4141 const bAnimChannelType *ANIM_channel_get_typeinfo(bAnimListElem *ale)
4142 {
4143   /* santiy checks */
4144   if (ale == NULL) {
4145     return NULL;
4146   }
4147 
4148   /* init the typeinfo if not available yet... */
4149   ANIM_init_channel_typeinfo_data();
4150 
4151   /* check if type is in bounds... */
4152   if ((ale->type >= 0) && (ale->type < ANIMTYPE_NUM_TYPES)) {
4153     return animchannelTypeInfo[ale->type];
4154   }
4155 
4156   return NULL;
4157 }
4158 
4159 /* --------------------------- */
4160 
4161 /* Print debug info string for the given channel */
ANIM_channel_debug_print_info(bAnimListElem * ale,short indent_level)4162 void ANIM_channel_debug_print_info(bAnimListElem *ale, short indent_level)
4163 {
4164   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
4165 
4166   /* print indents */
4167   for (; indent_level > 0; indent_level--) {
4168     printf("  ");
4169   }
4170 
4171   /* print info */
4172   if (acf) {
4173     char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
4174 
4175     /* get UI name */
4176     if (acf->name) {
4177       acf->name(ale, name);
4178     }
4179     else {
4180       BLI_strncpy(name, "<No name>", sizeof(name));
4181     }
4182 
4183     /* print type name + ui name */
4184     printf("ChanType: <%s> Name: \"%s\"\n", acf->channel_type_name, name);
4185   }
4186   else if (ale) {
4187     printf("ChanType: <Unknown - %d>\n", ale->type);
4188   }
4189   else {
4190     printf("<Invalid channel - NULL>\n");
4191   }
4192 }
4193 
4194 /* --------------------------- */
4195 
4196 /* Check if some setting for a channel is enabled
4197  * Returns: 1 = On, 0 = Off, -1 = Invalid
4198  */
ANIM_channel_setting_get(bAnimContext * ac,bAnimListElem * ale,eAnimChannel_Settings setting)4199 short ANIM_channel_setting_get(bAnimContext *ac, bAnimListElem *ale, eAnimChannel_Settings setting)
4200 {
4201   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
4202 
4203   /* 1) check that the setting exists for the current context */
4204   if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
4205     /* 2) get pointer to check for flag in, and the flag to check for */
4206     short ptrsize;
4207     bool negflag;
4208     int flag;
4209     void *ptr;
4210 
4211     flag = acf->setting_flag(ac, setting, &negflag);
4212     ptr = acf->setting_ptr(ale, setting, &ptrsize);
4213 
4214     /* check if flag is enabled */
4215     if (ptr && flag) {
4216       switch (ptrsize) {
4217         case sizeof(int): /* integer pointer for setting */
4218         {
4219           const int *val = (int *)ptr;
4220 
4221           if (negflag) {
4222             return ((*val) & flag) == 0;
4223           }
4224           return ((*val) & flag) != 0;
4225         }
4226         case sizeof(short): /* short pointer for setting */
4227         {
4228           const short *val = (short *)ptr;
4229 
4230           if (negflag) {
4231             return ((*val) & flag) == 0;
4232           }
4233           return ((*val) & flag) != 0;
4234         }
4235         case sizeof(char): /* char pointer for setting */
4236         {
4237           const char *val = (char *)ptr;
4238 
4239           if (negflag) {
4240             return ((*val) & flag) == 0;
4241           }
4242           return ((*val) & flag) != 0;
4243         }
4244       }
4245     }
4246   }
4247 
4248   /* not found... */
4249   return -1;
4250 }
4251 
4252 /* Quick macro for use in ANIM_channel_setting_set -
4253  * set flag for setting according the mode given. */
4254 #define ACF_SETTING_SET(sval, sflag, smode) \
4255   { \
4256     if (negflag) { \
4257       if (smode == ACHANNEL_SETFLAG_INVERT) { \
4258         (sval) ^= (sflag); \
4259       } \
4260       else if (smode == ACHANNEL_SETFLAG_ADD) { \
4261         (sval) &= ~(sflag); \
4262       } \
4263       else { \
4264         (sval) |= (sflag); \
4265       } \
4266     } \
4267     else { \
4268       if (smode == ACHANNEL_SETFLAG_INVERT) { \
4269         (sval) ^= (sflag); \
4270       } \
4271       else if (smode == ACHANNEL_SETFLAG_ADD) { \
4272         (sval) |= (sflag); \
4273       } \
4274       else { \
4275         (sval) &= ~(sflag); \
4276       } \
4277     } \
4278   } \
4279   (void)0
4280 
4281 /* Change value of some setting for a channel
4282  * - setting: eAnimChannel_Settings
4283  * - mode: eAnimChannels_SetFlag
4284  */
ANIM_channel_setting_set(bAnimContext * ac,bAnimListElem * ale,eAnimChannel_Settings setting,eAnimChannels_SetFlag mode)4285 void ANIM_channel_setting_set(bAnimContext *ac,
4286                               bAnimListElem *ale,
4287                               eAnimChannel_Settings setting,
4288                               eAnimChannels_SetFlag mode)
4289 {
4290   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
4291 
4292   /* 1) check that the setting exists for the current context */
4293   if ((acf) && (!acf->has_setting || acf->has_setting(ac, ale, setting))) {
4294     /* 2) get pointer to check for flag in, and the flag to check for */
4295     short ptrsize;
4296     bool negflag;
4297     int flag;
4298     void *ptr;
4299 
4300     flag = acf->setting_flag(ac, setting, &negflag);
4301     ptr = acf->setting_ptr(ale, setting, &ptrsize);
4302 
4303     /* check if flag is enabled */
4304     if (ptr && flag) {
4305       switch (ptrsize) {
4306         case sizeof(int): /* integer pointer for setting */
4307         {
4308           int *val = (int *)ptr;
4309           ACF_SETTING_SET(*val, flag, mode);
4310           break;
4311         }
4312         case sizeof(short): /* short pointer for setting */
4313         {
4314           short *val = (short *)ptr;
4315           ACF_SETTING_SET(*val, flag, mode);
4316           break;
4317         }
4318         case sizeof(char): /* char pointer for setting */
4319         {
4320           char *val = (char *)ptr;
4321           ACF_SETTING_SET(*val, flag, mode);
4322           break;
4323         }
4324       }
4325     }
4326   }
4327 }
4328 
4329 /* --------------------------- */
4330 
4331 /* size of icons */
4332 #define ICON_WIDTH (0.85f * U.widget_unit)
4333 /* width of sliders */
4334 #define SLIDER_WIDTH (4 * U.widget_unit)
4335 /* min-width of rename textboxes */
4336 #define RENAME_TEXT_MIN_WIDTH (U.widget_unit)
4337 /* width of graph editor color bands */
4338 #define GRAPH_COLOR_BAND_WIDTH (0.3f * U.widget_unit)
4339 /* extra offset for the visibility icons in the graph editor */
4340 #define GRAPH_ICON_VISIBILITY_OFFSET (GRAPH_COLOR_BAND_WIDTH * 1.5f)
4341 
4342 /* Helper - Check if a channel needs renaming */
achannel_is_being_renamed(const bAnimContext * ac,const bAnimChannelType * acf,size_t channel_index)4343 static bool achannel_is_being_renamed(const bAnimContext *ac,
4344                                       const bAnimChannelType *acf,
4345                                       size_t channel_index)
4346 {
4347   if (acf->name_prop && ac->ads) {
4348     /* if rename index matches, this channel is being renamed */
4349     if (ac->ads->renameIndex == channel_index + 1) {
4350       return true;
4351     }
4352   }
4353 
4354   /* not being renamed */
4355   return false;
4356 }
4357 
4358 /* Draw the given channel */
ANIM_channel_draw(bAnimContext * ac,bAnimListElem * ale,float yminc,float ymaxc,size_t channel_index)4359 void ANIM_channel_draw(
4360     bAnimContext *ac, bAnimListElem *ale, float yminc, float ymaxc, size_t channel_index)
4361 {
4362   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
4363   View2D *v2d = &ac->region->v2d;
4364   short selected, offset;
4365   float y, ymid, ytext;
4366 
4367   /* sanity checks - don't draw anything */
4368   if (ELEM(NULL, acf, ale)) {
4369     return;
4370   }
4371 
4372   /* get initial offset */
4373   if (acf->get_offset) {
4374     offset = acf->get_offset(ac, ale);
4375   }
4376   else {
4377     offset = 0;
4378   }
4379 
4380   /* calculate appropriate y-coordinates for icon buttons */
4381   y = (ymaxc - yminc) / 2 + yminc;
4382   ymid = y - 0.5f * ICON_WIDTH;
4383   /* y-coordinates for text is only 4 down from middle */
4384   ytext = y - 0.2f * U.widget_unit;
4385 
4386   /* check if channel is selected */
4387   if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) {
4388     selected = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
4389   }
4390   else {
4391     selected = 0;
4392   }
4393 
4394   /* set blending again, as may not be set in previous step */
4395   GPU_blend(GPU_BLEND_ALPHA);
4396 
4397   /* step 1) draw backdrop ...........................................  */
4398   if (acf->draw_backdrop) {
4399     acf->draw_backdrop(ac, ale, yminc, ymaxc);
4400   }
4401 
4402   /* step 2) draw expand widget ....................................... */
4403   if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
4404     /* just skip - drawn as widget now */
4405     offset += ICON_WIDTH;
4406   }
4407 
4408   /* step 3) draw icon ............................................... */
4409   if (acf->icon) {
4410     UI_icon_draw(offset, ymid, acf->icon(ale));
4411     offset += ICON_WIDTH;
4412   }
4413 
4414   /* step 4) draw special toggles  .................................
4415    * - in Graph Editor, check-boxes for visibility in curves area
4416    * - in NLA Editor, glowing dots for solo/not solo...
4417    * - in Grease Pencil mode, color swatches for layer color
4418    */
4419   if (ac->sl) {
4420     if ((ac->spacetype == SPACE_GRAPH) &&
4421         (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
4422          acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
4423       /* for F-Curves, draw color-preview of curve left to the visibility icon */
4424       if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
4425         FCurve *fcu = (FCurve *)ale->data;
4426         uint pos = GPU_vertformat_attr_add(
4427             immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
4428 
4429         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
4430 
4431         /* F-Curve channels need to have a special 'color code' box drawn,
4432          * which is colored with whatever color the curve has stored.
4433          */
4434 
4435         /* If the curve is hidden, make the rect less opaque. */
4436         float rect_alpha = (fcu->flag & FCURVE_VISIBLE) ? 1 : 0.3f;
4437         immUniformColor3fvAlpha(fcu->color, rect_alpha);
4438 
4439         immRectf(pos, offset, yminc, offset + GRAPH_COLOR_BAND_WIDTH, ymaxc);
4440         immUnbindProgram();
4441       }
4442 
4443       /* turn off blending, since not needed anymore... */
4444       GPU_blend(GPU_BLEND_NONE);
4445 
4446       /* icon is drawn as widget now... */
4447       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
4448         if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
4449           offset += ICON_WIDTH + GRAPH_ICON_VISIBILITY_OFFSET;
4450         }
4451         else {
4452           offset += ICON_WIDTH;
4453         }
4454       }
4455       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
4456         offset += ICON_WIDTH;
4457       }
4458     }
4459     else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
4460       /* just skip - drawn as widget now */
4461       offset += ICON_WIDTH;
4462     }
4463   }
4464 
4465   /* step 5) draw name ............................................... */
4466   /* Don't draw this if renaming... */
4467   if (acf->name && !achannel_is_being_renamed(ac, acf, channel_index)) {
4468     const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
4469     char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
4470     uchar col[4];
4471 
4472     /* set text color */
4473     /* XXX: if active, highlight differently? */
4474 
4475     if (selected) {
4476       UI_GetThemeColor4ubv(TH_TEXT_HI, col);
4477     }
4478     else {
4479       UI_GetThemeColor4ubv(TH_TEXT, col);
4480     }
4481 
4482     /* get name */
4483     acf->name(ale, name);
4484 
4485     offset += 3;
4486     UI_fontstyle_draw_simple(fstyle, offset, ytext, name, col);
4487 
4488     /* draw red underline if channel is disabled */
4489     if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE) && (ale->flag & FCURVE_DISABLED)) {
4490       uint pos = GPU_vertformat_attr_add(
4491           immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
4492 
4493       immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
4494 
4495       /* FIXME: replace hardcoded color here, and check on extents! */
4496       immUniformColor3f(1.0f, 0.0f, 0.0f);
4497 
4498       GPU_line_width(2.0f);
4499 
4500       immBegin(GPU_PRIM_LINES, 2);
4501       immVertex2f(pos, (float)offset, yminc);
4502       immVertex2f(pos, (float)v2d->cur.xmax, yminc);
4503       immEnd();
4504 
4505       immUnbindProgram();
4506     }
4507   }
4508 
4509   /* step 6) draw backdrops behind mute+protection toggles + (sliders) ....................... */
4510   /*  - Reset offset - now goes from RHS of panel.
4511    *  - Exception for graph editor, which needs extra space for the scroll bar.
4512    */
4513   if (ac->spacetype == SPACE_GRAPH &&
4514       ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_GROUP)) {
4515     offset = V2D_SCROLL_WIDTH;
4516   }
4517   else {
4518     offset = 0;
4519   }
4520 
4521   /* TODO: when drawing sliders, make those draw instead of these toggles if not enough space */
4522 
4523   if (v2d) {
4524     short draw_sliders = 0;
4525     float ymin_ofs = 0.0f;
4526     float color[3];
4527     uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
4528 
4529     immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
4530 
4531     /* get and set backdrop color */
4532     acf->get_backdrop_color(ac, ale, color);
4533     immUniformColor3fv(color);
4534 
4535     /* check if we need to show the sliders */
4536     if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH)) {
4537       switch (ac->spacetype) {
4538         case SPACE_ACTION: {
4539           SpaceAction *saction = (SpaceAction *)ac->sl;
4540           draw_sliders = (saction->flag & SACTION_SLIDERS);
4541           break;
4542         }
4543         case SPACE_GRAPH: {
4544           SpaceGraph *sipo = (SpaceGraph *)ac->sl;
4545           draw_sliders = (sipo->flag & SIPO_SLIDERS);
4546           break;
4547         }
4548       }
4549     }
4550 
4551     /* check if there's enough space for the toggles if the sliders are drawn too */
4552     if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2)) {
4553       /* protect... */
4554       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
4555         offset += ICON_WIDTH;
4556       }
4557 
4558       /* mute... */
4559       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
4560         offset += ICON_WIDTH;
4561       }
4562 
4563       /* grease pencil visibility... */
4564       if (ale->type == ANIMTYPE_GPLAYER) {
4565         offset += ICON_WIDTH;
4566       }
4567 
4568       /* modifiers toggle... */
4569       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
4570         offset += ICON_WIDTH;
4571       }
4572 
4573       /* pinned... */
4574       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED)) {
4575         offset += ICON_WIDTH;
4576       }
4577 
4578       /* NOTE: technically, NLA Action "pushdown" should be here too,
4579        * but there are no sliders there. */
4580 
4581       /* NLA action channels have slightly different spacing requirements... */
4582       if (ale->type == ANIMTYPE_NLAACTION) {
4583         ymin_ofs = NLACHANNEL_SKIP;
4584       }
4585     }
4586 
4587     /* Draw slider:
4588      * - Even if we can draw sliders for this view,
4589      *   we must also check that the channel-type supports them
4590      *   (only only F-Curves really can support them for now).
4591      * - Slider should start before the toggles (if they're visible)
4592      *   to keep a clean line down the side.
4593      */
4594     if ((draw_sliders) &&
4595         ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE, ANIMTYPE_SHAPEKEY, ANIMTYPE_GPLAYER)) {
4596       /* adjust offset */
4597       offset += SLIDER_WIDTH;
4598     }
4599 
4600     /* Finally draw a backdrop rect behind these:
4601      * - Starts from the point where the first toggle/slider starts.
4602      * - Ends past the space that might be reserved for a scroller.
4603      */
4604     immRectf(pos,
4605              v2d->cur.xmax - (float)offset,
4606              yminc + ymin_ofs,
4607              v2d->cur.xmax + EXTRA_SCROLL_PAD,
4608              ymaxc);
4609 
4610     immUnbindProgram();
4611   }
4612 }
4613 
4614 /* ------------------ */
4615 
4616 /* callback for (normal) widget settings - send notifiers */
achannel_setting_widget_cb(bContext * C,void * UNUSED (arg1),void * UNUSED (arg2))4617 static void achannel_setting_widget_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
4618 {
4619   WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
4620 }
4621 
4622 /* callback for widget settings that need flushing */
achannel_setting_flush_widget_cb(bContext * C,void * ale_npoin,void * setting_wrap)4623 static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void *setting_wrap)
4624 {
4625   bAnimListElem *ale_setting = (bAnimListElem *)ale_npoin;
4626   bAnimContext ac;
4627   ListBase anim_data = {NULL, NULL};
4628   int filter;
4629   int setting = POINTER_AS_INT(setting_wrap);
4630   short on = 0;
4631 
4632   /* send notifiers before doing anything else... */
4633   WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
4634 
4635   /* verify that we have a channel to operate on. */
4636   if (!ale_setting) {
4637     return;
4638   }
4639 
4640   if (ale_setting->type == ANIMTYPE_GPLAYER) {
4641     /* draw cache updates for settings that affect the visible strokes */
4642     if (setting == ACHANNEL_SETTING_VISIBLE) {
4643       bGPdata *gpd = (bGPdata *)ale_setting->id;
4644       DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
4645     }
4646 
4647     /* UI updates */
4648     WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
4649   }
4650 
4651   /* Tag for full animation update, so that the settings will have an effect. */
4652   if (ale_setting->id) {
4653     DEG_id_tag_update(ale_setting->id, ID_RECALC_ANIMATION);
4654   }
4655   if (ale_setting->adt && ale_setting->adt->action) {
4656     /* Action is it's own datablock, so has to be tagged specifically. */
4657     DEG_id_tag_update(&ale_setting->adt->action->id, ID_RECALC_ANIMATION);
4658   }
4659 
4660   /* verify animation context */
4661   if (ANIM_animdata_get_context(C, &ac) == 0) {
4662     return;
4663   }
4664 
4665   /* check if the setting is on... */
4666   on = ANIM_channel_setting_get(&ac, ale_setting, setting);
4667 
4668   /* on == -1 means setting not found... */
4669   if (on == -1) {
4670     return;
4671   }
4672 
4673   /* get all channels that can possibly be chosen - but ignore hierarchy */
4674   filter = ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
4675   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
4676 
4677   /* call API method to flush the setting */
4678   ANIM_flush_setting_anim_channels(&ac, &anim_data, ale_setting, setting, on);
4679 
4680   /* free temp data */
4681   ANIM_animdata_freelist(&anim_data);
4682 }
4683 
4684 /* callback for wrapping NLA Track "solo" toggle logic */
achannel_nlatrack_solo_widget_cb(bContext * C,void * ale_poin,void * UNUSED (arg2))4685 static void achannel_nlatrack_solo_widget_cb(bContext *C, void *ale_poin, void *UNUSED(arg2))
4686 {
4687   bAnimListElem *ale = ale_poin;
4688   AnimData *adt = ale->adt;
4689   NlaTrack *nlt = ale->data;
4690 
4691   /* Toggle 'solo' mode. There are several complications here which need explaining:
4692    * - The method call is needed to perform a few additional validation operations
4693    *   to ensure that the mode is applied properly
4694    * - BUT, since the button already toggles the value, we need to un-toggle it
4695    *   before the API call gets to it, otherwise it will end up clearing the result
4696    *   again!
4697    */
4698   nlt->flag ^= NLATRACK_SOLO;
4699   BKE_nlatrack_solo_toggle(adt, nlt);
4700 
4701   /* send notifiers */
4702   DEG_id_tag_update(ale->id, ID_RECALC_ANIMATION);
4703   WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
4704 }
4705 
4706 /* callback for widget sliders - insert keyframes */
achannel_setting_slider_cb(bContext * C,void * id_poin,void * fcu_poin)4707 static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
4708 {
4709   ID *id = (ID *)id_poin;
4710   AnimData *adt = BKE_animdata_from_id(id);
4711   FCurve *fcu = (FCurve *)fcu_poin;
4712 
4713   ReportList *reports = CTX_wm_reports(C);
4714   Scene *scene = CTX_data_scene(C);
4715   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
4716   ToolSettings *ts = scene->toolsettings;
4717   ListBase nla_cache = {NULL, NULL};
4718   PointerRNA id_ptr, ptr;
4719   PropertyRNA *prop;
4720   eInsertKeyFlags flag = 0;
4721   bool done = false;
4722   float cfra;
4723 
4724   /* Get RNA pointer */
4725   RNA_id_pointer_create(id, &id_ptr);
4726 
4727   /* Get NLA context for value remapping */
4728   const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
4729                                                                                     (float)CFRA);
4730   NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
4731       &nla_cache, &id_ptr, adt, &anim_eval_context, false);
4732 
4733   /* get current frame and apply NLA-mapping to it (if applicable) */
4734   cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
4735 
4736   /* Get flags for keyframing. */
4737   flag = ANIM_get_keyframing_flags(scene, true);
4738 
4739   /* try to resolve the path stored in the F-Curve */
4740   if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
4741     /* set the special 'replace' flag if on a keyframe */
4742     if (fcurve_frame_has_keyframe(fcu, cfra, 0)) {
4743       flag |= INSERTKEY_REPLACE;
4744     }
4745 
4746     /* insert a keyframe for this F-Curve */
4747     done = insert_keyframe_direct(
4748         reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, nla_context, flag);
4749 
4750     if (done) {
4751       if (adt->action != NULL) {
4752         DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
4753       }
4754       DEG_id_tag_update(id, ID_RECALC_ANIMATION_NO_FLUSH);
4755       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
4756     }
4757   }
4758 
4759   BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
4760 }
4761 
4762 /* callback for shapekey widget sliders - insert keyframes */
achannel_setting_slider_shapekey_cb(bContext * C,void * key_poin,void * kb_poin)4763 static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin)
4764 {
4765   Main *bmain = CTX_data_main(C);
4766   Key *key = (Key *)key_poin;
4767   KeyBlock *kb = (KeyBlock *)kb_poin;
4768   char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
4769 
4770   ReportList *reports = CTX_wm_reports(C);
4771   Scene *scene = CTX_data_scene(C);
4772   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
4773   ToolSettings *ts = scene->toolsettings;
4774   ListBase nla_cache = {NULL, NULL};
4775   PointerRNA id_ptr, ptr;
4776   PropertyRNA *prop;
4777   eInsertKeyFlags flag = 0;
4778   bool done = false;
4779 
4780   /* Get RNA pointer */
4781   RNA_id_pointer_create((ID *)key, &id_ptr);
4782 
4783   /* Get NLA context for value remapping */
4784   const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
4785                                                                                     (float)CFRA);
4786   NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context(
4787       &nla_cache, &id_ptr, key->adt, &anim_eval_context, false);
4788 
4789   /* get current frame and apply NLA-mapping to it (if applicable) */
4790   const float remapped_frame = BKE_nla_tweakedit_remap(
4791       key->adt, anim_eval_context.eval_time, NLATIME_CONVERT_UNMAP);
4792 
4793   /* get flags for keyframing */
4794   flag = ANIM_get_keyframing_flags(scene, true);
4795 
4796   /* try to resolve the path stored in the F-Curve */
4797   if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) {
4798     /* find or create new F-Curve */
4799     /* XXX is the group name for this ok? */
4800     bAction *act = ED_id_action_ensure(bmain, (ID *)key);
4801     FCurve *fcu = ED_action_fcurve_ensure(bmain, act, NULL, &ptr, rna_path, 0);
4802 
4803     /* set the special 'replace' flag if on a keyframe */
4804     if (fcurve_frame_has_keyframe(fcu, remapped_frame, 0)) {
4805       flag |= INSERTKEY_REPLACE;
4806     }
4807 
4808     /* insert a keyframe for this F-Curve */
4809     const AnimationEvalContext remapped_anim_eval_context = BKE_animsys_eval_context_construct_at(
4810         &anim_eval_context, remapped_frame);
4811     done = insert_keyframe_direct(reports,
4812                                   ptr,
4813                                   prop,
4814                                   fcu,
4815                                   &remapped_anim_eval_context,
4816                                   ts->keyframe_type,
4817                                   nla_context,
4818                                   flag);
4819 
4820     if (done) {
4821       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
4822     }
4823   }
4824 
4825   /* free the path */
4826   if (rna_path) {
4827     MEM_freeN(rna_path);
4828   }
4829 
4830   BKE_animsys_free_nla_keyframing_context_cache(&nla_cache);
4831 }
4832 
4833 /* callback for NLA Control Curve widget sliders - insert keyframes */
achannel_setting_slider_nla_curve_cb(bContext * C,void * UNUSED (id_poin),void * fcu_poin)4834 static void achannel_setting_slider_nla_curve_cb(bContext *C,
4835                                                  void *UNUSED(id_poin),
4836                                                  void *fcu_poin)
4837 {
4838   /* ID *id = (ID *)id_poin; */
4839   FCurve *fcu = (FCurve *)fcu_poin;
4840 
4841   PointerRNA ptr;
4842   PropertyRNA *prop;
4843   int index;
4844 
4845   ReportList *reports = CTX_wm_reports(C);
4846   Scene *scene = CTX_data_scene(C);
4847   ToolSettings *ts = scene->toolsettings;
4848   eInsertKeyFlags flag = 0;
4849   bool done = false;
4850   float cfra;
4851 
4852   /* get current frame - *no* NLA mapping should be done */
4853   cfra = (float)CFRA;
4854 
4855   /* get flags for keyframing */
4856   flag = ANIM_get_keyframing_flags(scene, true);
4857 
4858   /* Get pointer and property from the slider -
4859    * this should all match up with the NlaStrip required. */
4860   UI_context_active_but_prop_get(C, &ptr, &prop, &index);
4861 
4862   if (fcu && prop) {
4863     /* set the special 'replace' flag if on a keyframe */
4864     if (fcurve_frame_has_keyframe(fcu, cfra, 0)) {
4865       flag |= INSERTKEY_REPLACE;
4866     }
4867 
4868     /* insert a keyframe for this F-Curve */
4869     Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
4870     const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
4871                                                                                       cfra);
4872     done = insert_keyframe_direct(
4873         reports, ptr, prop, fcu, &anim_eval_context, ts->keyframe_type, NULL, flag);
4874 
4875     if (done) {
4876       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
4877     }
4878   }
4879 }
4880 
4881 /* Draw a widget for some setting */
draw_setting_widget(bAnimContext * ac,bAnimListElem * ale,const bAnimChannelType * acf,uiBlock * block,int xpos,int ypos,int setting)4882 static void draw_setting_widget(bAnimContext *ac,
4883                                 bAnimListElem *ale,
4884                                 const bAnimChannelType *acf,
4885                                 uiBlock *block,
4886                                 int xpos,
4887                                 int ypos,
4888                                 int setting)
4889 {
4890   short ptrsize, butType;
4891   bool negflag;
4892   bool usetoggle = true;
4893   int flag, icon;
4894   void *ptr;
4895   const char *tooltip;
4896   uiBut *but = NULL;
4897   bool enabled;
4898 
4899   /* get the flag and the pointer to that flag */
4900   flag = acf->setting_flag(ac, setting, &negflag);
4901   ptr = acf->setting_ptr(ale, setting, &ptrsize);
4902   enabled = ANIM_channel_setting_get(ac, ale, setting);
4903 
4904   /* get the base icon for the setting */
4905   switch (setting) {
4906     case ACHANNEL_SETTING_VISIBLE: /* visibility eyes */
4907       // icon = ((enabled) ? ICON_HIDE_OFF : ICON_HIDE_ON);
4908       icon = ICON_HIDE_ON;
4909 
4910       if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
4911         tooltip = TIP_("F-Curve visibility in Graph Editor");
4912       }
4913       else if (ale->type == ANIMTYPE_GPLAYER) {
4914         tooltip = TIP_("Grease Pencil layer is visible in the viewport");
4915       }
4916       else {
4917         tooltip = TIP_("Channels are visible in Graph Editor for editing");
4918       }
4919       break;
4920 
4921     case ACHANNEL_SETTING_ALWAYS_VISIBLE:
4922       icon = ICON_UNPINNED;
4923       tooltip = TIP_("Channels are visible in Graph Editor for editing");
4924       break;
4925 
4926     case ACHANNEL_SETTING_MOD_OFF: /* modifiers disabled */
4927       icon = ICON_MODIFIER_OFF;
4928       tooltip = TIP_("Enable F-Curve modifiers");
4929       break;
4930 
4931     case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
4932       // icon = ((enabled) ? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
4933       icon = ICON_TRIA_RIGHT;
4934       tooltip = TIP_("Make channels grouped under this channel visible");
4935       break;
4936 
4937     case ACHANNEL_SETTING_SOLO: /* NLA Tracks only */
4938       // icon = ((enabled) ? ICON_SOLO_OFF : ICON_SOLO_ON);
4939       icon = ICON_SOLO_OFF;
4940       tooltip = TIP_(
4941           "NLA Track is the only one evaluated in this animation data-block, with all others "
4942           "muted");
4943       break;
4944 
4945       /* --- */
4946 
4947     case ACHANNEL_SETTING_PROTECT: /* protected lock */
4948       /* TODO: what about when there's no protect needed? */
4949       // icon = ((enabled) ? ICON_LOCKED : ICON_UNLOCKED);
4950       icon = ICON_UNLOCKED;
4951 
4952       if (ale->datatype != ALE_NLASTRIP) {
4953         tooltip = TIP_("Editability of keyframes for this channel");
4954       }
4955       else {
4956         tooltip = TIP_("Editability of NLA Strips in this track");
4957       }
4958       break;
4959 
4960     case ACHANNEL_SETTING_MUTE: /* muted speaker */
4961       icon = ((enabled) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT);
4962       usetoggle = false;
4963 
4964       if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
4965         tooltip = TIP_("Does F-Curve contribute to result");
4966       }
4967       else if ((ac) && (ac->spacetype == SPACE_NLA) && (ale->type != ANIMTYPE_NLATRACK)) {
4968         tooltip = TIP_(
4969             "Temporarily disable NLA stack evaluation (i.e. only the active action is evaluated)");
4970       }
4971       else if (ale->type == ANIMTYPE_GPLAYER) {
4972         tooltip = TIP_(
4973             "Shows all keyframes during animation playback and enabled all frames for editing "
4974             "(uncheck to use only the current keyframe during animation playback and editing)");
4975       }
4976       else {
4977         tooltip = TIP_("Do channels contribute to result (toggle channel muting)");
4978       }
4979       break;
4980 
4981     case ACHANNEL_SETTING_PINNED: /* pin icon */
4982       // icon = ((enabled) ? ICON_PINNED : ICON_UNPINNED);
4983       icon = ICON_UNPINNED;
4984 
4985       if (ale->type == ANIMTYPE_NLAACTION) {
4986         tooltip = TIP_("Display action without any time remapping (when unpinned)");
4987       }
4988       else {
4989         /* TODO: there are no other tools which require the 'pinning' concept yet */
4990         tooltip = NULL;
4991       }
4992       break;
4993 
4994     default:
4995       tooltip = NULL;
4996       icon = 0;
4997       break;
4998   }
4999 
5000   /* type of button */
5001   if (usetoggle) {
5002     if (negflag) {
5003       butType = UI_BTYPE_ICON_TOGGLE_N;
5004     }
5005     else {
5006       butType = UI_BTYPE_ICON_TOGGLE;
5007     }
5008   }
5009   else {
5010     if (negflag) {
5011       butType = UI_BTYPE_TOGGLE_N;
5012     }
5013     else {
5014       butType = UI_BTYPE_TOGGLE;
5015     }
5016   }
5017   /* draw button for setting */
5018   if (ptr && flag) {
5019     switch (ptrsize) {
5020       case sizeof(int): /* integer pointer for setting */
5021         but = uiDefIconButBitI(block,
5022                                butType,
5023                                flag,
5024                                0,
5025                                icon,
5026                                xpos,
5027                                ypos,
5028                                ICON_WIDTH,
5029                                ICON_WIDTH,
5030                                ptr,
5031                                0,
5032                                0,
5033                                0,
5034                                0,
5035                                tooltip);
5036         break;
5037 
5038       case sizeof(short): /* short pointer for setting */
5039         but = uiDefIconButBitS(block,
5040                                butType,
5041                                flag,
5042                                0,
5043                                icon,
5044                                xpos,
5045                                ypos,
5046                                ICON_WIDTH,
5047                                ICON_WIDTH,
5048                                ptr,
5049                                0,
5050                                0,
5051                                0,
5052                                0,
5053                                tooltip);
5054         break;
5055 
5056       case sizeof(char): /* char pointer for setting */
5057         but = uiDefIconButBitC(block,
5058                                butType,
5059                                flag,
5060                                0,
5061                                icon,
5062                                xpos,
5063                                ypos,
5064                                ICON_WIDTH,
5065                                ICON_WIDTH,
5066                                ptr,
5067                                0,
5068                                0,
5069                                0,
5070                                0,
5071                                tooltip);
5072         break;
5073     }
5074 
5075     /* set call to send relevant notifiers and/or perform type-specific updates */
5076     if (but) {
5077       switch (setting) {
5078         /* settings needing flushing up/down hierarchy  */
5079         case ACHANNEL_SETTING_VISIBLE: /* Graph Editor - 'visibility' toggles */
5080         case ACHANNEL_SETTING_PROTECT: /* General - protection flags */
5081         case ACHANNEL_SETTING_MUTE:    /* General - muting flags */
5082         case ACHANNEL_SETTING_PINNED:  /* NLA Actions - 'map/nomap' */
5083         case ACHANNEL_SETTING_MOD_OFF:
5084         case ACHANNEL_SETTING_ALWAYS_VISIBLE:
5085           UI_but_funcN_set(but,
5086                            achannel_setting_flush_widget_cb,
5087                            MEM_dupallocN(ale),
5088                            POINTER_FROM_INT(setting));
5089           break;
5090 
5091         /* settings needing special attention */
5092         case ACHANNEL_SETTING_SOLO: /* NLA Tracks - Solo toggle */
5093           UI_but_funcN_set(but, achannel_nlatrack_solo_widget_cb, MEM_dupallocN(ale), NULL);
5094           break;
5095 
5096         /* no flushing */
5097         case ACHANNEL_SETTING_EXPAND: /* expanding - cannot flush,
5098                                        * otherwise all would open/close at once */
5099         default:
5100           UI_but_func_set(but, achannel_setting_widget_cb, NULL, NULL);
5101           break;
5102       }
5103 
5104       if ((ale->fcurve_owner_id != NULL && ID_IS_LINKED(ale->fcurve_owner_id)) ||
5105           (ale->id != NULL && ID_IS_LINKED(ale->id))) {
5106         if (setting != ACHANNEL_SETTING_EXPAND) {
5107           UI_but_flag_enable(but, UI_BUT_DISABLED);
5108         }
5109       }
5110     }
5111   }
5112 }
5113 
5114 /* Draw UI widgets the given channel */
ANIM_channel_draw_widgets(const bContext * C,bAnimContext * ac,bAnimListElem * ale,uiBlock * block,rctf * rect,size_t channel_index)5115 void ANIM_channel_draw_widgets(const bContext *C,
5116                                bAnimContext *ac,
5117                                bAnimListElem *ale,
5118                                uiBlock *block,
5119                                rctf *rect,
5120                                size_t channel_index)
5121 {
5122   const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
5123   View2D *v2d = &ac->region->v2d;
5124   float ymid;
5125   const short channel_height = round_fl_to_int(BLI_rctf_size_y(rect));
5126   const bool is_being_renamed = achannel_is_being_renamed(ac, acf, channel_index);
5127 
5128   /* sanity checks - don't draw anything */
5129   if (ELEM(NULL, acf, ale, block)) {
5130     return;
5131   }
5132 
5133   /* get initial offset */
5134   short offset = rect->xmin;
5135   if (acf->get_offset) {
5136     offset += acf->get_offset(ac, ale);
5137   }
5138 
5139   /* calculate appropriate y-coordinates for icon buttons */
5140   ymid = BLI_rctf_cent_y(rect) - 0.5f * ICON_WIDTH;
5141 
5142   /* no button backdrop behind icons */
5143   UI_block_emboss_set(block, UI_EMBOSS_NONE);
5144 
5145   /* step 1) draw expand widget ....................................... */
5146   if (acf->has_setting(ac, ale, ACHANNEL_SETTING_EXPAND)) {
5147     draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_EXPAND);
5148     offset += ICON_WIDTH;
5149   }
5150 
5151   /* step 2) draw icon ............................................... */
5152   if (acf->icon) {
5153     /* icon is not drawn here (not a widget) */
5154     offset += ICON_WIDTH;
5155   }
5156 
5157   /* step 3) draw special toggles  .................................
5158    * - in Graph Editor, checkboxes for visibility in curves area
5159    * - in NLA Editor, glowing dots for solo/not solo...
5160    * - in Grease Pencil mode, color swatches for layer color
5161    */
5162   if (ac->sl) {
5163     if ((ac->spacetype == SPACE_GRAPH) &&
5164         (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
5165          acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
5166       /* pin toggle  */
5167       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)) {
5168         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_ALWAYS_VISIBLE);
5169         offset += ICON_WIDTH;
5170       }
5171       /* visibility toggle  */
5172       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
5173         /* For F-curves, add the extra space for the color bands. */
5174         if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
5175           offset += GRAPH_ICON_VISIBILITY_OFFSET;
5176         }
5177         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
5178         offset += ICON_WIDTH;
5179       }
5180     }
5181     else if ((ac->spacetype == SPACE_NLA) && acf->has_setting(ac, ale, ACHANNEL_SETTING_SOLO)) {
5182       /* 'solo' setting for NLA Tracks */
5183       draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
5184       offset += ICON_WIDTH;
5185     }
5186   }
5187 
5188   /* step 4) draw text - check if renaming widget is in use... */
5189   if (is_being_renamed) {
5190     PointerRNA ptr = {NULL};
5191     PropertyRNA *prop = NULL;
5192 
5193     /* draw renaming widget if we can get RNA pointer for it
5194      * NOTE: property may only be available in some cases, even if we have
5195      *       a callback available (e.g. broken F-Curve rename)
5196      */
5197     if (acf->name_prop(ale, &ptr, &prop)) {
5198       const short margin_x = 3 * round_fl_to_int(UI_DPI_FAC);
5199       const short width = ac->region->winx - offset - (margin_x * 2);
5200       uiBut *but;
5201 
5202       UI_block_emboss_set(block, UI_EMBOSS);
5203 
5204       but = uiDefButR(block,
5205                       UI_BTYPE_TEXT,
5206                       1,
5207                       "",
5208                       offset + margin_x,
5209                       rect->ymin,
5210                       MAX2(width, RENAME_TEXT_MIN_WIDTH),
5211                       channel_height,
5212                       &ptr,
5213                       RNA_property_identifier(prop),
5214                       -1,
5215                       0,
5216                       0,
5217                       -1,
5218                       -1,
5219                       NULL);
5220 
5221       /* copy what outliner does here, see outliner_buttons */
5222       if (UI_but_active_only(C, ac->region, block, but) == false) {
5223         ac->ads->renameIndex = 0;
5224 
5225         /* send notifiers */
5226         WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_RENAME, NULL);
5227       }
5228 
5229       UI_block_emboss_set(block, UI_EMBOSS_NONE);
5230     }
5231     else {
5232       /* Cannot get property/cannot or rename for some reason, so clear rename index
5233        * so that this doesn't hang around, and the name can be drawn normally - T47492
5234        */
5235       ac->ads->renameIndex = 0;
5236       WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
5237     }
5238   }
5239 
5240   /* step 5) draw mute+protection toggles + (sliders) ....................... */
5241   /* reset offset - now goes from RHS of panel */
5242   offset = (int)rect->xmax;
5243 
5244   /* TODO: when drawing sliders, make those draw instead of these toggles if not enough space. */
5245   if (v2d && !is_being_renamed) {
5246     short draw_sliders = 0;
5247 
5248     /* check if we need to show the sliders */
5249     if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_GRAPH)) {
5250       switch (ac->spacetype) {
5251         case SPACE_ACTION: {
5252           SpaceAction *saction = (SpaceAction *)ac->sl;
5253           draw_sliders = (saction->flag & SACTION_SLIDERS);
5254           break;
5255         }
5256         case SPACE_GRAPH: {
5257           SpaceGraph *sipo = (SpaceGraph *)ac->sl;
5258           draw_sliders = (sipo->flag & SIPO_SLIDERS);
5259           break;
5260         }
5261       }
5262     }
5263 
5264     /* check if there's enough space for the toggles if the sliders are drawn too */
5265     if (!(draw_sliders) || (BLI_rcti_size_x(&v2d->mask) > ACHANNEL_BUTTON_WIDTH / 2)) {
5266       /* protect... */
5267       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PROTECT)) {
5268         offset -= ICON_WIDTH;
5269         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_PROTECT);
5270       }
5271       /* mute... */
5272       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MUTE)) {
5273         offset -= ICON_WIDTH;
5274         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MUTE);
5275       }
5276       if (ale->type == ANIMTYPE_GPLAYER) {
5277         /* Not technically "mute"
5278          * (in terms of anim channels, but this sets layer visibility instead). */
5279         offset -= ICON_WIDTH;
5280         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
5281       }
5282 
5283       /* modifiers disable */
5284       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
5285         offset -= ICON_WIDTH;
5286         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_MOD_OFF);
5287       }
5288 
5289       /* ----------- */
5290 
5291       /* pinned... */
5292       if (acf->has_setting(ac, ale, ACHANNEL_SETTING_PINNED)) {
5293         offset -= ICON_WIDTH;
5294         draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_PINNED);
5295       }
5296 
5297       /* NLA Action "pushdown" */
5298       if ((ale->type == ANIMTYPE_NLAACTION) && (ale->adt && ale->adt->action) &&
5299           !(ale->adt->flag & ADT_NLA_EDIT_ON)) {
5300         uiBut *but;
5301         PointerRNA *opptr_b;
5302 
5303         UI_block_emboss_set(block, UI_EMBOSS);
5304 
5305         offset -= UI_UNIT_X;
5306         but = uiDefIconButO(block,
5307                             UI_BTYPE_BUT,
5308                             "NLA_OT_action_pushdown",
5309                             WM_OP_INVOKE_DEFAULT,
5310                             ICON_NLA_PUSHDOWN,
5311                             offset,
5312                             ymid,
5313                             UI_UNIT_X,
5314                             UI_UNIT_X,
5315                             NULL);
5316 
5317         opptr_b = UI_but_operator_ptr_get(but);
5318         RNA_int_set(opptr_b, "channel_index", channel_index);
5319 
5320         UI_block_emboss_set(block, UI_EMBOSS_NONE);
5321       }
5322     }
5323 
5324     /* Draw slider:
5325      * - Even if we can draw sliders for this view, we must also check that the channel-type
5326      *   supports them (only only F-Curves really can support them for now).
5327      * - To make things easier, we use RNA-autobuts for this so that changes are
5328      *   reflected immediately, wherever they occurred.
5329      *   BUT, we don't use the layout engine, otherwise we'd get wrong alignment,
5330      *   and wouldn't be able to auto-keyframe.
5331      * - Slider should start before the toggles (if they're visible)
5332      *   to keep a clean line down the side.
5333      * - Sliders are always drawn in Shapekey mode now. Prior to this
5334      *   the SACTION_SLIDERS flag would be set when changing into Shapekey mode.
5335      */
5336     if (((draw_sliders) && ELEM(ale->type,
5337                                 ANIMTYPE_FCURVE,
5338                                 ANIMTYPE_NLACURVE,
5339                                 ANIMTYPE_SHAPEKEY,
5340                                 ANIMTYPE_GPLAYER)) ||
5341         ale->type == ANIMTYPE_SHAPEKEY) {
5342       /* adjust offset */
5343       /* TODO: make slider width dynamic,
5344        * so that they can be easier to use when the view is wide enough. */
5345       offset -= SLIDER_WIDTH;
5346 
5347       /* need backdrop behind sliders... */
5348       UI_block_emboss_set(block, UI_EMBOSS);
5349 
5350       if (ale->owner) { /* Slider using custom RNA Access ---------- */
5351         if (ale->type == ANIMTYPE_NLACURVE) {
5352           NlaStrip *strip = (NlaStrip *)ale->owner;
5353           FCurve *fcu = (FCurve *)ale->data;
5354           PointerRNA ptr;
5355           PropertyRNA *prop;
5356 
5357           /* create RNA pointers */
5358           RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, &ptr);
5359           prop = RNA_struct_find_property(&ptr, fcu->rna_path);
5360 
5361           /* create property slider */
5362           if (prop) {
5363             uiBut *but;
5364 
5365             /* Create the slider button,
5366              * and assign relevant callback to ensure keyframes are inserted. */
5367             but = uiDefAutoButR(block,
5368                                 &ptr,
5369                                 prop,
5370                                 fcu->array_index,
5371                                 "",
5372                                 ICON_NONE,
5373                                 offset,
5374                                 ymid,
5375                                 SLIDER_WIDTH,
5376                                 channel_height);
5377             UI_but_func_set(but, achannel_setting_slider_nla_curve_cb, ale->id, ale->data);
5378           }
5379         }
5380       }
5381       else if (ale->id) { /* Slider using RNA Access --------------- */
5382         PointerRNA id_ptr, ptr;
5383         PropertyRNA *prop;
5384         char *rna_path = NULL;
5385         int array_index = 0;
5386         short free_path = 0;
5387 
5388         /* get destination info */
5389         if (ale->type == ANIMTYPE_FCURVE) {
5390           FCurve *fcu = (FCurve *)ale->data;
5391 
5392           rna_path = fcu->rna_path;
5393           array_index = fcu->array_index;
5394         }
5395         else if (ale->type == ANIMTYPE_SHAPEKEY) {
5396           KeyBlock *kb = (KeyBlock *)ale->data;
5397           Key *key = (Key *)ale->id;
5398 
5399           rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
5400           free_path = 1;
5401         }
5402         /* Special for Grease Pencil Layer. */
5403         else if (ale->type == ANIMTYPE_GPLAYER) {
5404           bGPdata *gpd = (bGPdata *)ale->id;
5405           if ((gpd != NULL) && ((gpd->flag & GP_DATA_ANNOTATIONS) == 0)) {
5406             /* Reset slider offset, in order to add special gp icons. */
5407             offset += SLIDER_WIDTH;
5408 
5409             char *gp_rna_path = NULL;
5410             bGPDlayer *gpl = (bGPDlayer *)ale->data;
5411 
5412             /* Create the RNA pointers. */
5413             RNA_pointer_create(ale->id, &RNA_GPencilLayer, ale->data, &ptr);
5414             RNA_id_pointer_create(ale->id, &id_ptr);
5415             int icon;
5416 
5417             /* Layer onion skinning switch. */
5418             offset -= ICON_WIDTH;
5419             UI_block_emboss_set(block, UI_EMBOSS_NONE);
5420             prop = RNA_struct_find_property(&ptr, "use_onion_skinning");
5421             gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
5422             if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
5423               icon = (gpl->onion_flag & GP_LAYER_ONIONSKIN) ? ICON_ONIONSKIN_ON :
5424                                                               ICON_ONIONSKIN_OFF;
5425               uiDefAutoButR(block,
5426                             &ptr,
5427                             prop,
5428                             array_index,
5429                             "",
5430                             icon,
5431                             offset,
5432                             ymid,
5433                             ICON_WIDTH,
5434                             channel_height);
5435             }
5436             MEM_freeN(gp_rna_path);
5437 
5438             /* Mask Layer. */
5439             offset -= ICON_WIDTH;
5440             UI_block_emboss_set(block, UI_EMBOSS_NONE);
5441             prop = RNA_struct_find_property(&ptr, "use_mask_layer");
5442             gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
5443             if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
5444               icon = ICON_LAYER_ACTIVE;
5445               if (gpl->flag & GP_LAYER_USE_MASK) {
5446                 icon = ICON_MOD_MASK;
5447               }
5448               else {
5449                 icon = ICON_LAYER_ACTIVE;
5450               }
5451               uiDefAutoButR(block,
5452                             &ptr,
5453                             prop,
5454                             array_index,
5455                             "",
5456                             icon,
5457                             offset,
5458                             ymid,
5459                             ICON_WIDTH,
5460                             channel_height);
5461             }
5462             MEM_freeN(gp_rna_path);
5463 
5464             /* Layer opacity. */
5465             const short width = SLIDER_WIDTH * 0.6;
5466             offset -= width;
5467             UI_block_emboss_set(block, UI_EMBOSS);
5468             prop = RNA_struct_find_property(&ptr, "opacity");
5469             gp_rna_path = RNA_path_from_ID_to_property(&ptr, prop);
5470             if (RNA_path_resolve_property(&id_ptr, gp_rna_path, &ptr, &prop)) {
5471               uiDefAutoButR(block,
5472                             &ptr,
5473                             prop,
5474                             array_index,
5475                             "",
5476                             ICON_NONE,
5477                             offset,
5478                             ymid,
5479                             width,
5480                             channel_height);
5481             }
5482             MEM_freeN(gp_rna_path);
5483           }
5484         }
5485 
5486         /* Only if RNA-Path found. */
5487         if (rna_path) {
5488           /* get RNA pointer, and resolve the path */
5489           RNA_id_pointer_create(ale->id, &id_ptr);
5490 
5491           /* try to resolve the path */
5492           if (RNA_path_resolve_property(&id_ptr, rna_path, &ptr, &prop)) {
5493             uiBut *but;
5494 
5495             /* Create the slider button,
5496              * and assign relevant callback to ensure keyframes are inserted. */
5497             but = uiDefAutoButR(block,
5498                                 &ptr,
5499                                 prop,
5500                                 array_index,
5501                                 "",
5502                                 ICON_NONE,
5503                                 offset,
5504                                 ymid,
5505                                 SLIDER_WIDTH,
5506                                 channel_height);
5507 
5508             /* assign keyframing function according to slider type */
5509             if (ale->type == ANIMTYPE_SHAPEKEY) {
5510               UI_but_func_set(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
5511             }
5512             else {
5513               UI_but_func_set(but, achannel_setting_slider_cb, ale->id, ale->data);
5514             }
5515           }
5516 
5517           /* free the path if necessary */
5518           if (free_path) {
5519             MEM_freeN(rna_path);
5520           }
5521         }
5522       }
5523       else { /* Special Slider for stuff without RNA Access ---------- */
5524         /* TODO: only implement this case when we really need it... */
5525       }
5526     }
5527   }
5528 }
5529 
5530 /* *********************************************** */
5531