Blender  V3.3
anim_filter.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation, Joshua Leung. All rights reserved. */
3 
8 /* This file contains a system used to provide a layer of abstraction between sources
9  * of animation data and tools in Animation Editors. The method used here involves
10  * generating a list of edit structures which enable tools to naively perform the actions
11  * they require without all the boiler-plate associated with loops within loops and checking
12  * for cases to ignore.
13  *
14  * While this is primarily used for the Action/Dopesheet Editor (and its accessory modes),
15  * the Graph Editor also uses this for its channel list and for determining which curves
16  * are being edited. Likewise, the NLA Editor also uses this for its channel list and in
17  * its operators.
18  *
19  * NOTE: much of the original system this was based on was built before the creation of the RNA
20  * system. In future, it would be interesting to replace some parts of this code with RNA queries,
21  * however, RNA does not eliminate some of the boiler-plate reduction benefits presented by this
22  * system, so if any such work does occur, it should only be used for the internals used here...
23  *
24  * -- Joshua Leung, Dec 2008 (Last revision July 2009)
25  */
26 
27 #include <string.h>
28 
29 #include "DNA_anim_types.h"
30 #include "DNA_armature_types.h"
31 #include "DNA_brush_types.h"
32 #include "DNA_cachefile_types.h"
33 #include "DNA_camera_types.h"
34 #include "DNA_curves_types.h"
35 #include "DNA_gpencil_types.h"
36 #include "DNA_key_types.h"
37 #include "DNA_lattice_types.h"
38 #include "DNA_layer_types.h"
39 #include "DNA_light_types.h"
40 #include "DNA_linestyle_types.h"
41 #include "DNA_mask_types.h"
42 #include "DNA_material_types.h"
43 #include "DNA_mesh_types.h"
44 #include "DNA_meta_types.h"
45 #include "DNA_movieclip_types.h"
46 #include "DNA_node_types.h"
47 #include "DNA_object_force_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_particle_types.h"
50 #include "DNA_pointcloud_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_screen_types.h"
53 #include "DNA_sequence_types.h"
54 #include "DNA_simulation_types.h"
55 #include "DNA_space_types.h"
56 #include "DNA_speaker_types.h"
57 #include "DNA_userdef_types.h"
58 #include "DNA_volume_types.h"
59 #include "DNA_world_types.h"
60 
61 #include "MEM_guardedalloc.h"
62 
63 #include "BLI_alloca.h"
64 #include "BLI_blenlib.h"
65 #include "BLI_ghash.h"
66 #include "BLI_string.h"
67 #include "BLI_utildefines.h"
68 
69 #include "BKE_action.h"
70 #include "BKE_anim_data.h"
71 #include "BKE_collection.h"
72 #include "BKE_context.h"
73 #include "BKE_fcurve.h"
74 #include "BKE_fcurve_driver.h"
75 #include "BKE_global.h"
76 #include "BKE_key.h"
77 #include "BKE_layer.h"
78 #include "BKE_main.h"
79 #include "BKE_mask.h"
80 #include "BKE_material.h"
81 #include "BKE_modifier.h"
82 #include "BKE_node.h"
83 
84 #include "ED_anim_api.h"
85 #include "ED_markers.h"
86 
87 #include "SEQ_sequencer.h"
88 #include "SEQ_utils.h"
89 
90 #include "UI_resources.h" /* for TH_KEYFRAME_SCALE lookup */
91 
92 /* ************************************************************ */
93 /* Blender Context <-> Animation Context mapping */
94 
95 /* ----------- Private Stuff - General -------------------- */
96 
97 /* Get vertical scaling factor (i.e. typically used for keyframe size) */
99 {
100  bTheme *btheme = UI_GetTheme();
101 
102  /* grab scale factor directly from action editor setting
103  * NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally
104  * since it is a float, and the theme settings methods can only handle chars.
105  */
107 
108  /* clamp to avoid problems with uninitialized values... */
109  if (ac->yscale_fac < 0.1f) {
110  ac->yscale_fac = 1.0f;
111  }
112  // printf("yscale_fac = %f\n", ac->yscale_fac);
113 }
114 
115 /* ----------- Private Stuff - Action Editor ------------- */
116 
117 /* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
118 /* NOTE: there's a similar function in key.c #BKE_key_from_object. */
120 {
121  ViewLayer *view_layer = ac->view_layer;
122  Object *ob;
123  Key *key;
124 
125  ob = OBACT(view_layer);
126  if (ob == NULL) {
127  return NULL;
128  }
129 
130  /* XXX pinning is not available in 'ShapeKey' mode... */
131  // if (saction->pin) { return NULL; }
132 
133  /* shapekey data is stored with geometry data */
134  key = BKE_key_from_object(ob);
135 
136  if (key) {
137  if (key->type == KEY_RELATIVE) {
138  return key;
139  }
140  }
141 
142  return NULL;
143 }
144 
145 /* Get data being edited in Action Editor (depending on current 'mode') */
146 static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
147 {
148  /* get dopesheet */
149  ac->ads = &saction->ads;
150 
151  /* sync settings with current view status, then return appropriate data */
152  switch (saction->mode) {
153  case SACTCONT_ACTION: /* 'Action Editor' */
154  /* if not pinned, sync with active object */
155  if (/*saction->pin == 0*/ true) {
156  if (ac->obact && ac->obact->adt) {
157  saction->action = ac->obact->adt->action;
158  }
159  else {
160  saction->action = NULL;
161  }
162  }
163 
165  ac->data = saction->action;
166 
167  ac->mode = saction->mode;
168  return true;
169 
170  case SACTCONT_SHAPEKEY: /* 'ShapeKey Editor' */
172  ac->data = actedit_get_shapekeys(ac);
173 
174  /* if not pinned, sync with active object */
175  if (/*saction->pin == 0*/ true) {
176  Key *key = (Key *)ac->data;
177 
178  if (key && key->adt) {
179  saction->action = key->adt->action;
180  }
181  else {
182  saction->action = NULL;
183  }
184  }
185 
186  ac->mode = saction->mode;
187  return true;
188 
189  case SACTCONT_GPENCIL: /* Grease Pencil */ /* XXX review how this mode is handled... */
190  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
191  saction->ads.source = (ID *)ac->scene;
192 
194  ac->data = &saction->ads;
195 
196  ac->mode = saction->mode;
197  return true;
198 
199  case SACTCONT_CACHEFILE: /* Cache File */ /* XXX review how this mode is handled... */
200  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
201  saction->ads.source = (ID *)ac->scene;
202 
204  ac->data = &saction->ads;
205 
206  ac->mode = saction->mode;
207  return true;
208 
209  case SACTCONT_MASK: /* Mask */ /* XXX: review how this mode is handled. */
210  {
211  /* TODO: other methods to get the mask. */
212 #if 0
214  MovieClip *clip = ac->scene->clip;
215  struct Mask *mask = seq ? seq->mask : NULL;
216 #endif
217 
218  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
219  saction->ads.source = (ID *)ac->scene;
220 
221  ac->datatype = ANIMCONT_MASK;
222  ac->data = &saction->ads;
223 
224  ac->mode = saction->mode;
225  return true;
226  }
227 
228  case SACTCONT_DOPESHEET: /* DopeSheet */
229  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
230  saction->ads.source = (ID *)ac->scene;
231 
233  ac->data = &saction->ads;
234 
235  ac->mode = saction->mode;
236  return true;
237 
238  case SACTCONT_TIMELINE: /* Timeline */
239  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
240  saction->ads.source = (ID *)ac->scene;
241 
242  /* sync scene's "selected keys only" flag with our "only selected" flag
243  *
244  * XXX: This is a workaround for T55525. We shouldn't really be syncing the flags like this,
245  * but it's a simpler fix for now than also figuring out how the next/prev keyframe
246  * tools should work in the 3D View if we allowed full access to the timeline's
247  * dopesheet filters (i.e. we'd have to figure out where to host those settings,
248  * to be on a scene level like this flag currently is, along with several other unknowns).
249  */
250  if (ac->scene->flag & SCE_KEYS_NO_SELONLY) {
251  saction->ads.filterflag &= ~ADS_FILTER_ONLYSEL;
252  }
253  else {
254  saction->ads.filterflag |= ADS_FILTER_ONLYSEL;
255  }
256 
258  ac->data = &saction->ads;
259 
260  ac->mode = saction->mode;
261  return true;
262 
263  default: /* unhandled yet */
264  ac->datatype = ANIMCONT_NONE;
265  ac->data = NULL;
266 
267  ac->mode = -1;
268  return false;
269  }
270 }
271 
272 /* ----------- Private Stuff - Graph Editor ------------- */
273 
274 /* Get data being edited in Graph Editor (depending on current 'mode') */
276 {
277  /* init dopesheet data if non-existent (i.e. for old files) */
278  if (sipo->ads == NULL) {
279  sipo->ads = MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
280  sipo->ads->source = (ID *)ac->scene;
281  }
282  ac->ads = sipo->ads;
283 
284  /* set settings for Graph Editor - "Selected = Editable" */
285  if (sipo->flag & SIPO_SELCUVERTSONLY) {
287  }
288  else {
289  sipo->ads->filterflag &= ~ADS_FILTER_SELEDIT;
290  }
291 
292  /* sync settings with current view status, then return appropriate data */
293  switch (sipo->mode) {
294  case SIPO_MODE_ANIMATION: /* Animation F-Curve Editor */
295  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
296  sipo->ads->source = (ID *)ac->scene;
298 
300  ac->data = sipo->ads;
301 
302  ac->mode = sipo->mode;
303  return true;
304 
305  case SIPO_MODE_DRIVERS: /* Driver F-Curve Editor */
306  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
307  sipo->ads->source = (ID *)ac->scene;
309 
311  ac->data = sipo->ads;
312 
313  ac->mode = sipo->mode;
314  return true;
315 
316  default: /* unhandled yet */
317  ac->datatype = ANIMCONT_NONE;
318  ac->data = NULL;
319 
320  ac->mode = -1;
321  return false;
322  }
323 }
324 
325 /* ----------- Private Stuff - NLA Editor ------------- */
326 
327 /* Get data being edited in Graph Editor (depending on current 'mode') */
329 {
330  /* init dopesheet data if non-existent (i.e. for old files) */
331  if (snla->ads == NULL) {
332  snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
333  }
334  ac->ads = snla->ads;
335 
336  /* sync settings with current view status, then return appropriate data */
337  /* update scene-pointer (no need to check for pinning yet, as not implemented) */
338  snla->ads->source = (ID *)ac->scene;
340 
341  ac->datatype = ANIMCONT_NLA;
342  ac->data = snla->ads;
343 
344  return true;
345 }
346 
347 /* ----------- Public API --------------- */
348 
350 {
351  SpaceLink *sl = ac->sl;
352  bool ok = false;
353 
354  /* context depends on editor we are currently in */
355  if (sl) {
356  switch (ac->spacetype) {
357  case SPACE_ACTION: {
358  SpaceAction *saction = (SpaceAction *)sl;
359  ok = actedit_get_context(ac, saction);
360  break;
361  }
362  case SPACE_GRAPH: {
363  SpaceGraph *sipo = (SpaceGraph *)sl;
364  ok = graphedit_get_context(ac, sipo);
365  break;
366  }
367  case SPACE_NLA: {
368  SpaceNla *snla = (SpaceNla *)sl;
369  ok = nlaedit_get_context(ac, snla);
370  break;
371  }
372  }
373  }
374 
375  /* check if there's any valid data */
376  return (ok && ac->data);
377 }
378 
380 {
381  Main *bmain = CTX_data_main(C);
383  ARegion *region = CTX_wm_region(C);
386 
387  /* clear old context info */
388  if (ac == NULL) {
389  return false;
390  }
391  memset(ac, 0, sizeof(bAnimContext));
392 
393  /* get useful default context settings from context */
394  ac->bmain = bmain;
395  ac->scene = scene;
396  if (scene) {
398  }
401  ac->obact = (ac->view_layer->basact) ? ac->view_layer->basact->object : NULL;
402  ac->area = area;
403  ac->region = region;
404  ac->sl = sl;
405  ac->spacetype = (area) ? area->spacetype : 0;
406  ac->regiontype = (region) ? region->regiontype : 0;
407 
408  /* Initialize default y-scale factor. */
410 
411  /* get data context info */
412  /* XXX: if the below fails, try to grab this info from context instead...
413  * (to allow for scripting). */
415 }
416 
418 {
420 }
421 
422 /* ************************************************************ */
423 /* Blender Data <-- Filter --> Channels to be operated on */
424 
425 /* macros to use before/after getting the sub-channels of some channel,
426  * to abstract away some of the tricky logic involved
427  *
428  * cases:
429  * 1) Graph Edit main area (just data) OR channels visible in Channel List
430  * 2) If not showing channels, we're only interested in the data (Action Editor's editing)
431  * 3) We don't care what data, we just care there is some (so that a collapsed
432  * channel can be kept around). No need to clear channels-flag in order to
433  * keep expander channels with no sub-data out, as those cases should get
434  * dealt with by the recursive detection idiom in place.
435  *
436  * Implementation NOTE:
437  * YES the _doSubChannels variable is NOT read anywhere. BUT, this is NOT an excuse
438  * to go steamrolling the logic into a single-line expression as from experience,
439  * those are notoriously difficult to read + debug when extending later on. The code
440  * below is purposefully laid out so that each case noted above corresponds clearly to
441  * one case below.
442  */
443 #define BEGIN_ANIMFILTER_SUBCHANNELS(expanded_check) \
444  { \
445  int _filter = filter_mode; \
446  short _doSubChannels = 0; \
447  if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || (expanded_check)) { \
448  _doSubChannels = 1; \
449  } \
450  else if (!(filter_mode & ANIMFILTER_LIST_CHANNELS)) { \
451  _doSubChannels = 2; \
452  } \
453  else { \
454  filter_mode |= ANIMFILTER_TMP_PEEK; \
455  } \
456 \
457  { \
458  (void)_doSubChannels; \
459  }
460 /* ... standard sub-channel filtering can go on here now ... */
461 #define END_ANIMFILTER_SUBCHANNELS \
462  filter_mode = _filter; \
463  } \
464  (void)0
465 
466 /* ............................... */
467 
468 /* quick macro to test if AnimData is usable */
469 #define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
470 
471 /* quick macro to test if AnimData is usable for drivers */
472 #define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
473 
474 /* quick macro to test if AnimData is usable for NLA */
475 #define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
476 
512 #define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk) \
513  { \
514  if ((id)->adt) { \
515  if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || \
516  !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) { \
517  if (filter_mode & ANIMFILTER_ANIMDATA) { \
518  adtOk \
519  } \
520  else if (ads->filterflag & ADS_FILTER_ONLYNLA) { \
521  if (ANIMDATA_HAS_NLA(id)) { \
522  nlaOk \
523  } \
524  else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_KEYS(id)) { \
525  nlaOk \
526  } \
527  } \
528  else if (ads->filterflag & ADS_FILTER_ONLYDRIVERS) { \
529  if (ANIMDATA_HAS_DRIVERS(id)) { \
530  driversOk \
531  } \
532  } \
533  else { \
534  if (ANIMDATA_HAS_NLA(id)) { \
535  nlaKeysOk \
536  } \
537  if (ANIMDATA_HAS_KEYS(id)) { \
538  keysOk \
539  } \
540  } \
541  } \
542  } \
543  } \
544  (void)0
545 
546 /* ............................... */
547 
556 #define ANIMCHANNEL_NEW_CHANNEL_FULL( \
557  channel_data, channel_type, owner_id, fcurve_owner_id, ale_statement) \
558  if (filter_mode & ANIMFILTER_TMP_PEEK) { \
559  return 1; \
560  } \
561  { \
562  bAnimListElem *ale = make_new_animlistelem( \
563  channel_data, channel_type, (ID *)owner_id, fcurve_owner_id); \
564  if (ale) { \
565  BLI_addtail(anim_data, ale); \
566  items++; \
567  ale_statement \
568  } \
569  } \
570  (void)0
571 
572 #define ANIMCHANNEL_NEW_CHANNEL(channel_data, channel_type, owner_id, fcurve_owner_id) \
573  ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, fcurve_owner_id, {})
574 
575 /* ............................... */
576 
577 /* quick macro to test if an anim-channel representing an AnimData block is suitably active */
578 #define ANIMCHANNEL_ACTIVEOK(ale) \
579  (!(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE))
580 
581 /* Quick macro to test if an anim-channel (F-Curve, Group, etc.)
582  * is selected in an acceptable way. */
583 #define ANIMCHANNEL_SELOK(test_func) \
584  (!(filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) || \
585  ((filter_mode & ANIMFILTER_SEL) && test_func) || \
586  ((filter_mode & ANIMFILTER_UNSEL) && test_func == 0))
587 
588 /* quick macro to test if an anim-channel (F-Curve) is selected ok for editing purposes
589  * - _SELEDIT means that only selected curves will have visible+editable keyframes
590  *
591  * checks here work as follows:
592  * 1) seledit off - don't need to consider the implications of this option
593  * 2) foredit off - we're not considering editing, so channel is ok still
594  * 3) test_func (i.e. selection test) - only if selected, this test will pass
595  */
596 #define ANIMCHANNEL_SELEDITOK(test_func) \
597  (!(filter_mode & ANIMFILTER_SELEDIT) || !(filter_mode & ANIMFILTER_FOREDIT) || (test_func))
598 
599 /* ----------- 'Private' Stuff --------------- */
600 
601 /* this function allocates memory for a new bAnimListElem struct for the
602  * provided animation channel-data.
603  */
605  short datatype,
606  ID *owner_id,
607  ID *fcurve_owner_id)
608 {
609  bAnimListElem *ale = NULL;
610 
611  /* only allocate memory if there is data to convert */
612  if (data) {
613  /* allocate and set generic data */
614  ale = MEM_callocN(sizeof(bAnimListElem), "bAnimListElem");
615 
616  ale->data = data;
617  ale->type = datatype;
618 
619  ale->id = owner_id;
620  ale->adt = BKE_animdata_from_id(owner_id);
621  ale->fcurve_owner_id = fcurve_owner_id;
622 
623  /* do specifics */
624  switch (datatype) {
625  case ANIMTYPE_SUMMARY: {
626  /* Nothing to include for now... this is just a dummy wrapper around
627  * all the other channels in the DopeSheet, and gets included at the start of the list. */
628  ale->key_data = NULL;
629  ale->datatype = ALE_ALL;
630  break;
631  }
632  case ANIMTYPE_SCENE: {
633  Scene *sce = (Scene *)data;
634 
635  ale->flag = sce->flag;
636 
637  ale->key_data = sce;
638  ale->datatype = ALE_SCE;
639 
640  ale->adt = BKE_animdata_from_id(data);
641  break;
642  }
643  case ANIMTYPE_OBJECT: {
644  Base *base = (Base *)data;
645  Object *ob = base->object;
646 
647  ale->flag = ob->flag;
648 
649  ale->key_data = ob;
650  ale->datatype = ALE_OB;
651 
652  ale->adt = BKE_animdata_from_id(&ob->id);
653  break;
654  }
655  case ANIMTYPE_FILLACTD: {
656  bAction *act = (bAction *)data;
657 
658  ale->flag = act->flag;
659 
660  ale->key_data = act;
661  ale->datatype = ALE_ACT;
662  break;
663  }
664  case ANIMTYPE_FILLDRIVERS: {
665  AnimData *adt = (AnimData *)data;
666 
667  ale->flag = adt->flag;
668 
669  /* XXX drivers don't show summary for now. */
670  ale->key_data = NULL;
671  ale->datatype = ALE_NONE;
672  break;
673  }
674  case ANIMTYPE_DSMAT: {
675  Material *ma = (Material *)data;
676  AnimData *adt = ma->adt;
677 
678  ale->flag = FILTER_MAT_OBJD(ma);
679 
680  ale->key_data = (adt) ? adt->action : NULL;
681  ale->datatype = ALE_ACT;
682 
683  ale->adt = BKE_animdata_from_id(data);
684  break;
685  }
686  case ANIMTYPE_DSLAM: {
687  Light *la = (Light *)data;
688  AnimData *adt = la->adt;
689 
690  ale->flag = FILTER_LAM_OBJD(la);
691 
692  ale->key_data = (adt) ? adt->action : NULL;
693  ale->datatype = ALE_ACT;
694 
695  ale->adt = BKE_animdata_from_id(data);
696  break;
697  }
698  case ANIMTYPE_DSCAM: {
699  Camera *ca = (Camera *)data;
700  AnimData *adt = ca->adt;
701 
702  ale->flag = FILTER_CAM_OBJD(ca);
703 
704  ale->key_data = (adt) ? adt->action : NULL;
705  ale->datatype = ALE_ACT;
706 
707  ale->adt = BKE_animdata_from_id(data);
708  break;
709  }
710  case ANIMTYPE_DSCACHEFILE: {
711  CacheFile *cache_file = (CacheFile *)data;
712  AnimData *adt = cache_file->adt;
713 
714  ale->flag = FILTER_CACHEFILE_OBJD(cache_file);
715 
716  ale->key_data = (adt) ? adt->action : NULL;
717  ale->datatype = ALE_ACT;
718 
719  ale->adt = BKE_animdata_from_id(data);
720  break;
721  }
722  case ANIMTYPE_DSCUR: {
723  Curve *cu = (Curve *)data;
724  AnimData *adt = cu->adt;
725 
726  ale->flag = FILTER_CUR_OBJD(cu);
727 
728  ale->key_data = (adt) ? adt->action : NULL;
729  ale->datatype = ALE_ACT;
730 
731  ale->adt = BKE_animdata_from_id(data);
732  break;
733  }
734  case ANIMTYPE_DSARM: {
735  bArmature *arm = (bArmature *)data;
736  AnimData *adt = arm->adt;
737 
738  ale->flag = FILTER_ARM_OBJD(arm);
739 
740  ale->key_data = (adt) ? adt->action : NULL;
741  ale->datatype = ALE_ACT;
742 
743  ale->adt = BKE_animdata_from_id(data);
744  break;
745  }
746  case ANIMTYPE_DSMESH: {
747  Mesh *me = (Mesh *)data;
748  AnimData *adt = me->adt;
749 
750  ale->flag = FILTER_MESH_OBJD(me);
751 
752  ale->key_data = (adt) ? adt->action : NULL;
753  ale->datatype = ALE_ACT;
754 
755  ale->adt = BKE_animdata_from_id(data);
756  break;
757  }
758  case ANIMTYPE_DSLAT: {
759  Lattice *lt = (Lattice *)data;
760  AnimData *adt = lt->adt;
761 
762  ale->flag = FILTER_LATTICE_OBJD(lt);
763 
764  ale->key_data = (adt) ? adt->action : NULL;
765  ale->datatype = ALE_ACT;
766 
767  ale->adt = BKE_animdata_from_id(data);
768  break;
769  }
770  case ANIMTYPE_DSSPK: {
771  Speaker *spk = (Speaker *)data;
772  AnimData *adt = spk->adt;
773 
774  ale->flag = FILTER_SPK_OBJD(spk);
775 
776  ale->key_data = (adt) ? adt->action : NULL;
777  ale->datatype = ALE_ACT;
778 
779  ale->adt = BKE_animdata_from_id(data);
780  break;
781  }
782  case ANIMTYPE_DSHAIR: {
783  Curves *curves = (Curves *)data;
784  AnimData *adt = curves->adt;
785 
787 
788  ale->key_data = (adt) ? adt->action : NULL;
789  ale->datatype = ALE_ACT;
790 
791  ale->adt = BKE_animdata_from_id(data);
792  break;
793  }
794  case ANIMTYPE_DSPOINTCLOUD: {
795  PointCloud *pointcloud = (PointCloud *)data;
796  AnimData *adt = pointcloud->adt;
797 
798  ale->flag = FILTER_POINTS_OBJD(pointcloud);
799 
800  ale->key_data = (adt) ? adt->action : NULL;
801  ale->datatype = ALE_ACT;
802 
803  ale->adt = BKE_animdata_from_id(data);
804  break;
805  }
806  case ANIMTYPE_DSVOLUME: {
807  Volume *volume = (Volume *)data;
808  AnimData *adt = volume->adt;
809 
810  ale->flag = FILTER_VOLUME_OBJD(volume);
811 
812  ale->key_data = (adt) ? adt->action : NULL;
813  ale->datatype = ALE_ACT;
814 
815  ale->adt = BKE_animdata_from_id(data);
816  break;
817  }
818  case ANIMTYPE_DSSIMULATION: {
821 
823 
824  ale->key_data = (adt) ? adt->action : NULL;
825  ale->datatype = ALE_ACT;
826 
827  ale->adt = BKE_animdata_from_id(data);
828  break;
829  }
830  case ANIMTYPE_DSSKEY: {
831  Key *key = (Key *)data;
832  AnimData *adt = key->adt;
833 
834  ale->flag = FILTER_SKE_OBJD(key);
835 
836  ale->key_data = (adt) ? adt->action : NULL;
837  ale->datatype = ALE_ACT;
838 
839  ale->adt = BKE_animdata_from_id(data);
840  break;
841  }
842  case ANIMTYPE_DSWOR: {
843  World *wo = (World *)data;
844  AnimData *adt = wo->adt;
845 
846  ale->flag = FILTER_WOR_SCED(wo);
847 
848  ale->key_data = (adt) ? adt->action : NULL;
849  ale->datatype = ALE_ACT;
850 
851  ale->adt = BKE_animdata_from_id(data);
852  break;
853  }
854  case ANIMTYPE_DSNTREE: {
856  AnimData *adt = ntree->adt;
857 
858  ale->flag = FILTER_NTREE_DATA(ntree);
859 
860  ale->key_data = (adt) ? adt->action : NULL;
861  ale->datatype = ALE_ACT;
862 
863  ale->adt = BKE_animdata_from_id(data);
864  break;
865  }
866  case ANIMTYPE_DSLINESTYLE: {
869 
870  ale->flag = FILTER_LS_SCED(linestyle);
871 
872  ale->key_data = (adt) ? adt->action : NULL;
873  ale->datatype = ALE_ACT;
874 
875  ale->adt = BKE_animdata_from_id(data);
876  break;
877  }
878  case ANIMTYPE_DSPART: {
879  ParticleSettings *part = (ParticleSettings *)ale->data;
880  AnimData *adt = part->adt;
881 
882  ale->flag = FILTER_PART_OBJD(part);
883 
884  ale->key_data = (adt) ? adt->action : NULL;
885  ale->datatype = ALE_ACT;
886 
887  ale->adt = BKE_animdata_from_id(data);
888  break;
889  }
890  case ANIMTYPE_DSTEX: {
891  Tex *tex = (Tex *)data;
892  AnimData *adt = tex->adt;
893 
894  ale->flag = FILTER_TEX_DATA(tex);
895 
896  ale->key_data = (adt) ? adt->action : NULL;
897  ale->datatype = ALE_ACT;
898 
899  ale->adt = BKE_animdata_from_id(data);
900  break;
901  }
902  case ANIMTYPE_DSGPENCIL: {
903  bGPdata *gpd = (bGPdata *)data;
904  AnimData *adt = gpd->adt;
905 
906  /* NOTE: we just reuse the same expand filter for this case */
907  ale->flag = EXPANDED_GPD(gpd);
908 
909  /* XXX: currently, this is only used for access to its animation data */
910  ale->key_data = (adt) ? adt->action : NULL;
911  ale->datatype = ALE_ACT;
912 
913  ale->adt = BKE_animdata_from_id(data);
914  break;
915  }
916  case ANIMTYPE_DSMCLIP: {
917  MovieClip *clip = (MovieClip *)data;
918  AnimData *adt = clip->adt;
919 
920  ale->flag = EXPANDED_MCLIP(clip);
921 
922  ale->key_data = (adt) ? adt->action : NULL;
923  ale->datatype = ALE_ACT;
924 
925  ale->adt = BKE_animdata_from_id(data);
926  break;
927  }
928  case ANIMTYPE_NLACONTROLS: {
929  AnimData *adt = (AnimData *)data;
930 
931  ale->flag = adt->flag;
932 
933  ale->key_data = NULL;
934  ale->datatype = ALE_NONE;
935  break;
936  }
937  case ANIMTYPE_GROUP: {
938  bActionGroup *agrp = (bActionGroup *)data;
939 
940  ale->flag = agrp->flag;
941 
942  ale->key_data = NULL;
943  ale->datatype = ALE_GROUP;
944  break;
945  }
946  case ANIMTYPE_FCURVE:
947  case ANIMTYPE_NLACURVE: /* practically the same as ANIMTYPE_FCURVE.
948  * Differences are applied post-creation */
949  {
950  FCurve *fcu = (FCurve *)data;
951 
952  ale->flag = fcu->flag;
953 
954  ale->key_data = fcu;
955  ale->datatype = ALE_FCURVE;
956  break;
957  }
958  case ANIMTYPE_SHAPEKEY: {
959  KeyBlock *kb = (KeyBlock *)data;
960  Key *key = (Key *)ale->id;
961 
962  ale->flag = kb->flag;
963 
964  /* whether we have keyframes depends on whether there is a Key block to find it from */
965  if (key) {
966  /* index of shapekey is defined by place in key's list */
967  ale->index = BLI_findindex(&key->block, kb);
968 
969  /* the corresponding keyframes are from the animdata */
970  if (ale->adt && ale->adt->action) {
971  bAction *act = ale->adt->action;
972  char *rna_path = BKE_keyblock_curval_rnapath_get(key, kb);
973 
974  /* try to find the F-Curve which corresponds to this exactly,
975  * then free the MEM_alloc'd string
976  */
977  if (rna_path) {
978  ale->key_data = (void *)BKE_fcurve_find(&act->curves, rna_path, 0);
979  MEM_freeN(rna_path);
980  }
981  }
982  ale->datatype = (ale->key_data) ? ALE_FCURVE : ALE_NONE;
983  }
984  break;
985  }
986  case ANIMTYPE_GPLAYER: {
987  bGPDlayer *gpl = (bGPDlayer *)data;
988 
989  ale->flag = gpl->flag;
990 
991  ale->key_data = NULL;
992  ale->datatype = ALE_GPFRAME;
993  break;
994  }
995  case ANIMTYPE_MASKLAYER: {
996  MaskLayer *masklay = (MaskLayer *)data;
997 
998  ale->flag = masklay->flag;
999 
1000  ale->key_data = NULL;
1001  ale->datatype = ALE_MASKLAY;
1002  break;
1003  }
1004  case ANIMTYPE_NLATRACK: {
1005  NlaTrack *nlt = (NlaTrack *)data;
1006 
1007  ale->flag = nlt->flag;
1008 
1009  ale->key_data = &nlt->strips;
1010  ale->datatype = ALE_NLASTRIP;
1011  break;
1012  }
1013  case ANIMTYPE_NLAACTION: {
1014  /* nothing to include for now... nothing editable from NLA-perspective here */
1015  ale->key_data = NULL;
1016  ale->datatype = ALE_NONE;
1017  break;
1018  }
1019  }
1020  }
1021 
1022  /* return created datatype */
1023  return ale;
1024 }
1025 
1026 /* ----------------------------------------- */
1027 
1028 /* 'Only Selected' selected data and/or 'Include Hidden' filtering
1029  * NOTE: when this function returns true, the F-Curve is to be skipped
1030  */
1031 static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
1032 {
1033  if (fcu->grp != NULL && fcu->grp->flag & ADT_CURVES_ALWAYS_VISIBLE) {
1034  return false;
1035  }
1036  /* hidden items should be skipped if we only care about visible data,
1037  * but we aren't interested in hidden stuff */
1038  const bool skip_hidden = (filter_mode & ANIMFILTER_DATA_VISIBLE) &&
1040 
1041  if (GS(owner_id->name) == ID_OB) {
1042  Object *ob = (Object *)owner_id;
1043  bPoseChannel *pchan = NULL;
1044  char bone_name[sizeof(pchan->name)];
1045 
1046  /* Only consider if F-Curve involves `pose.bones`. */
1047  if (fcu->rna_path &&
1048  BLI_str_quoted_substr(fcu->rna_path, "pose.bones[", bone_name, sizeof(bone_name))) {
1049  /* Get bone-name, and check if this bone is selected. */
1050  pchan = BKE_pose_channel_find_name(ob->pose, bone_name);
1051 
1052  /* check whether to continue or skip */
1053  if (pchan && pchan->bone) {
1054  /* If only visible channels,
1055  * skip if bone not visible unless user wants channels from hidden data too. */
1056  if (skip_hidden) {
1057  bArmature *arm = (bArmature *)ob->data;
1058 
1059  /* skipping - not visible on currently visible layers */
1060  if ((arm->layer & pchan->bone->layer) == 0) {
1061  return true;
1062  }
1063  /* skipping - is currently hidden */
1064  if (pchan->bone->flag & BONE_HIDDEN_P) {
1065  return true;
1066  }
1067  }
1068 
1069  /* can only add this F-Curve if it is selected */
1070  if (ads->filterflag & ADS_FILTER_ONLYSEL) {
1071  if ((pchan->bone->flag & BONE_SELECTED) == 0) {
1072  return true;
1073  }
1074  }
1075  }
1076  }
1077  }
1078  else if (GS(owner_id->name) == ID_SCE) {
1079  Scene *scene = (Scene *)owner_id;
1080  Sequence *seq = NULL;
1081  char seq_name[sizeof(seq->name)];
1082 
1083  /* Only consider if F-Curve involves `sequence_editor.sequences`. */
1084  if (fcu->rna_path &&
1085  BLI_str_quoted_substr(fcu->rna_path, "sequences_all[", seq_name, sizeof(seq_name))) {
1086  /* Get strip name, and check if this strip is selected. */
1087  Editing *ed = SEQ_editing_get(scene);
1088  if (ed) {
1089  seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false);
1090  }
1091 
1092  /* Can only add this F-Curve if it is selected. */
1093  if (ads->filterflag & ADS_FILTER_ONLYSEL) {
1094 
1095  /* NOTE(@campbellbarton): The `seq == NULL` check doesn't look right
1096  * (compared to other checks in this function which skip data that can't be found).
1097  *
1098  * This is done since the search for sequence strips doesn't use a global lookup:
1099  * - Nested meta-strips are excluded.
1100  * - When inside a meta-strip - strips outside the meta-strip excluded.
1101  *
1102  * Instead, only the strips directly visible to the user are considered for selection.
1103  * The NULL check here means everything else is considered unselected and is not shown.
1104  *
1105  * There is a subtle difference between nodes, pose-bones ... etc
1106  * since data-paths that point to missing strips are not shown.
1107  * If this is an important difference, the NULL case could perform a global lookup,
1108  * only returning `true` if the sequence strip exists elsewhere
1109  * (ignoring it's selection state). */
1110  if (seq == NULL) {
1111  return true;
1112  }
1113 
1114  if ((seq->flag & SELECT) == 0) {
1115  return true;
1116  }
1117  }
1118  }
1119  }
1120  else if (GS(owner_id->name) == ID_NT) {
1121  bNodeTree *ntree = (bNodeTree *)owner_id;
1122  bNode *node = NULL;
1123  char node_name[sizeof(node->name)];
1124 
1125  /* Check for selected nodes. */
1126  if (fcu->rna_path &&
1127  (BLI_str_quoted_substr(fcu->rna_path, "nodes[", node_name, sizeof(node_name)))) {
1128  /* Get strip name, and check if this strip is selected. */
1129  node = nodeFindNodebyName(ntree, node_name);
1130 
1131  /* Can only add this F-Curve if it is selected. */
1132  if (node) {
1133  if (ads->filterflag & ADS_FILTER_ONLYSEL) {
1134  if ((node->flag & NODE_SELECT) == 0) {
1135  return true;
1136  }
1137  }
1138  }
1139  }
1140  }
1141 
1142  return false;
1143 }
1144 
1145 /* Helper for name-based filtering - Perform "partial/fuzzy matches" (as in 80a7efd) */
1146 static bool name_matches_dopesheet_filter(bDopeSheet *ads, char *name)
1147 {
1148  if (ads->flag & ADS_FLAG_FUZZY_NAMES) {
1149  /* full fuzzy, multi-word, case insensitive matches */
1150  const size_t str_len = strlen(ads->searchstr);
1151  const int words_max = BLI_string_max_possible_word_count(str_len);
1152 
1153  int(*words)[2] = BLI_array_alloca(words, words_max);
1154  const int words_len = BLI_string_find_split_words(
1155  ads->searchstr, str_len, ' ', words, words_max);
1156  bool found = false;
1157 
1158  /* match name against all search words */
1159  for (int index = 0; index < words_len; index++) {
1160  if (BLI_strncasestr(name, ads->searchstr + words[index][0], words[index][1])) {
1161  found = true;
1162  break;
1163  }
1164  }
1165 
1166  /* if we have a match somewhere, this returns true */
1167  return ((ads->flag & ADS_FLAG_INVERT_FILTER) == 0) ? found : !found;
1168  }
1169  /* fallback/default - just case insensitive, but starts from start of word */
1170  bool found = BLI_strcasestr(name, ads->searchstr) != NULL;
1171  return ((ads->flag & ADS_FLAG_INVERT_FILTER) == 0) ? found : !found;
1172 }
1173 
1174 /* (Display-)Name-based F-Curve filtering
1175  * NOTE: when this function returns true, the F-Curve is to be skipped
1176  */
1178  bDopeSheet *ads, FCurve *fcu, eAnim_ChannelType channel_type, void *owner, ID *owner_id)
1179 {
1180  bAnimListElem ale_dummy = {NULL};
1181  const bAnimChannelType *acf;
1182 
1183  /* create a dummy wrapper for the F-Curve, so we can get typeinfo for it */
1184  ale_dummy.type = channel_type;
1185  ale_dummy.owner = owner;
1186  ale_dummy.id = owner_id;
1187  ale_dummy.data = fcu;
1188 
1189  /* get type info for channel */
1190  acf = ANIM_channel_get_typeinfo(&ale_dummy);
1191  if (acf && acf->name) {
1192  char name[256]; /* hopefully this will be enough! */
1193 
1194  /* get name */
1195  acf->name(&ale_dummy, name);
1196 
1197  /* check for partial match with the match string, assuming case insensitive filtering
1198  * if match, this channel shouldn't be ignored!
1199  */
1200  return !name_matches_dopesheet_filter(ads, name);
1201  }
1202 
1203  /* just let this go... */
1204  return true;
1205 }
1206 
1212 static bool fcurve_has_errors(const FCurve *fcu)
1213 {
1214  /* F-Curve disabled - path eval error */
1215  if (fcu->flag & FCURVE_DISABLED) {
1216  return true;
1217  }
1218 
1219  /* driver? */
1220  if (fcu->driver) {
1221  const ChannelDriver *driver = fcu->driver;
1222  DriverVar *dvar;
1223 
1224  /* error flag on driver usually means that there is an error
1225  * BUT this may not hold with PyDrivers as this flag gets cleared
1226  * if no critical errors prevent the driver from working...
1227  */
1228  if (driver->flag & DRIVER_FLAG_INVALID) {
1229  return true;
1230  }
1231 
1232  /* check variables for other things that need linting... */
1233  /* TODO: maybe it would be more efficient just to have a quick flag for this? */
1234  for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
1236  if (dtar->flag & DTAR_FLAG_INVALID) {
1237  return true;
1238  }
1239  }
1241  }
1242  }
1243 
1244  /* no errors found */
1245  return false;
1246 }
1247 
1248 /* find the next F-Curve that is usable for inclusion */
1250  FCurve *first,
1251  eAnim_ChannelType channel_type,
1252  int filter_mode,
1253  void *owner,
1254  ID *owner_id)
1255 {
1256  bActionGroup *grp = (channel_type == ANIMTYPE_FCURVE) ? owner : NULL;
1257  FCurve *fcu = NULL;
1258 
1259  /* Loop over F-Curves - assume that the caller of this has already checked
1260  * that these should be included.
1261  * NOTE: we need to check if the F-Curves belong to the same group,
1262  * as this gets called for groups too...
1263  */
1264  for (fcu = first; ((fcu) && (fcu->grp == grp)); fcu = fcu->next) {
1265  /* special exception for Pose-Channel/Sequence-Strip/Node Based F-Curves:
1266  * - The 'Only Selected' and 'Include Hidden' data filters should be applied to sub-ID data
1267  * which can be independently selected/hidden, such as Pose-Channels, Sequence Strips,
1268  * and Nodes. Since these checks were traditionally done as first check for objects,
1269  * we do the same here.
1270  * - We currently use an 'approximate' method for getting these F-Curves that doesn't require
1271  * carefully checking the entire path.
1272  * - This will also affect things like Drivers, and also works for Bone Constraints.
1273  */
1274  if (ads && owner_id) {
1275  if ((filter_mode & ANIMFILTER_TMP_IGNORE_ONLYSEL) == 0) {
1276  if ((ads->filterflag & ADS_FILTER_ONLYSEL) ||
1277  (ads->filterflag & ADS_FILTER_INCL_HIDDEN) == 0) {
1278  if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode)) {
1279  continue;
1280  }
1281  }
1282  }
1283  }
1284 
1285  /* only include if visible (Graph Editor check, not channels check) */
1286  if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
1287  /* only work with this channel and its subchannels if it is editable */
1288  if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
1289  /* Only include this curve if selected in a way consistent
1290  * with the filtering requirements. */
1292  /* only include if this curve is active */
1293  if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
1294  /* name based filtering... */
1295  if (((ads) && (ads->searchstr[0] != '\0')) && (owner_id)) {
1296  if (skip_fcurve_with_name(ads, fcu, channel_type, owner, owner_id)) {
1297  continue;
1298  }
1299  }
1300 
1301  /* error-based filtering... */
1302  if ((ads) && (ads->filterflag & ADS_FILTER_ONLY_ERRORS)) {
1303  /* skip if no errors... */
1304  if (fcurve_has_errors(fcu) == false) {
1305  continue;
1306  }
1307  }
1308 
1309  /* this F-Curve can be used, so return it */
1310  return fcu;
1311  }
1312  }
1313  }
1314  }
1315  }
1316 
1317  /* no (more) F-Curves from the list are suitable... */
1318  return NULL;
1319 }
1320 
1321 static size_t animfilter_fcurves(ListBase *anim_data,
1322  bDopeSheet *ads,
1323  FCurve *first,
1324  eAnim_ChannelType fcurve_type,
1325  int filter_mode,
1326  void *owner,
1327  ID *owner_id,
1328  ID *fcurve_owner_id)
1329 {
1330  FCurve *fcu;
1331  size_t items = 0;
1332 
1333  /* Loop over every F-Curve able to be included.
1334  *
1335  * This for-loop works like this:
1336  * 1) The starting F-Curve is assigned to the fcu pointer
1337  * so that we have a starting point to search from.
1338  * 2) The first valid F-Curve to start from (which may include the one given as 'first')
1339  * in the remaining list of F-Curves is found, and verified to be non-null.
1340  * 3) The F-Curve referenced by fcu pointer is added to the list
1341  * 4) The fcu pointer is set to the F-Curve after the one we just added,
1342  * so that we can keep going through the rest of the F-Curve list without an eternal loop.
1343  * Back to step 2 :)
1344  */
1345  for (fcu = first;
1346  ((fcu = animfilter_fcurve_next(ads, fcu, fcurve_type, filter_mode, owner, owner_id)));
1347  fcu = fcu->next) {
1348  if (UNLIKELY(fcurve_type == ANIMTYPE_NLACURVE)) {
1349  /* NLA Control Curve - Basically the same as normal F-Curves,
1350  * except we need to set some stuff differently */
1351  ANIMCHANNEL_NEW_CHANNEL_FULL(fcu, ANIMTYPE_NLACURVE, owner_id, fcurve_owner_id, {
1352  ale->owner = owner; /* strip */
1353  ale->adt = NULL; /* to prevent time mapping from causing problems */
1354  });
1355  }
1356  else {
1357  /* Normal FCurve */
1358  ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id, fcurve_owner_id);
1359  }
1360  }
1361 
1362  /* return the number of items added to the list */
1363  return items;
1364 }
1365 
1367  ListBase *anim_data,
1368  bDopeSheet *ads,
1369  bAction *act,
1370  bActionGroup *agrp,
1371  int filter_mode,
1372  ID *owner_id)
1373 {
1374  ListBase tmp_data = {NULL, NULL};
1375  size_t tmp_items = 0;
1376  size_t items = 0;
1377  // int ofilter = filter_mode;
1378 
1379  /* if we care about the selection status of the channels,
1380  * but the group isn't expanded (1)...
1381  * (1) this only matters if we actually care about the hierarchy though.
1382  * - Hierarchy matters: this hack should be applied
1383  * - Hierarchy ignored: cases like T21276 won't work properly, unless we skip this hack
1384  */
1385  if (
1386  /* Care about hierarchy but group isn't expanded. */
1387  ((filter_mode & ANIMFILTER_LIST_VISIBLE) && EXPANDED_AGRP(ac, agrp) == 0) &&
1388  /* Care about selection status. */
1389  (filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL))) {
1390  /* If the group itself isn't selected appropriately,
1391  * we shouldn't consider its children either. */
1392  if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) == 0) {
1393  return 0;
1394  }
1395 
1396  /* if we're still here,
1397  * then the selection status of the curves within this group should not matter,
1398  * since this creates too much overhead for animators (i.e. making a slow workflow).
1399  *
1400  * Tools affected by this at time of coding (2010 Feb 09):
1401  * - Inserting keyframes on selected channels only.
1402  * - Pasting keyframes.
1403  * - Creating ghost curves in Graph Editor.
1404  */
1406  }
1407 
1408  /* add grouped F-Curves */
1410  /* special filter so that we can get just the F-Curves within the active group */
1411  if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
1412  /* for the Graph Editor, curves may be set to not be visible in the view to lessen
1413  * clutter, but to do this, we need to check that the group doesn't have its
1414  * not-visible flag set preventing all its sub-curves to be shown
1415  */
1416  if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE)) {
1417  /* group must be editable for its children to be editable (if we care about this) */
1418  if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
1419  /* get first F-Curve which can be used here */
1420  FCurve *first_fcu = animfilter_fcurve_next(
1421  ads, agrp->channels.first, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id);
1422 
1423  /* filter list, starting from this F-Curve */
1424  tmp_items += animfilter_fcurves(
1425  &tmp_data, ads, first_fcu, ANIMTYPE_FCURVE, filter_mode, agrp, owner_id, &act->id);
1426  }
1427  }
1428  }
1429  }
1431 
1432  /* did we find anything? */
1433  if (tmp_items) {
1434  /* add this group as a channel first */
1435  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1436  /* restore original filter mode so that this next step works ok... */
1437  // filter_mode = ofilter;
1438 
1439  /* filter selection of channel specially here again,
1440  * since may be open and not subject to previous test */
1441  if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp))) {
1442  ANIMCHANNEL_NEW_CHANNEL(agrp, ANIMTYPE_GROUP, owner_id, &act->id);
1443  }
1444  }
1445 
1446  /* now add the list of collected channels */
1447  BLI_movelisttolist(anim_data, &tmp_data);
1448  BLI_assert(BLI_listbase_is_empty(&tmp_data));
1449  items += tmp_items;
1450  }
1451 
1452  /* return the number of items added to the list */
1453  return items;
1454 }
1455 
1457  ListBase *anim_data,
1458  bDopeSheet *ads,
1459  bAction *act,
1460  int filter_mode,
1461  ID *owner_id)
1462 {
1463  bActionGroup *agrp;
1464  FCurve *lastchan = NULL;
1465  size_t items = 0;
1466 
1467  /* don't include anything from this action if it is linked in from another file,
1468  * and we're getting stuff for editing...
1469  */
1470  if ((filter_mode & ANIMFILTER_FOREDIT) && (ID_IS_LINKED(act) || ID_IS_OVERRIDE_LIBRARY(act))) {
1471  return 0;
1472  }
1473 
1474  /* do groups */
1475  /* TODO: do nested groups? */
1476  for (agrp = act->groups.first; agrp; agrp = agrp->next) {
1477  /* store reference to last channel of group */
1478  if (agrp->channels.last) {
1479  lastchan = agrp->channels.last;
1480  }
1481 
1482  /* action group's channels */
1483  items += animfilter_act_group(ac, anim_data, ads, act, agrp, filter_mode, owner_id);
1484  }
1485 
1486  /* un-grouped F-Curves (only if we're not only considering those channels in the active group) */
1487  if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
1488  FCurve *firstfcu = (lastchan) ? (lastchan->next) : (act->curves.first);
1489  items += animfilter_fcurves(
1490  anim_data, ads, firstfcu, ANIMTYPE_FCURVE, filter_mode, NULL, owner_id, &act->id);
1491  }
1492 
1493  /* return the number of items added to the list */
1494  return items;
1495 }
1496 
1497 /* Include NLA-Data for NLA-Editor:
1498  * - When ANIMFILTER_LIST_CHANNELS is used, that means we should be filtering the list for display
1499  * Although the evaluation order is from the first track to the last and then apply the
1500  * Action on top, we present this in the UI as the Active Action followed by the last track
1501  * to the first so that we get the evaluation order presented as per a stack.
1502  * - For normal filtering (i.e. for editing),
1503  * we only need the NLA-tracks but they can be in 'normal' evaluation order, i.e. first to last.
1504  * Otherwise, some tools may get screwed up.
1505  */
1507  ListBase *anim_data,
1508  bDopeSheet *ads,
1509  AnimData *adt,
1510  int filter_mode,
1511  ID *owner_id)
1512 {
1513  NlaTrack *nlt;
1514  NlaTrack *first = NULL, *next = NULL;
1515  size_t items = 0;
1516 
1517  /* if showing channels, include active action */
1518  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1519  /* if NLA action-line filtering is off, don't show unless there are keyframes,
1520  * in order to keep things more compact for doing transforms
1521  */
1522  if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || (adt->action)) {
1523  /* there isn't really anything editable here, so skip if need editable */
1524  if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
1525  /* Just add the action track now (this MUST appear for drawing):
1526  * - As AnimData may not have an action,
1527  * we pass a dummy pointer just to get the list elem created,
1528  * then overwrite this with the real value - REVIEW THIS.
1529  */
1531  ale->data = adt->action ? adt->action : NULL;
1532  });
1533  }
1534  }
1535 
1536  /* first track to include will be the last one if we're filtering by channels */
1537  first = adt->nla_tracks.last;
1538  }
1539  else {
1540  /* first track to include will the first one (as per normal) */
1541  first = adt->nla_tracks.first;
1542  }
1543 
1544  /* loop over NLA Tracks -
1545  * assume that the caller of this has already checked that these should be included */
1546  for (nlt = first; nlt; nlt = next) {
1547  /* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
1548  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1549  next = nlt->prev;
1550  }
1551  else {
1552  next = nlt->next;
1553  }
1554 
1555  /* only work with this channel and its subchannels if it is editable */
1556  if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_NLT(nlt)) {
1557  /* only include this track if selected in a way consistent with the filtering requirements */
1558  if (ANIMCHANNEL_SELOK(SEL_NLT(nlt))) {
1559  /* only include if this track is active */
1560  if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
1561  /* name based filtering... */
1562  if (((ads) && (ads->searchstr[0] != '\0')) && (owner_id)) {
1563  bool track_ok = false, strip_ok = false;
1564 
1565  /* check if the name of the track, or the strips it has are ok... */
1566  track_ok = name_matches_dopesheet_filter(ads, nlt->name);
1567 
1568  if (track_ok == false) {
1569  NlaStrip *strip;
1570  for (strip = nlt->strips.first; strip; strip = strip->next) {
1571  if (name_matches_dopesheet_filter(ads, strip->name)) {
1572  strip_ok = true;
1573  break;
1574  }
1575  }
1576  }
1577 
1578  /* skip if both fail this test... */
1579  if (!track_ok && !strip_ok) {
1580  continue;
1581  }
1582  }
1583 
1584  /* add the track now that it has passed all our tests */
1586  }
1587  }
1588  }
1589  }
1590 
1591  /* return the number of items added to the list */
1592  return items;
1593 }
1594 
1595 /* Include the control FCurves per NLA Strip in the channel list
1596  * NOTE: This is includes the expander too...
1597  */
1599  ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
1600 {
1601  ListBase tmp_data = {NULL, NULL};
1602  size_t tmp_items = 0;
1603  size_t items = 0;
1604 
1605  /* add control curves from each NLA strip... */
1606  /* NOTE: ANIMTYPE_FCURVES are created here, to avoid duplicating the code needed */
1608  NlaTrack *nlt;
1609  NlaStrip *strip;
1610 
1611  /* for now, we only go one level deep - so controls on grouped FCurves are not handled */
1612  for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
1613  for (strip = nlt->strips.first; strip; strip = strip->next) {
1614  /* pass strip as the "owner",
1615  * so that the name lookups (used while filtering) will resolve */
1616  /* NLA tracks are coming from AnimData, so owner of f-curves
1617  * is the same as owner of animation data. */
1618  tmp_items += animfilter_fcurves(&tmp_data,
1619  ads,
1620  strip->fcurves.first,
1622  filter_mode,
1623  strip,
1624  owner_id,
1625  owner_id);
1626  }
1627  }
1628  }
1630 
1631  /* did we find anything? */
1632  if (tmp_items) {
1633  /* add the expander as a channel first */
1634  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1635  /* currently these channels cannot be selected, so they should be skipped */
1636  if ((filter_mode & (ANIMFILTER_SEL | ANIMFILTER_UNSEL)) == 0) {
1638  }
1639  }
1640 
1641  /* now add the list of collected channels */
1642  BLI_movelisttolist(anim_data, &tmp_data);
1643  BLI_assert(BLI_listbase_is_empty(&tmp_data));
1644  items += tmp_items;
1645  }
1646 
1647  /* return the number of items added to the list */
1648  return items;
1649 }
1650 
1651 /* determine what animation data from AnimData block should get displayed */
1653  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode)
1654 {
1656  size_t items = 0;
1657 
1658  /* image object data-blocks have no anim-data so check for NULL */
1659  if (adt) {
1660  IdAdtTemplate *iat = (IdAdtTemplate *)id;
1661 
1662  /* NOTE: this macro is used instead of inlining the logic here,
1663  * since this sort of filtering is still needed in a few places in the rest of the code still -
1664  * notably for the few cases where special mode-based
1665  * different types of data expanders are required.
1666  */
1668  iat,
1669  { /* AnimData */
1670  /* specifically filter animdata block */
1673  }
1674  },
1675  { /* NLA */
1676  items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
1677  },
1678  { /* Drivers */
1679  items += animfilter_fcurves(
1680  anim_data, ads, adt->drivers.first, ANIMTYPE_FCURVE, filter_mode, NULL, id, id);
1681  },
1682  { /* NLA Control Keyframes */
1683  items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id);
1684  },
1685  { /* Keyframes */
1686  items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id);
1687  });
1688  }
1689 
1690  return items;
1691 }
1692 
1693 /* Include ShapeKey Data for ShapeKey Editor */
1695  ListBase *anim_data,
1696  Key *key,
1697  int filter_mode)
1698 {
1699  size_t items = 0;
1700 
1701  /* check if channels or only F-Curves */
1702  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1703  KeyBlock *kb;
1704  bDopeSheet *ads = ac->ads;
1705 
1706  /* loop through the channels adding ShapeKeys as appropriate */
1707  for (kb = key->block.first; kb; kb = kb->next) {
1708  /* skip the first one, since that's the non-animatable basis */
1709  if (kb == key->block.first) {
1710  continue;
1711  }
1712 
1713  /* Skip shapekey if the name doesn't match the filter string. */
1714  if (ads != NULL && ads->searchstr[0] != '\0' &&
1715  name_matches_dopesheet_filter(ads, kb->name) == false) {
1716  continue;
1717  }
1718 
1719  /* only work with this channel and its subchannels if it is editable */
1720  if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
1721  /* Only include this track if selected in a way consistent
1722  * with the filtering requirements. */
1723  if (ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb))) {
1724  /* TODO: consider 'active' too? */
1725 
1726  /* owner-id here must be key so that the F-Curve can be resolved... */
1728  }
1729  }
1730  }
1731  }
1732  else {
1733  /* just use the action associated with the shapekey */
1734  /* TODO: somehow manage to pass dopesheet info down here too? */
1735  if (key->adt) {
1736  if (filter_mode & ANIMFILTER_ANIMDATA) {
1737  if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(key->adt))) {
1739  }
1740  }
1741  else if (key->adt->action) {
1742  items = animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
1743  }
1744  }
1745  }
1746 
1747  /* return the number of items added to the list */
1748  return items;
1749 }
1750 
1751 /* Helper for Grease Pencil - layers within a data-block. */
1753  bDopeSheet *ads,
1754  bGPdata *gpd,
1755  int filter_mode)
1756 {
1757  bGPDlayer *gpl;
1758  size_t items = 0;
1759 
1760  /* loop over layers as the conditions are acceptable (top-Down order) */
1761  for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
1762  /* only if selected */
1763  if (!ANIMCHANNEL_SELOK(SEL_GPL(gpl))) {
1764  continue;
1765  }
1766 
1767  /* only if editable */
1768  if ((filter_mode & ANIMFILTER_FOREDIT) && !EDITABLE_GPL(gpl)) {
1769  continue;
1770  }
1771 
1772  /* active... */
1773  if ((filter_mode & ANIMFILTER_ACTIVE) && (gpl->flag & GP_LAYER_ACTIVE) == 0) {
1774  continue;
1775  }
1776 
1777  /* skip layer if the name doesn't match the filter string */
1778  if (ads != NULL && ads->searchstr[0] != '\0' &&
1779  name_matches_dopesheet_filter(ads, gpl->info) == false) {
1780  continue;
1781  }
1782 
1783  /* Skip empty layers. */
1784  if (BLI_listbase_is_empty(&gpl->frames)) {
1785  continue;
1786  }
1787 
1788  /* add to list */
1790  }
1791 
1792  return items;
1793 }
1794 
1795 /* Helper for Grease Pencil - Grease Pencil data-block - GP Frames. */
1796 static size_t animdata_filter_gpencil_data(ListBase *anim_data,
1797  bDopeSheet *ads,
1798  bGPdata *gpd,
1799  int filter_mode)
1800 {
1801  size_t items = 0;
1802 
1803  /* When asked from "AnimData" blocks (i.e. the top-level containers for normal animation),
1804  * for convenience, this will return GP Data-blocks instead.
1805  * This may cause issues down the track, but for now, this will do.
1806  */
1807  if (filter_mode & ANIMFILTER_ANIMDATA) {
1808  /* just add GPD as a channel - this will add everything needed */
1810  }
1811  else {
1812  ListBase tmp_data = {NULL, NULL};
1813  size_t tmp_items = 0;
1814 
1815  if (!(filter_mode & ANIMFILTER_FCURVESONLY)) {
1816  /* add gpencil animation channels */
1818  tmp_items += animdata_filter_gpencil_layers_data(&tmp_data, ads, gpd, filter_mode);
1819  }
1821  }
1822 
1823  /* did we find anything? */
1824  if (tmp_items) {
1825  /* include data-expand widget first */
1826  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1827  /* add gpd as channel too (if for drawing, and it has layers) */
1829  }
1830 
1831  /* now add the list of collected channels */
1832  BLI_movelisttolist(anim_data, &tmp_data);
1833  BLI_assert(BLI_listbase_is_empty(&tmp_data));
1834  items += tmp_items;
1835  }
1836  }
1837 
1838  return items;
1839 }
1840 
1847  ListBase *anim_data,
1848  void *UNUSED(data),
1849  int filter_mode)
1850 {
1851  bDopeSheet *ads = ac->ads;
1852  size_t items = 0;
1853 
1854  ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
1855  Base *base;
1856 
1857  /* Include all annotation datablocks. */
1858  if (((ads->filterflag & ADS_FILTER_ONLYSEL) == 0) ||
1860  LISTBASE_FOREACH (bGPdata *, gpd, &ac->bmain->gpencils) {
1861  if (gpd->flag & GP_DATA_ANNOTATIONS) {
1862  items += animdata_filter_gpencil_data(anim_data, ads, gpd, filter_mode);
1863  }
1864  }
1865  }
1866  /* Objects in the scene */
1867  for (base = view_layer->object_bases.first; base; base = base->next) {
1868  /* Only consider this object if it has got some GP data (saving on all the other tests) */
1869  if (base->object && (base->object->type == OB_GPENCIL)) {
1870  Object *ob = base->object;
1871 
1872  /* firstly, check if object can be included, by the following factors:
1873  * - if only visible, must check for layer and also viewport visibility
1874  * --> while tools may demand only visible, user setting takes priority
1875  * as user option controls whether sets of channels get included while
1876  * tool-flag takes into account collapsed/open channels too
1877  * - if only selected, must check if object is selected
1878  * - there must be animation data to edit (this is done recursively as we
1879  * try to add the channels)
1880  */
1881  if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
1882  /* Layer visibility - we check both object and base,
1883  * since these may not be in sync yet. */
1884  if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0 ||
1885  (base->flag & BASE_VISIBLE_VIEWLAYER) == 0) {
1886  continue;
1887  }
1888 
1889  /* outliner restrict-flag */
1890  if (ob->visibility_flag & OB_HIDE_VIEWPORT) {
1891  continue;
1892  }
1893  }
1894 
1895  /* check selection and object type filters */
1896  if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED))) {
1897  /* only selected should be shown */
1898  continue;
1899  }
1900 
1901  /* check if object belongs to the filtering group if option to filter
1902  * objects by the grouped status is on
1903  * - used to ease the process of doing multiple-character choreographies
1904  */
1905  if (ads->filter_grp != NULL) {
1906  if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0) {
1907  continue;
1908  }
1909  }
1910 
1911  /* finally, include this object's grease pencil data-block. */
1912  /* XXX: Should we store these under expanders per item? */
1913  items += animdata_filter_gpencil_data(anim_data, ads, ob->data, filter_mode);
1914  }
1915  }
1916 
1917  /* return the number of items added to the list */
1918  return items;
1919 }
1920 
1921 /* Helper for Grease Pencil data integrated with main DopeSheet */
1923  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
1924 {
1925  ListBase tmp_data = {NULL, NULL};
1926  size_t tmp_items = 0;
1927  size_t items = 0;
1928 
1929  /* add relevant animation channels for Grease Pencil */
1931  /* add animation channels */
1932  tmp_items += animfilter_block_data(ac, &tmp_data, ads, &gpd->id, filter_mode);
1933 
1934  /* add Grease Pencil layers */
1935  if (!(filter_mode & ANIMFILTER_FCURVESONLY)) {
1936  tmp_items += animdata_filter_gpencil_layers_data(&tmp_data, ads, gpd, filter_mode);
1937  }
1938 
1939  /* TODO: do these need a separate expander?
1940  * XXX: what order should these go in? */
1941  }
1943 
1944  /* did we find anything? */
1945  if (tmp_items) {
1946  /* include data-expand widget first */
1947  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1948  /* check if filtering by active status */
1949  /* XXX: active check here needs checking */
1950  if (ANIMCHANNEL_ACTIVEOK(gpd)) {
1952  }
1953  }
1954 
1955  /* now add the list of collected channels */
1956  BLI_movelisttolist(anim_data, &tmp_data);
1957  BLI_assert(BLI_listbase_is_empty(&tmp_data));
1958  items += tmp_items;
1959  }
1960 
1961  /* return the number of items added to the list */
1962  return items;
1963 }
1964 
1965 /* Helper for Cache File data integrated with main DopeSheet */
1967  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, CacheFile *cache_file, int filter_mode)
1968 {
1969  ListBase tmp_data = {NULL, NULL};
1970  size_t tmp_items = 0;
1971  size_t items = 0;
1972 
1973  /* add relevant animation channels for Cache File */
1975  /* add animation channels */
1976  tmp_items += animfilter_block_data(ac, &tmp_data, ads, &cache_file->id, filter_mode);
1977  }
1979 
1980  /* did we find anything? */
1981  if (tmp_items) {
1982  /* include data-expand widget first */
1983  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
1984  /* check if filtering by active status */
1985  /* XXX: active check here needs checking */
1986  if (ANIMCHANNEL_ACTIVEOK(cache_file)) {
1987  ANIMCHANNEL_NEW_CHANNEL(cache_file, ANIMTYPE_DSCACHEFILE, cache_file, NULL);
1988  }
1989  }
1990 
1991  /* now add the list of collected channels */
1992  BLI_movelisttolist(anim_data, &tmp_data);
1993  BLI_assert(BLI_listbase_is_empty(&tmp_data));
1994  items += tmp_items;
1995  }
1996 
1997  /* return the number of items added to the list */
1998  return items;
1999 }
2000 
2001 /* Helper for Mask Editing - mask layers */
2002 static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
2003 {
2005  MaskLayer *masklay;
2006  size_t items = 0;
2007 
2008  /* loop over layers as the conditions are acceptable */
2009  for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
2010  /* only if selected */
2011  if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay))) {
2012  /* only if editable */
2013  if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_MASK(masklay)) {
2014  /* active... */
2015  if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
2016  /* add to list */
2018  }
2019  }
2020  }
2021  }
2022 
2023  return items;
2024 }
2025 
2026 /* Grab all mask data */
2027 static size_t animdata_filter_mask(Main *bmain,
2028  ListBase *anim_data,
2029  void *UNUSED(data),
2030  int filter_mode)
2031 {
2032  Mask *mask;
2033  size_t items = 0;
2034 
2035  /* For now, grab mask data-blocks directly from main. */
2036  /* XXX: this is not good... */
2037  for (mask = bmain->masks.first; mask; mask = mask->id.next) {
2038  ListBase tmp_data = {NULL, NULL};
2039  size_t tmp_items = 0;
2040 
2041  /* only show if mask is used by something... */
2042  if (ID_REAL_USERS(mask) < 1) {
2043  continue;
2044  }
2045 
2046  /* add mask animation channels */
2048  tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode);
2049  }
2051 
2052  /* did we find anything? */
2053  if (tmp_items) {
2054  /* include data-expand widget first */
2055  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2056  /* add mask data-block as channel too (if for drawing, and it has layers) */
2058  }
2059 
2060  /* now add the list of collected channels */
2061  BLI_movelisttolist(anim_data, &tmp_data);
2062  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2063  items += tmp_items;
2064  }
2065  }
2066 
2067  /* return the number of items added to the list */
2068  return items;
2069 }
2070 
2071 /* NOTE: owner_id is scene, material, or texture block,
2072  * which is the direct owner of the node tree in question. */
2074  ListBase *anim_data,
2075  bDopeSheet *ads,
2076  ID *owner_id,
2077  bNodeTree *ntree,
2078  int filter_mode)
2079 {
2080  ListBase tmp_data = {NULL, NULL};
2081  size_t tmp_items = 0;
2082  size_t items = 0;
2083 
2084  /* add nodetree animation channels */
2086  /* animation data filtering */
2087  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ntree, filter_mode);
2088  }
2090 
2091  /* did we find anything? */
2092  if (tmp_items) {
2093  /* include data-expand widget first */
2094  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2095  /* check if filtering by active status */
2096  if (ANIMCHANNEL_ACTIVEOK(ntree)) {
2098  }
2099  }
2100 
2101  /* now add the list of collected channels */
2102  BLI_movelisttolist(anim_data, &tmp_data);
2103  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2104  items += tmp_items;
2105  }
2106 
2107  /* return the number of items added to the list */
2108  return items;
2109 }
2110 
2112  ListBase *anim_data,
2113  bDopeSheet *ads,
2114  ID *owner_id,
2115  bNodeTree *ntree,
2116  int filter_mode)
2117 {
2118  bNode *node;
2119  size_t items = 0;
2120 
2121  items += animdata_filter_ds_nodetree_group(ac, anim_data, ads, owner_id, ntree, filter_mode);
2122 
2123  for (node = ntree->nodes.first; node; node = node->next) {
2124  if (node->type == NODE_GROUP) {
2125  if (node->id) {
2126  if ((ads->filterflag & ADS_FILTER_ONLYSEL) && (node->flag & NODE_SELECT) == 0) {
2127  continue;
2128  }
2129  /* Recurse into the node group */
2130  items += animdata_filter_ds_nodetree(ac,
2131  anim_data,
2132  ads,
2133  owner_id,
2134  (bNodeTree *)node->id,
2135  filter_mode | ANIMFILTER_TMP_IGNORE_ONLYSEL);
2136  }
2137  }
2138  }
2139 
2140  return items;
2141 }
2142 
2144  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
2145 {
2146  ViewLayer *view_layer;
2147  FreestyleLineSet *lineset;
2148  size_t items = 0;
2149 
2150  for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
2151  for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
2152  if (lineset->linestyle) {
2153  lineset->linestyle->id.tag |= LIB_TAG_DOIT;
2154  }
2155  }
2156  }
2157 
2158  for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
2159  /* skip render layers without Freestyle enabled */
2160  if ((view_layer->flag & VIEW_LAYER_FREESTYLE) == 0) {
2161  continue;
2162  }
2163 
2164  /* loop over linesets defined in the render layer */
2165  for (lineset = view_layer->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
2167  ListBase tmp_data = {NULL, NULL};
2168  size_t tmp_items = 0;
2169 
2170  if ((linestyle == NULL) || !(linestyle->id.tag & LIB_TAG_DOIT)) {
2171  continue;
2172  }
2174 
2175  /* add scene-level animation channels */
2177  /* animation data filtering */
2178  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)linestyle, filter_mode);
2179  }
2181 
2182  /* did we find anything? */
2183  if (tmp_items) {
2184  /* include anim-expand widget first */
2185  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2186  /* check if filtering by active status */
2189  }
2190  }
2191 
2192  /* now add the list of collected channels */
2193  BLI_movelisttolist(anim_data, &tmp_data);
2194  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2195  items += tmp_items;
2196  }
2197  }
2198  }
2199 
2200  /* return the number of items added to the list */
2201  return items;
2202 }
2203 
2205  ListBase *anim_data,
2206  bDopeSheet *ads,
2207  Tex *tex,
2208  ID *owner_id,
2209  int filter_mode)
2210 {
2211  ListBase tmp_data = {NULL, NULL};
2212  size_t tmp_items = 0;
2213  size_t items = 0;
2214 
2215  /* add texture's animation data to temp collection */
2217  /* texture animdata */
2218  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)tex, filter_mode);
2219 
2220  /* nodes */
2221  if ((tex->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
2222  /* owner_id as id instead of texture,
2223  * since it'll otherwise be impossible to track the depth. */
2224 
2225  /* FIXME: perhaps as a result, textures should NOT be included under materials,
2226  * but under their own section instead so that free-floating textures can also be animated.
2227  */
2228  tmp_items += animdata_filter_ds_nodetree(
2229  ac, &tmp_data, ads, (ID *)tex, tex->nodetree, filter_mode);
2230  }
2231  }
2233 
2234  /* did we find anything? */
2235  if (tmp_items) {
2236  /* include texture-expand widget? */
2237  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2238  /* check if filtering by active status */
2239  if (ANIMCHANNEL_ACTIVEOK(tex)) {
2241  }
2242  }
2243 
2244  /* now add the list of collected channels */
2245  BLI_movelisttolist(anim_data, &tmp_data);
2246  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2247  items += tmp_items;
2248  }
2249 
2250  /* return the number of items added to the list */
2251  return items;
2252 }
2253 
2254 /* NOTE: owner_id is the direct owner of the texture stack in question
2255  * It used to be Material/Light/World before the Blender Internal removal for 2.8
2256  */
2258  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
2259 {
2260  MTex **mtex = NULL;
2261  size_t items = 0;
2262  int a = 0;
2263 
2264  /* get datatype specific data first */
2265  if (owner_id == NULL) {
2266  return 0;
2267  }
2268 
2269  switch (GS(owner_id->name)) {
2270  case ID_PA: {
2271  ParticleSettings *part = (ParticleSettings *)owner_id;
2272  mtex = (MTex **)(&part->mtex);
2273  break;
2274  }
2275  default: {
2276  /* invalid/unsupported option */
2277  if (G.debug & G_DEBUG) {
2278  printf("ERROR: Unsupported owner_id (i.e. texture stack) for filter textures - %s\n",
2279  owner_id->name);
2280  }
2281  return 0;
2282  }
2283  }
2284 
2285  /* Firstly check that we actually have some textures,
2286  * by gathering all textures in a temp list. */
2287  for (a = 0; a < MAX_MTEX; a++) {
2288  Tex *tex = (mtex[a]) ? mtex[a]->tex : NULL;
2289 
2290  /* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */
2291  if (tex == NULL) {
2292  continue;
2293  }
2294 
2295  /* add texture's anim channels */
2296  items += animdata_filter_ds_texture(ac, anim_data, ads, tex, owner_id, filter_mode);
2297  }
2298 
2299  /* return the number of items added to the list */
2300  return items;
2301 }
2302 
2304  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Material *ma, int filter_mode)
2305 {
2306  ListBase tmp_data = {NULL, NULL};
2307  size_t tmp_items = 0;
2308  size_t items = 0;
2309 
2310  /* add material's animation data to temp collection */
2312  /* material's animation data */
2313  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ma, filter_mode);
2314 
2315  /* nodes */
2316  if ((ma->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
2317  tmp_items += animdata_filter_ds_nodetree(
2318  ac, &tmp_data, ads, (ID *)ma, ma->nodetree, filter_mode);
2319  }
2320  }
2322 
2323  /* did we find anything? */
2324  if (tmp_items) {
2325  /* include material-expand widget first */
2326  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2327  /* check if filtering by active status */
2328  if (ANIMCHANNEL_ACTIVEOK(ma)) {
2330  }
2331  }
2332 
2333  /* now add the list of collected channels */
2334  BLI_movelisttolist(anim_data, &tmp_data);
2335  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2336  items += tmp_items;
2337  }
2338 
2339  return items;
2340 }
2341 
2343  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
2344 {
2345  size_t items = 0;
2346  int a = 0;
2347 
2348  /* First pass: take the materials referenced via the Material slots of the object. */
2349  for (a = 1; a <= ob->totcol; a++) {
2350  Material *ma = BKE_object_material_get(ob, a);
2351 
2352  /* if material is valid, try to add relevant contents from here */
2353  if (ma) {
2354  /* add channels */
2355  items += animdata_filter_ds_material(ac, anim_data, ads, ma, filter_mode);
2356  }
2357  }
2358 
2359  /* return the number of items added to the list */
2360  return items;
2361 }
2362 
2363 /* ............ */
2364 
2365 /* Temporary context for modifier linked-data channel extraction */
2367  bAnimContext *ac; /* anim editor context */
2368  bDopeSheet *ads; /* dopesheet filtering settings */
2369 
2370  ListBase tmp_data; /* list of channels created (but not yet added to the main list) */
2371  size_t items; /* number of channels created */
2372 
2373  int filter_mode; /* flags for stuff we want to filter */
2375 
2376 /* dependency walker callback for modifier dependencies */
2377 static void animfilter_modifier_idpoin_cb(void *afm_ptr,
2378  Object *ob,
2379  ID **idpoin,
2380  int UNUSED(cb_flag))
2381 {
2383  ID *owner_id = &ob->id;
2384  ID *id = *idpoin;
2385 
2386  /* NOTE: the walker only guarantees to give us all the ID-ptr *slots*,
2387  * not just the ones which are actually used, so be careful!
2388  */
2389  if (id == NULL) {
2390  return;
2391  }
2392 
2393  /* check if this is something we're interested in... */
2394  switch (GS(id->name)) {
2395  case ID_TE: /* Textures */
2396  {
2397  Tex *tex = (Tex *)id;
2398  if (!(afm->ads->filterflag & ADS_FILTER_NOTEX)) {
2400  afm->ac, &afm->tmp_data, afm->ads, tex, owner_id, afm->filter_mode);
2401  }
2402  break;
2403  }
2404  case ID_NT: {
2405  bNodeTree *node_tree = (bNodeTree *)id;
2406  if (!(afm->ads->filterflag & ADS_FILTER_NONTREE)) {
2408  afm->ac, &afm->tmp_data, afm->ads, owner_id, node_tree, afm->filter_mode);
2409  }
2410  }
2411 
2412  /* TODO: images? */
2413  default:
2414  break;
2415  }
2416 }
2417 
2418 /* animation linked to data used by modifiers
2419  * NOTE: strictly speaking, modifier animation is already included under Object level
2420  * but for some modifiers (e.g. Displace), there can be linked data that has settings
2421  * which would be nice to animate (i.e. texture parameters) but which are not actually
2422  * attached to any other objects/materials/etc. in the scene
2423  */
2424 /* TODO: do we want an expander for this? */
2426  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
2427 {
2429  size_t items = 0;
2430 
2431  /* 1) create a temporary "context" containing all the info we have here to pass to the callback
2432  * use to walk through the dependencies of the modifiers
2433  *
2434  * Assumes that all other unspecified values (i.e. accumulation buffers)
2435  * are zero'd out properly!
2436  */
2437  afm.ac = ac;
2438  afm.ads = ads;
2439  afm.filter_mode = filter_mode;
2440 
2441  /* 2) walk over dependencies */
2443 
2444  /* 3) extract data from the context, merging it back into the standard list */
2445  if (afm.items) {
2446  /* now add the list of collected channels */
2447  BLI_movelisttolist(anim_data, &afm.tmp_data);
2449  items += afm.items;
2450  }
2451 
2452  return items;
2453 }
2454 
2455 /* ............ */
2456 
2458  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
2459 {
2460  ParticleSystem *psys;
2461  size_t items = 0;
2462 
2463  for (psys = ob->particlesystem.first; psys; psys = psys->next) {
2464  ListBase tmp_data = {NULL, NULL};
2465  size_t tmp_items = 0;
2466 
2467  /* Note that when psys->part->adt is NULL the textures can still be
2468  * animated. */
2469  if (psys->part == NULL) {
2470  continue;
2471  }
2472 
2473  /* add particle-system's animation data to temp collection */
2475  /* particle system's animation data */
2476  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
2477 
2478  /* textures */
2479  if (!(ads->filterflag & ADS_FILTER_NOTEX)) {
2480  tmp_items += animdata_filter_ds_textures(
2481  ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
2482  }
2483  }
2485 
2486  /* did we find anything? */
2487  if (tmp_items) {
2488  /* include particle-expand widget first */
2489  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2490  /* check if filtering by active status */
2491  if (ANIMCHANNEL_ACTIVEOK(psys->part)) {
2493  }
2494  }
2495 
2496  /* now add the list of collected channels */
2497  BLI_movelisttolist(anim_data, &tmp_data);
2498  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2499  items += tmp_items;
2500  }
2501  }
2502 
2503  /* return the number of items added to the list */
2504  return items;
2505 }
2506 
2508  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
2509 {
2510  ListBase tmp_data = {NULL, NULL};
2511  size_t tmp_items = 0;
2512  size_t items = 0;
2513 
2514  IdAdtTemplate *iat = ob->data;
2515  short type = 0, expanded = 0;
2516 
2517  /* get settings based on data type */
2518  switch (ob->type) {
2519  case OB_CAMERA: /* ------- Camera ------------ */
2520  {
2521  Camera *ca = (Camera *)ob->data;
2522 
2523  if (ads->filterflag & ADS_FILTER_NOCAM) {
2524  return 0;
2525  }
2526 
2527  type = ANIMTYPE_DSCAM;
2528  expanded = FILTER_CAM_OBJD(ca);
2529  break;
2530  }
2531  case OB_LAMP: /* ---------- Light ----------- */
2532  {
2533  Light *la = (Light *)ob->data;
2534 
2535  if (ads->filterflag & ADS_FILTER_NOLAM) {
2536  return 0;
2537  }
2538 
2539  type = ANIMTYPE_DSLAM;
2540  expanded = FILTER_LAM_OBJD(la);
2541  break;
2542  }
2543  case OB_CURVES_LEGACY: /* ------- Curve ---------- */
2544  case OB_SURF: /* ------- Nurbs Surface ---------- */
2545  case OB_FONT: /* ------- Text Curve ---------- */
2546  {
2547  Curve *cu = (Curve *)ob->data;
2548 
2549  if (ads->filterflag & ADS_FILTER_NOCUR) {
2550  return 0;
2551  }
2552 
2553  type = ANIMTYPE_DSCUR;
2554  expanded = FILTER_CUR_OBJD(cu);
2555  break;
2556  }
2557  case OB_MBALL: /* ------- MetaBall ---------- */
2558  {
2559  MetaBall *mb = (MetaBall *)ob->data;
2560 
2561  if (ads->filterflag & ADS_FILTER_NOMBA) {
2562  return 0;
2563  }
2564 
2566  expanded = FILTER_MBALL_OBJD(mb);
2567  break;
2568  }
2569  case OB_ARMATURE: /* ------- Armature ---------- */
2570  {
2571  bArmature *arm = (bArmature *)ob->data;
2572 
2573  if (ads->filterflag & ADS_FILTER_NOARM) {
2574  return 0;
2575  }
2576 
2577  type = ANIMTYPE_DSARM;
2578  expanded = FILTER_ARM_OBJD(arm);
2579  break;
2580  }
2581  case OB_MESH: /* ------- Mesh ---------- */
2582  {
2583  Mesh *me = (Mesh *)ob->data;
2584 
2585  if (ads->filterflag & ADS_FILTER_NOMESH) {
2586  return 0;
2587  }
2588 
2590  expanded = FILTER_MESH_OBJD(me);
2591  break;
2592  }
2593  case OB_LATTICE: /* ---- Lattice ---- */
2594  {
2595  Lattice *lt = (Lattice *)ob->data;
2596 
2597  if (ads->filterflag & ADS_FILTER_NOLAT) {
2598  return 0;
2599  }
2600 
2601  type = ANIMTYPE_DSLAT;
2602  expanded = FILTER_LATTICE_OBJD(lt);
2603  break;
2604  }
2605  case OB_SPEAKER: /* ---------- Speaker ----------- */
2606  {
2607  Speaker *spk = (Speaker *)ob->data;
2608 
2609  type = ANIMTYPE_DSSPK;
2610  expanded = FILTER_SPK_OBJD(spk);
2611  break;
2612  }
2613  case OB_CURVES: /* ---------- Curves ----------- */
2614  {
2615  Curves *curves = (Curves *)ob->data;
2616 
2617  if (ads->filterflag2 & ADS_FILTER_NOHAIR) {
2618  return 0;
2619  }
2620 
2622  expanded = FILTER_CURVES_OBJD(curves);
2623  break;
2624  }
2625  case OB_POINTCLOUD: /* ---------- PointCloud ----------- */
2626  {
2627  PointCloud *pointcloud = (PointCloud *)ob->data;
2628 
2630  return 0;
2631  }
2632 
2634  expanded = FILTER_POINTS_OBJD(pointcloud);
2635  break;
2636  }
2637  case OB_VOLUME: /* ---------- Volume ----------- */
2638  {
2639  Volume *volume = (Volume *)ob->data;
2640 
2642  return 0;
2643  }
2644 
2646  expanded = FILTER_VOLUME_OBJD(volume);
2647  break;
2648  }
2649  }
2650 
2651  /* add object data animation channels */
2652  BEGIN_ANIMFILTER_SUBCHANNELS (expanded) {
2653  /* animation data filtering */
2654  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)iat, filter_mode);
2655 
2656  /* sub-data filtering... */
2657  switch (ob->type) {
2658  case OB_LAMP: /* light - textures + nodetree */
2659  {
2660  Light *la = ob->data;
2661  bNodeTree *ntree = la->nodetree;
2662 
2663  /* nodetree */
2664  if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
2665  tmp_items += animdata_filter_ds_nodetree(
2666  ac, &tmp_data, ads, &la->id, ntree, filter_mode);
2667  }
2668  break;
2669  }
2670  }
2671  }
2673 
2674  /* did we find anything? */
2675  if (tmp_items) {
2676  /* include data-expand widget first */
2677  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2678  /* check if filtering by active status */
2679  if (ANIMCHANNEL_ACTIVEOK(iat)) {
2680  ANIMCHANNEL_NEW_CHANNEL(iat, type, iat, NULL);
2681  }
2682  }
2683 
2684  /* now add the list of collected channels */
2685  BLI_movelisttolist(anim_data, &tmp_data);
2686  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2687  items += tmp_items;
2688  }
2689 
2690  /* return the number of items added to the list */
2691  return items;
2692 }
2693 
2694 /* shapekey-level animation */
2696  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, Key *key, int filter_mode)
2697 {
2698  ListBase tmp_data = {NULL, NULL};
2699  size_t tmp_items = 0;
2700  size_t items = 0;
2701 
2702  /* add shapekey-level animation channels */
2704  /* animation data filtering */
2705  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)key, filter_mode);
2706  }
2708 
2709  /* did we find anything? */
2710  if (tmp_items) {
2711  /* include key-expand widget first */
2712  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2713  if (ANIMCHANNEL_ACTIVEOK(key)) {
2715  }
2716  }
2717 
2718  /* now add the list of collected channels */
2719  BLI_movelisttolist(anim_data, &tmp_data);
2720  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2721  items += tmp_items;
2722  }
2723 
2724  /* return the number of items added to the list */
2725  return items;
2726 }
2727 
2728 /* object-level animation */
2730  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
2731 {
2732  ListBase tmp_data = {NULL, NULL};
2733  size_t tmp_items = 0;
2734  size_t items = 0;
2735 
2736  AnimData *adt = ob->adt;
2737  short type = 0, expanded = 1;
2738  void *cdata = NULL;
2739 
2740  /* determine the type of expander channels to use */
2741  /* this is the best way to do this for now... */
2743  ob, /* Some useless long comment to prevent wrapping by old clang-format versions... */
2744  {/* AnimData - no channel, but consider data */},
2745  {/* NLA - no channel, but consider data */},
2746  { /* Drivers */
2748  cdata = adt;
2749  expanded = EXPANDED_DRVD(adt);
2750  },
2751  {/* NLA Strip Controls - no dedicated channel for now (XXX) */},
2752  { /* Keyframes */
2754  cdata = adt->action;
2755  expanded = EXPANDED_ACTC(adt->action);
2756  });
2757 
2758  /* add object-level animation channels */
2759  BEGIN_ANIMFILTER_SUBCHANNELS (expanded) {
2760  /* animation data filtering */
2761  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ob, filter_mode);
2762  }
2764 
2765  /* did we find anything? */
2766  if (tmp_items) {
2767  /* include anim-expand widget first */
2768  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2769  if (type != ANIMTYPE_NONE) {
2770  /* NOTE: active-status (and the associated checks) don't apply here... */
2771  ANIMCHANNEL_NEW_CHANNEL(cdata, type, ob, NULL);
2772  }
2773  }
2774 
2775  /* now add the list of collected channels */
2776  BLI_movelisttolist(anim_data, &tmp_data);
2777  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2778  items += tmp_items;
2779  }
2780 
2781  /* return the number of items added to the list */
2782  return items;
2783 }
2784 
2785 /* get animation channels from object2 */
2787  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
2788 {
2789  ListBase tmp_data = {NULL, NULL};
2790  Object *ob = base->object;
2791  size_t tmp_items = 0;
2792  size_t items = 0;
2793 
2794  /* filter data contained under object first */
2796  Key *key = BKE_key_from_object(ob);
2797 
2798  /* object-level animation */
2799  if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
2800  tmp_items += animdata_filter_ds_obanim(ac, &tmp_data, ads, ob, filter_mode);
2801  }
2802 
2803  /* particle deflector textures */
2804  if (ob->pd != NULL && ob->pd->tex != NULL && !(ads->filterflag & ADS_FILTER_NOTEX)) {
2805  tmp_items += animdata_filter_ds_texture(
2806  ac, &tmp_data, ads, ob->pd->tex, &ob->id, filter_mode);
2807  }
2808 
2809  /* shape-key */
2810  if ((key && key->adt) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
2811  tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, key, filter_mode);
2812  }
2813 
2814  /* modifiers */
2815  if ((ob->modifiers.first) && !(ads->filterflag & ADS_FILTER_NOMODIFIERS)) {
2816  tmp_items += animdata_filter_ds_modifiers(ac, &tmp_data, ads, ob, filter_mode);
2817  }
2818 
2819  /* materials */
2820  if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) {
2821  tmp_items += animdata_filter_ds_materials(ac, &tmp_data, ads, ob, filter_mode);
2822  }
2823 
2824  /* object data */
2825  if (ob->data) {
2826  tmp_items += animdata_filter_ds_obdata(ac, &tmp_data, ads, ob, filter_mode);
2827  }
2828 
2829  /* particles */
2830  if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
2831  tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
2832  }
2833 
2834  /* grease pencil */
2835  if ((ob->type == OB_GPENCIL) && (ob->data) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
2836  tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, ob->data, filter_mode);
2837  }
2838  }
2840 
2841  /* if we collected some channels, add these to the new list... */
2842  if (tmp_items) {
2843  /* firstly add object expander if required */
2844  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2845  /* check if filtering by selection */
2846  /* XXX: double-check on this -
2847  * most of the time, a lot of tools need to filter out these channels! */
2848  if (ANIMCHANNEL_SELOK((base->flag & BASE_SELECTED))) {
2849  /* check if filtering by active status */
2850  if (ANIMCHANNEL_ACTIVEOK(ob)) {
2852  }
2853  }
2854  }
2855 
2856  /* now add the list of collected channels */
2857  BLI_movelisttolist(anim_data, &tmp_data);
2858  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2859  items += tmp_items;
2860  }
2861 
2862  /* return the number of items added */
2863  return items;
2864 }
2865 
2867  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, World *wo, int filter_mode)
2868 {
2869  ListBase tmp_data = {NULL, NULL};
2870  size_t tmp_items = 0;
2871  size_t items = 0;
2872 
2873  /* add world animation channels */
2875  /* animation data filtering */
2876  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)wo, filter_mode);
2877 
2878  /* nodes */
2879  if ((wo->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
2880  tmp_items += animdata_filter_ds_nodetree(
2881  ac, &tmp_data, ads, (ID *)wo, wo->nodetree, filter_mode);
2882  }
2883  }
2885 
2886  /* did we find anything? */
2887  if (tmp_items) {
2888  /* include data-expand widget first */
2889  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2890  /* check if filtering by active status */
2891  if (ANIMCHANNEL_ACTIVEOK(wo)) {
2893  }
2894  }
2895 
2896  /* now add the list of collected channels */
2897  BLI_movelisttolist(anim_data, &tmp_data);
2898  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2899  items += tmp_items;
2900  }
2901 
2902  /* return the number of items added to the list */
2903  return items;
2904 }
2905 
2907  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
2908 {
2909  ListBase tmp_data = {NULL, NULL};
2910  size_t tmp_items = 0;
2911  size_t items = 0;
2912 
2913  AnimData *adt = sce->adt;
2914  short type = 0, expanded = 1;
2915  void *cdata = NULL;
2916 
2917  /* determine the type of expander channels to use */
2918  /* this is the best way to do this for now... */
2920  sce, /* Some useless long comment to prevent wrapping by old clang-format versions... */
2921  {/* AnimData - no channel, but consider data */},
2922  {/* NLA - no channel, but consider data */},
2923  { /* Drivers */
2925  cdata = adt;
2926  expanded = EXPANDED_DRVD(adt);
2927  },
2928  {/* NLA Strip Controls - no dedicated channel for now (XXX) */},
2929  { /* Keyframes */
2931  cdata = adt->action;
2932  expanded = EXPANDED_ACTC(adt->action);
2933  });
2934 
2935  /* add scene-level animation channels */
2936  BEGIN_ANIMFILTER_SUBCHANNELS (expanded) {
2937  /* animation data filtering */
2938  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)sce, filter_mode);
2939  }
2941 
2942  /* did we find anything? */
2943  if (tmp_items) {
2944  /* include anim-expand widget first */
2945  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
2946  if (type != ANIMTYPE_NONE) {
2947  /* NOTE: active-status (and the associated checks) don't apply here... */
2948  ANIMCHANNEL_NEW_CHANNEL(cdata, type, sce, NULL);
2949  }
2950  }
2951 
2952  /* now add the list of collected channels */
2953  BLI_movelisttolist(anim_data, &tmp_data);
2954  BLI_assert(BLI_listbase_is_empty(&tmp_data));
2955  items += tmp_items;
2956  }
2957 
2958  /* return the number of items added to the list */
2959  return items;
2960 }
2961 
2963  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
2964 {
2965  ListBase tmp_data = {NULL, NULL};
2966  size_t tmp_items = 0;
2967  size_t items = 0;
2968 
2969  /* filter data contained under object first */
2971  bNodeTree *ntree = sce->nodetree;
2972  bGPdata *gpd = sce->gpd;
2973  World *wo = sce->world;
2974 
2975  /* Action, Drivers, or NLA for Scene */
2976  if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
2977  tmp_items += animdata_filter_ds_scene(ac, &tmp_data, ads, sce, filter_mode);
2978  }
2979 
2980  /* world */
2981  if ((wo) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
2982  tmp_items += animdata_filter_ds_world(ac, &tmp_data, ads, sce, wo, filter_mode);
2983  }
2984 
2985  /* nodetree */
2986  if ((ntree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
2987  tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
2988  }
2989 
2990  /* line styles */
2991  if ((ads->filterflag & ADS_FILTER_NOLINESTYLE) == 0) {
2992  tmp_items += animdata_filter_ds_linestyle(ac, &tmp_data, ads, sce, filter_mode);
2993  }
2994 
2995  /* grease pencil */
2996  if ((gpd) && !(ads->filterflag & ADS_FILTER_NOGPENCIL)) {
2997  tmp_items += animdata_filter_ds_gpencil(ac, &tmp_data, ads, gpd, filter_mode);
2998  }
2999 
3000  /* TODO: one day, when sequencer becomes its own datatype,
3001  * perhaps it should be included here. */
3002  }
3004 
3005  /* if we collected some channels, add these to the new list... */
3006  if (tmp_items) {
3007  /* firstly add object expander if required */
3008  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
3009  /* check if filtering by selection */
3010  if (ANIMCHANNEL_SELOK((sce->flag & SCE_DS_SELECTED))) {
3011  /* NOTE: active-status doesn't matter for this! */
3013  }
3014  }
3015 
3016  /* now add the list of collected channels */
3017  BLI_movelisttolist(anim_data, &tmp_data);
3018  BLI_assert(BLI_listbase_is_empty(&tmp_data));
3019  items += tmp_items;
3020  }
3021 
3022  /* return the number of items added */
3023  return items;
3024 }
3025 
3027  bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, MovieClip *clip, int filter_mode)
3028 {
3029  ListBase tmp_data = {NULL, NULL};
3030  size_t tmp_items = 0;
3031  size_t items = 0;
3032  /* add world animation channels */
3034  /* animation data filtering */
3035  tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)clip, filter_mode);
3036  }
3038  /* did we find anything? */
3039  if (tmp_items) {
3040  /* include data-expand widget first */
3041  if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
3042  /* check if filtering by active status */
3043  if (ANIMCHANNEL_ACTIVEOK(clip)) {
3045  }
3046  }
3047  /* now add the list of collected channels */
3048  BLI_movelisttolist(anim_data, &tmp_data);
3049  BLI_assert(BLI_listbase_is_empty(&tmp_data));
3050  items += tmp_items;
3051  }
3052  /* return the number of items added to the list */
3053  return items;
3054 }
3055 
3057  ListBase *anim_data,
3058  bDopeSheet *ads,
3059  int filter_mode)
3060 {
3061  size_t items = 0;
3062  MovieClip *clip;
3063  for (clip = ac->bmain->movieclips.first; clip != NULL; clip = clip->id.next) {
3064  /* only show if gpd is used by something... */
3065  if (ID_REAL_USERS(clip) < 1) {
3066  continue;
3067  }
3068  items += animdata_filter_ds_movieclip(ac, anim_data, ads, clip, filter_mode);
3069  }
3070  /* return the number of items added to the list */
3071  return items;
3072 }
3073 
3074 /* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */
3076  Base *base,
3077  const eObjectMode object_mode,
3078  int filter_mode)
3079 {
3080  Object *ob = base->object;
3081 
3082  if (base->object == NULL) {
3083  return false;
3084  }
3085 
3086  /* firstly, check if object can be included, by the following factors:
3087  * - if only visible, must check for layer and also viewport visibility
3088  * --> while tools may demand only visible, user setting takes priority
3089  * as user option controls whether sets of channels get included while
3090  * tool-flag takes into account collapsed/open channels too
3091  * - if only selected, must check if object is selected
3092  * - there must be animation data to edit (this is done recursively as we
3093  * try to add the channels)
3094  */
3095  if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
3096  /* layer visibility - we check both object and base, since these may not be in sync yet */
3097  if ((base->flag & BASE_VISIBLE_DEPSGRAPH) == 0 || (base->flag & BASE_VISIBLE_VIEWLAYER) == 0) {
3098  return false;
3099  }
3100 
3101  /* outliner restrict-flag */
3102  if (ob->visibility_flag & OB_HIDE_VIEWPORT) {
3103  return false;
3104  }
3105  }
3106 
3107  /* if only F-Curves with visible flags set can be shown, check that
3108  * data-block hasn't been set to invisible.
3109  */
3110  if (filter_mode & ANIMFILTER_CURVE_VISIBLE) {
3111  if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE)) {
3112  return false;
3113  }
3114  }
3115 
3116  /* Pinned curves are visible regardless of selection flags. */
3117  if ((ob->adt) && (ob->adt->flag & ADT_CURVES_ALWAYS_VISIBLE)) {
3118  return true;
3119  }
3120 
3121  /* Special case.
3122  * We don't do recursive checks for pin, but we need to deal with tricky
3123  * setup like animated camera lens without animated camera location.
3124  * Without such special handle here we wouldn't be able to bin such
3125  * camera data only animation to the editor.
3126  */
3127  if (ob->adt == NULL && ob->data != NULL) {
3128  AnimData *data_adt = BKE_animdata_from_id(ob->data);
3129  if (data_adt != NULL && (data_adt->flag & ADT_CURVES_ALWAYS_VISIBLE)) {
3130  return true;
3131  }
3132  }
3133 
3134  /* check selection and object type filters */
3135  if (ads->filterflag & ADS_FILTER_ONLYSEL) {
3136  if (object_mode & OB_MODE_POSE) {
3137  /* When in pose-mode handle all pose-mode objects.
3138  * This avoids problems with pose-mode where objects may be unselected,
3139  * where a selected bone of an unselected object would be hidden. see: T81922. */
3140  if (!(base->object->mode & object_mode)) {
3141  return false;
3142  }
3143  }
3144  else {
3145  /* only selected should be shown (ignore active) */
3146  if (!(base->flag & BASE_SELECTED)) {
3147  return false;
3148  }
3149  }
3150  }
3151 
3152  /* check if object belongs to the filtering group if option to filter
3153  * objects by the grouped status is on
3154  * - used to ease the process of doing multiple-character choreographies
3155  */
3156  if (ads->filter_grp != NULL) {
3157  if (BKE_collection_has_object_recursive(ads->filter_grp, ob) == 0) {
3158  return false;
3159  }
3160  }
3161 
3162  /* no reason to exclude this object... */
3163  return true;
3164 }
3165 
3166 /* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */
3167 static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
3168 {
3169  const Base *b1 = *((const Base **)base1_ptr);
3170  const Base *b2 = *((const Base **)base2_ptr);
3171 
3172  return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
3173 }
3174 
3175 /* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */
3177  ViewLayer *view_layer,
3178  int filter_mode,
3179  size_t *r_usable_bases)
3180 {
3181  /* Create an array with space for all the bases, but only containing the usable ones */
3182  size_t tot_bases = BLI_listbase_count(&view_layer->object_bases);
3183  size_t num_bases = 0;
3184 
3185  Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases");
3186  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
3187  if (animdata_filter_base_is_ok(ads, base, OB_MODE_OBJECT, filter_mode)) {
3188  sorted_bases[num_bases++] = base;
3189  }
3190  }
3191 
3192  /* Sort this list of pointers (based on the names) */
3193  qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp);
3194 
3195  /* Return list of sorted bases */
3196  *r_usable_bases = num_bases;
3197  return sorted_bases;
3198 }
3199 
3200 /* TODO: implement pinning...
3201  * (if and when pinning is done, what we need to do is to provide freeing mechanisms -
3202  * to protect against data that was deleted). */
3204  ListBase *anim_data,
3205  bDopeSheet *ads,
3206  int filter_mode)
3207 {
3208  Scene *scene = (Scene *)ads->source;
3209  ViewLayer *view_layer = (ViewLayer *)ac->view_layer;
3210  size_t items = 0;
3211 
3212  /* check that we do indeed have a scene */
3213  if ((ads->source == NULL) || (GS(ads->source->name) != ID_SCE)) {
3214  printf("Dope Sheet Error: No scene!\n");
3215  if (G.debug & G_DEBUG) {
3216  printf("\tPointer = %p, Name = '%s'\n",
3217  (void *)ads->source,
3218  (ads->source) ? ads->source->name : NULL);
3219  }
3220  return 0;
3221  }
3222 
3223  /* augment the filter-flags with settings based on the dopesheet filterflags
3224  * so that some temp settings can get added automagically...
3225  */
3226  if (ads->filterflag & ADS_FILTER_SELEDIT) {
3227  /* only selected F-Curves should get their keyframes considered for editability */
3228  filter_mode |= ANIMFILTER_SELEDIT;
3229  }
3230 
3231  /* Cache files level animations (frame duration and such). */
3233  CacheFile *cache_file = ac->bmain->cachefiles.first;
3234  for (; cache_file; cache_file = cache_file->id.next) {
3235  items += animdata_filter_ds_cachefile(ac, anim_data, ads, cache_file, filter_mode);
3236  }
3237  }
3238 
3239  /* movie clip's animation */
3241  items += animdata_filter_dopesheet_movieclips(ac, anim_data, ads, filter_mode);
3242  }
3243 
3244  /* Scene-linked animation - e.g. world, compositing nodes, scene anim
3245  * (including sequencer currently). */
3246  items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
3247 
3248  /* If filtering for channel drawing, we want the objects in alphabetical order,
3249  * to make it easier to predict where items are in the hierarchy
3250  * - This order only really matters
3251  * if we need to show all channels in the list (e.g. for drawing).
3252  * (XXX: What about lingering "active" flags? The order may now become unpredictable)
3253  * - Don't do this if this behavior has been turned off (i.e. due to it being too slow)
3254  * - Don't do this if there's just a single object
3255  */
3256  if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) &&
3257  (view_layer->object_bases.first != view_layer->object_bases.last)) {
3258  /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */
3259  /* TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort... */
3260  Base **sorted_bases;
3261  size_t num_bases;
3262 
3263  sorted_bases = animdata_filter_ds_sorted_bases(ads, view_layer, filter_mode, &num_bases);
3264  if (sorted_bases) {
3265  /* Add the necessary channels for these bases... */
3266  for (size_t i = 0; i < num_bases; i++) {
3267  items += animdata_filter_dopesheet_ob(ac, anim_data, ads, sorted_bases[i], filter_mode);
3268  }
3269 
3270  /* TODO: store something to validate whether any changes are needed? */
3271 
3272  /* free temporary data */
3273  MEM_freeN(sorted_bases);
3274  }
3275  }
3276  else {
3277  /* Filter and add contents of each base (i.e. object) without them sorting first
3278  * NOTE: This saves performance in cases where order doesn't matter
3279  */
3280  Object *obact = OBACT(view_layer);
3281  const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
3282  LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
3283  if (animdata_filter_base_is_ok(ads, base, object_mode, filter_mode)) {
3284  /* since we're still here, this object should be usable */
3285  items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
3286  }
3287  }
3288  }
3289 
3290  /* return the number of items in the list */
3291  return items;
3292 }
3293 
3294 /* Summary track for DopeSheet/Action Editor
3295  * - return code is whether the summary lets the other channels get drawn
3296  */
3298  ListBase *anim_data,
3299  int filter_mode,
3300  size_t *items)
3301 {
3302  bDopeSheet *ads = NULL;
3303 
3304  /* get the DopeSheet information to use
3305  * - we should only need to deal with the DopeSheet/Action Editor,
3306  * since all the other Animation Editors won't have this concept
3307  * being applicable.
3308  */
3309  if ((ac && ac->sl) && (ac->spacetype == SPACE_ACTION)) {
3310  SpaceAction *saction = (SpaceAction *)ac->sl;
3311  ads = &saction->ads;
3312  }
3313  else {
3314  /* invalid space type - skip this summary channels */
3315  return 1;
3316  }
3317 
3318  /* dopesheet summary
3319  * - only for drawing and/or selecting keyframes in channels, but not for real editing
3320  * - only useful for DopeSheet/Action/etc. editors where it is actually useful
3321  */
3322  if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
3324  if (ale) {
3325  BLI_addtail(anim_data, ale);
3326  (*items)++;
3327  }
3328 
3329  /* If summary is collapsed, don't show other channels beneath this - this check is put inside
3330  * the summary check so that it doesn't interfere with normal operation.
3331  */
3332  if (ads->flag & ADS_FLAG_SUMMARY_COLLAPSED) {
3333  return 0;
3334  }
3335  }
3336 
3337  /* the other channels beneath this can be shown */
3338  return 1;
3339 }
3340 
3341 /* ......................... */
3342 
3343 /* filter data associated with a channel - usually for handling summary-channels in DopeSheet */
3345  ListBase *anim_data,
3346  bDopeSheet *ads,
3347  bAnimListElem *channel,
3348  int filter_mode)
3349 {
3350  size_t items = 0;
3351 
3352  /* data to filter depends on channel type */
3353  /* NOTE: only common channel-types have been handled for now. More can be added as necessary */
3354  switch (channel->type) {
3355  case ANIMTYPE_SUMMARY:
3356  items += animdata_filter_dopesheet(ac, anim_data, ads, filter_mode);
3357  break;
3358 
3359  case ANIMTYPE_SCENE:
3360  items += animdata_filter_dopesheet_scene(ac, anim_data, ads, channel->data, filter_mode);
3361  break;
3362 
3363  case ANIMTYPE_OBJECT:
3364  items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
3365  break;
3366 
3367  case ANIMTYPE_DSCACHEFILE:
3368  items += animdata_filter_ds_cachefile(ac, anim_data, ads, channel->data, filter_mode);
3369  break;
3370 
3371  case ANIMTYPE_ANIMDATA:
3372  items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
3373  break;
3374 
3375  default:
3376  printf("ERROR: Unsupported channel type (%d) in animdata_filter_animchan()\n",
3377  channel->type);
3378  break;
3379  }
3380 
3381  return items;
3382 }
3383 
3384 /* ----------- Cleanup API --------------- */
3385 
3386 /* Remove entries with invalid types in animation channel list */
3387 static size_t animdata_filter_remove_invalid(ListBase *anim_data)
3388 {
3389  bAnimListElem *ale, *next;
3390  size_t items = 0;
3391 
3392  /* only keep entries with valid types */
3393  for (ale = anim_data->first; ale; ale = next) {
3394  next = ale->next;
3395 
3396  if (ale->type == ANIMTYPE_NONE) {
3397  BLI_freelinkN(anim_data, ale);
3398  }
3399  else {
3400  items++;
3401  }
3402  }
3403 
3404  return items;
3405 }
3406 
3407 /* Remove duplicate entries in animation channel list */
3408 static size_t animdata_filter_remove_duplis(ListBase *anim_data)
3409 {
3410  bAnimListElem *ale, *next;
3411  GSet *gs;
3412  size_t items = 0;
3413 
3414  /* build new hashtable to efficiently store and retrieve which entries have been
3415  * encountered already while searching
3416  */
3417  gs = BLI_gset_ptr_new(__func__);
3418 
3419  /* loop through items, removing them from the list if a similar item occurs already */
3420  for (ale = anim_data->first; ale; ale = next) {
3421  next = ale->next;
3422 
3423  /* check if hash has any record of an entry like this
3424  * - just use ale->data for now, though it would be nicer to involve
3425  * ale->type in combination too to capture corner cases
3426  * (where same data performs differently)
3427  */
3428  if (BLI_gset_add(gs, ale->data)) {
3429  /* this entry is 'unique' and can be kept */
3430  items++;
3431  }
3432  else {
3433  /* this entry isn't needed anymore */
3434  BLI_freelinkN(anim_data, ale);
3435  }
3436  }
3437 
3438  /* free the hash... */
3439  BLI_gset_free(gs, NULL);
3440 
3441  /* return the number of items still in the list */
3442  return items;
3443 }
3444 
3445 /* ----------- Public API --------------- */
3446 
3448  ListBase *anim_data,
3449  eAnimFilter_Flags filter_mode,
3450  void *data,
3451  eAnimCont_Types datatype)
3452 {
3453  size_t items = 0;
3454 
3455  /* only filter data if there's somewhere to put it */
3456  if (data && anim_data) {
3457  /* firstly filter the data */
3458  switch (datatype) {
3459  /* Action-Editing Modes */
3460  case ANIMCONT_ACTION: /* 'Action Editor' */
3461  {
3462  Object *obact = ac->obact;
3463  SpaceAction *saction = (SpaceAction *)ac->sl;
3464  bDopeSheet *ads = (saction) ? &saction->ads : NULL;
3465 
3466  /* specially check for AnimData filter, see T36687. */
3467  if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
3468  /* all channels here are within the same AnimData block, hence this special case */
3469  if (LIKELY(obact->adt)) {
3470  ANIMCHANNEL_NEW_CHANNEL(obact->adt, ANIMTYPE_ANIMDATA, (ID *)obact, NULL);
3471  }
3472  }
3473  else {
3474  /* The check for the DopeSheet summary is included here
3475  * since the summary works here too. */
3476  if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
3477  items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact);
3478  }
3479  }
3480 
3481  break;
3482  }
3483  case ANIMCONT_SHAPEKEY: /* 'ShapeKey Editor' */
3484  {
3485  Key *key = (Key *)data;
3486 
3487  /* specially check for AnimData filter, see T36687. */
3488  if (UNLIKELY(filter_mode & ANIMFILTER_ANIMDATA)) {
3489  /* all channels here are within the same AnimData block, hence this special case */
3490  if (LIKELY(key->adt)) {
3492  }
3493  }
3494  else {
3495  /* The check for the DopeSheet summary is included here
3496  * since the summary works here too. */
3497  if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
3498  items = animdata_filter_shapekey(ac, anim_data, key, filter_mode);
3499  }
3500  }
3501 
3502  break;
3503  }
3504 
3505  /* Modes for Specialty Data Types (i.e. not keyframes) */
3506  case ANIMCONT_GPENCIL: {
3507  if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
3508  items = animdata_filter_gpencil(ac, anim_data, data, filter_mode);
3509  }
3510  break;
3511  }
3512  case ANIMCONT_MASK: {
3513  if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
3514  items = animdata_filter_mask(ac->bmain, anim_data, data, filter_mode);
3515  }
3516  break;
3517  }
3518 
3519  /* DopeSheet Based Modes */
3520  case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
3521  {
3522  /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
3523  if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
3524  items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
3525  }
3526  break;
3527  }
3528  case ANIMCONT_FCURVES: /* Graph Editor -> F-Curves/Animation Editing */
3529  case ANIMCONT_DRIVERS: /* Graph Editor -> Drivers Editing */
3530  case ANIMCONT_NLA: /* NLA Editor */
3531  {
3532  /* all of these editors use the basic DopeSheet data for filtering options,
3533  * but don't have all the same features */
3534  items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
3535  break;
3536  }
3537 
3538  /* Timeline Mode - Basically the same as dopesheet,
3539  * except we only have the summary for now */
3540  case ANIMCONT_TIMELINE: {
3541  /* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
3542  if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items)) {
3543  items += animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
3544  }
3545  break;
3546  }
3547 
3548  /* Special/Internal Use */
3549  case ANIMCONT_CHANNEL: /* animation channel */
3550  {
3551  bDopeSheet *ads = ac->ads;
3552 
3553  /* based on the channel type, filter relevant data for this */
3554  items = animdata_filter_animchan(ac, anim_data, ads, data, filter_mode);
3555  break;
3556  }
3557 
3558  /* unhandled */
3559  default: {
3560  printf("ANIM_animdata_filter() - Invalid datatype argument %u\n", datatype);
3561  break;
3562  }
3563  }
3564 
3565  /* remove any 'weedy' entries */
3566  items = animdata_filter_remove_invalid(anim_data);
3567 
3568  /* remove duplicates (if required) */
3569  if (filter_mode & ANIMFILTER_NODUPLIS) {
3570  items = animdata_filter_remove_duplis(anim_data);
3571  }
3572  }
3573 
3574  /* return the number of items in the list */
3575  return items;
3576 }
3577 
3578 /* ************************************************************ */
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
struct AnimData * BKE_animdata_from_id(const struct ID *id)
bool BKE_collection_has_object_recursive(struct Collection *collection, struct Object *ob)
Definition: collection.c:921
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct SpaceLink * CTX_wm_space_data(const bContext *C)
Definition: context.c:743
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct FCurve * BKE_fcurve_find(ListBase *list, const char rna_path[], int array_index)
Definition: fcurve.c:249
#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
#define DRIVER_TARGETS_LOOPER_END
@ G_DEBUG
Definition: BKE_global.h:174
char * BKE_keyblock_curval_rnapath_get(const struct Key *key, const struct KeyBlock *kb)
struct Key * BKE_key_from_object(struct Object *ob)
Definition: key.c:1803
struct MaskLayer * BKE_mask_layer_active(struct Mask *mask)
Definition: mask.c:361
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:687
void BKE_modifiers_foreach_ID_link(struct Object *ob, IDWalkFunc walk, void *userData)
struct bNode * nodeFindNodebyName(struct bNodeTree *ntree, const char *name)
Definition: node.cc:1992
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
struct GSet GSet
Definition: BLI_ghash.h:340
GSet * BLI_gset_ptr_new(const char *info)
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:969
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t int BLI_string_max_possible_word_count(int str_len)
Definition: string.c:559
char * BLI_strncasestr(const char *s, const char *find, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:592
char * BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:538
int BLI_string_find_split_words(const char *str, size_t len, char delim, int r_words[][2], int words_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:1049
bool bool BLI_str_quoted_substr(const char *__restrict str, const char *__restrict prefix, char *result, size_t result_maxlen)
Definition: string.c:424
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define LIKELY(x)
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:553
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ ID_TE
Definition: DNA_ID_enums.h:52
@ ID_NT
Definition: DNA_ID_enums.h:68
@ ID_SCE
Definition: DNA_ID_enums.h:45
@ ID_OB
Definition: DNA_ID_enums.h:47
@ ID_PA
Definition: DNA_ID_enums.h:70
@ ADS_FILTER_NOMOVIECLIPS
@ ADS_FILTER_NOVOLUME
@ ADS_FILTER_NOHAIR
@ ADS_FILTER_NOCACHEFILES
@ ADS_FILTER_NOPOINTCLOUD
@ ADS_FILTER_ONLYSEL
@ ADS_FILTER_NOARM
@ ADS_FILTER_NLA_NOACT
@ ADS_FILTER_NOMAT
@ ADS_FILTER_NONTREE
@ ADS_FILTER_NOCAM
@ ADS_FILTER_NOSHAPEKEYS
@ ADS_FILTER_NOTEX
@ ADS_FILTER_ONLYNLA
@ ADS_FILTER_ONLY_ERRORS
@ ADS_FILTER_ONLYDRIVERS
@ ADS_FILTER_SELEDIT
@ ADS_FILTER_NOSCE
@ ADS_FILTER_NOLAM
@ ADS_FILTER_NOMODIFIERS
@ ADS_FILTER_NOLINESTYLE
@ ADS_FILTER_SUMMARY
@ ADS_FILTER_NOGPENCIL
@ ADS_FILTER_NOOBJ
@ ADS_FILTER_NOCUR
@ ADS_FILTER_NOPART
@ ADS_FILTER_NOMESH
@ ADS_FILTER_NOWOR
@ ADS_FILTER_INCL_HIDDEN
@ ADS_FILTER_NOMBA
@ ADS_FILTER_NOLAT
@ AGRP_ACTIVE
@ AGRP_NOTVISIBLE
@ ADS_FLAG_SUMMARY_COLLAPSED
@ ADS_FLAG_INVERT_FILTER
@ ADS_FLAG_NO_DB_SORT
@ ADS_FLAG_FUZZY_NAMES
@ SACTCONT_GPENCIL
@ SACTCONT_ACTION
@ SACTCONT_TIMELINE
@ SACTCONT_DOPESHEET
@ SACTCONT_SHAPEKEY
@ SACTCONT_MASK
@ SACTCONT_CACHEFILE
@ ADT_CURVES_ALWAYS_VISIBLE
@ ADT_CURVES_NOT_VISIBLE
@ ADT_NLA_SKEYS_COLLAPSED
@ DTAR_FLAG_INVALID
@ DRIVER_FLAG_INVALID
@ FCURVE_DISABLED
@ FCURVE_ACTIVE
@ FCURVE_VISIBLE
@ NLATRACK_ACTIVE
@ BONE_SELECTED
@ BONE_HIDDEN_P
@ GP_LAYER_ACTIVE
@ GP_DATA_ANNOTATIONS
@ KEY_RELATIVE
@ BASE_VISIBLE_VIEWLAYER
@ BASE_VISIBLE_DEPSGRAPH
@ BASE_SELECTED
@ VIEW_LAYER_FREESTYLE
#define NODE_SELECT
eObjectMode
@ OB_MODE_POSE
@ OB_MODE_OBJECT
Object is a sort of wrapper for general info.
@ OB_HIDE_VIEWPORT
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_GPENCIL
#define SCE_KEYS_NO_SELONLY
#define OBACT(_view_layer)
#define SCE_DS_SELECTED
@ SPACE_ACTION
@ SPACE_NLA
@ SPACE_GRAPH
@ SIPO_MODE_DRIVERS
@ SIPO_MODE_ANIMATION
@ SIPO_SELCUVERTSONLY
#define FILTER_SPK_OBJD(spk)
Definition: ED_anim_api.h:372
#define FILTER_CACHEFILE_OBJD(cf)
Definition: ED_anim_api.h:363
#define SEL_SHAPEKEY(kb)
Definition: ED_anim_api.h:402
eAnim_ChannelType
Definition: ED_anim_api.h:189
@ ANIMTYPE_DSSPK
Definition: ED_anim_api.h:222
@ ANIMTYPE_DSTEX
Definition: ED_anim_api.h:219
@ ANIMTYPE_SUMMARY
Definition: ED_anim_api.h:194
@ ANIMTYPE_DSNTREE
Definition: ED_anim_api.h:214
@ ANIMTYPE_NLACURVE
Definition: ED_anim_api.h:202
@ ANIMTYPE_SHAPEKEY
Definition: ED_anim_api.h:230
@ ANIMTYPE_DSMBALL
Definition: ED_anim_api.h:216
@ ANIMTYPE_DSCAM
Definition: ED_anim_api.h:209
@ ANIMTYPE_DSPOINTCLOUD
Definition: ED_anim_api.h:226
@ ANIMTYPE_FILLDRIVERS
Definition: ED_anim_api.h:205
@ ANIMTYPE_NONE
Definition: ED_anim_api.h:190
@ ANIMTYPE_DSPART
Definition: ED_anim_api.h:215
@ ANIMTYPE_DSLINESTYLE
Definition: ED_anim_api.h:221
@ ANIMTYPE_GROUP
Definition: ED_anim_api.h:198
@ ANIMTYPE_DSCUR
Definition: ED_anim_api.h:211
@ ANIMTYPE_SCENE
Definition: ED_anim_api.h:196
@ ANIMTYPE_DSARM
Definition: ED_anim_api.h:217
@ ANIMTYPE_NLACONTROLS
Definition: ED_anim_api.h:201
@ ANIMTYPE_GPLAYER
Definition: ED_anim_api.h:233
@ ANIMTYPE_MASKDATABLOCK
Definition: ED_anim_api.h:235
@ ANIMTYPE_ANIMDATA
Definition: ED_anim_api.h:191
@ ANIMTYPE_MASKLAYER
Definition: ED_anim_api.h:236
@ ANIMTYPE_DSSIMULATION
Definition: ED_anim_api.h:228
@ ANIMTYPE_DSGPENCIL
Definition: ED_anim_api.h:223
@ ANIMTYPE_DSLAT
Definition: ED_anim_api.h:220
@ ANIMTYPE_NLAACTION
Definition: ED_anim_api.h:239
@ ANIMTYPE_DSMCLIP
Definition: ED_anim_api.h:224
@ ANIMTYPE_DSMAT
Definition: ED_anim_api.h:207
@ ANIMTYPE_DSCACHEFILE
Definition: ED_anim_api.h:210
@ ANIMTYPE_DSVOLUME
Definition: ED_anim_api.h:227
@ ANIMTYPE_FCURVE
Definition: ED_anim_api.h:199
@ ANIMTYPE_DSLAM
Definition: ED_anim_api.h:208
@ ANIMTYPE_GPDATABLOCK
Definition: ED_anim_api.h:232
@ ANIMTYPE_FILLACTD
Definition: ED_anim_api.h:204
@ ANIMTYPE_OBJECT
Definition: ED_anim_api.h:197
@ ANIMTYPE_DSMESH
Definition: ED_anim_api.h:218
@ ANIMTYPE_NLATRACK
Definition: ED_anim_api.h:238
@ ANIMTYPE_DSWOR
Definition: ED_anim_api.h:213
@ ANIMTYPE_DSSKEY
Definition: ED_anim_api.h:212
@ ANIMTYPE_DSHAIR
Definition: ED_anim_api.h:225
#define EXPANDED_MCLIP(clip)
Definition: ED_anim_api.h:423
#define FILTER_NTREE_DATA(ntree)
Definition: ED_anim_api.h:379
#define FILTER_SKE_OBJD(key)
Definition: ED_anim_api.h:359
#define FILTER_MESH_OBJD(me)
Definition: ED_anim_api.h:370
#define EDITABLE_GPL(gpl)
Definition: ED_anim_api.h:408
#define SEL_AGRP(agrp)
Definition: ED_anim_api.h:395
#define EXPANDED_SCEC(sce)
Definition: ED_anim_api.h:350
#define SEL_MASKLAY(masklay)
Definition: ED_anim_api.h:416
#define SEL_GPL(gpl)
Definition: ED_anim_api.h:409
#define FILTER_ARM_OBJD(arm)
Definition: ED_anim_api.h:369
#define EDITABLE_AGRP(agrp)
Definition: ED_anim_api.h:391
#define EXPANDED_AGRP(ac, agrp)
Definition: ED_anim_api.h:392
#define FILTER_CAM_OBJD(ca)
Definition: ED_anim_api.h:362
@ ALE_SCE
Definition: ED_anim_api.h:256
@ ALE_NONE
Definition: ED_anim_api.h:249
@ ALE_GPFRAME
Definition: ED_anim_api.h:251
@ ALE_FCURVE
Definition: ED_anim_api.h:250
@ ALE_NLASTRIP
Definition: ED_anim_api.h:253
@ ALE_ALL
Definition: ED_anim_api.h:255
@ ALE_ACT
Definition: ED_anim_api.h:258
@ ALE_OB
Definition: ED_anim_api.h:257
@ ALE_GROUP
Definition: ED_anim_api.h:259
@ ALE_MASKLAY
Definition: ED_anim_api.h:252
#define FILTER_LATTICE_OBJD(lt)
Definition: ED_anim_api.h:371
#define FILTER_CURVES_OBJD(ha)
Definition: ED_anim_api.h:373
#define EXPANDED_ACTC(actc)
Definition: ED_anim_api.h:385
#define FILTER_LAM_OBJD(la)
Definition: ED_anim_api.h:361
eAnimCont_Types
Definition: ED_anim_api.h:102
@ ANIMCONT_DRIVERS
Definition: ED_anim_api.h:109
@ ANIMCONT_FCURVES
Definition: ED_anim_api.h:108
@ ANIMCONT_NLA
Definition: ED_anim_api.h:110
@ ANIMCONT_MASK
Definition: ED_anim_api.h:112
@ ANIMCONT_SHAPEKEY
Definition: ED_anim_api.h:105
@ ANIMCONT_TIMELINE
Definition: ED_anim_api.h:113
@ ANIMCONT_DOPESHEET
Definition: ED_anim_api.h:107
@ ANIMCONT_ACTION
Definition: ED_anim_api.h:104
@ ANIMCONT_NONE
Definition: ED_anim_api.h:103
@ ANIMCONT_GPENCIL
Definition: ED_anim_api.h:106
@ ANIMCONT_CHANNEL
Definition: ED_anim_api.h:111
#define EXPANDED_OBJC(ob)
Definition: ED_anim_api.h:356
#define SEL_FCU(fcu)
Definition: ED_anim_api.h:398
#define EDITABLE_SHAPEKEY(kb)
Definition: ED_anim_api.h:401
#define EDITABLE_FCU(fcu)
Definition: ED_anim_api.h:397
#define EDITABLE_MASK(masklay)
Definition: ED_anim_api.h:415
#define FILTER_CUR_OBJD(cu)
Definition: ED_anim_api.h:365
#define FILTER_MAT_OBJD(ma)
Definition: ED_anim_api.h:360
#define EDITABLE_NLT(nlt)
Definition: ED_anim_api.h:420
#define FILTER_WOR_SCED(wo)
Definition: ED_anim_api.h:352
#define FILTER_MBALL_OBJD(mb)
Definition: ED_anim_api.h:368
#define FILTER_LS_SCED(linestyle)
Definition: ED_anim_api.h:353
#define EXPANDED_DRVD(adt)
Definition: ED_anim_api.h:387
#define EXPANDED_MASK(mask)
Definition: ED_anim_api.h:413
#define SEL_ANIMDATA(adt)
Definition: ED_anim_api.h:429
#define FILTER_SIMULATION_OBJD(sim)
Definition: ED_anim_api.h:376
#define FILTER_POINTS_OBJD(pt)
Definition: ED_anim_api.h:374
#define EXPANDED_GPD(gpd)
Definition: ED_anim_api.h:406
#define FILTER_TEX_DATA(tex)
Definition: ED_anim_api.h:381
#define FILTER_VOLUME_OBJD(vo)
Definition: ED_anim_api.h:375
#define SEL_NLT(nlt)
Definition: ED_anim_api.h:419
eAnimFilter_Flags
Definition: ED_anim_api.h:284
@ ANIMFILTER_ACTIVE
Definition: ED_anim_api.h:303
@ ANIMFILTER_UNSEL
Definition: ED_anim_api.h:309
@ ANIMFILTER_FOREDIT
Definition: ED_anim_api.h:312
@ ANIMFILTER_ANIMDATA
Definition: ED_anim_api.h:322
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:292
@ ANIMFILTER_CURVE_VISIBLE
Definition: ED_anim_api.h:297
@ ANIMFILTER_SELEDIT
Definition: ED_anim_api.h:315
@ ANIMFILTER_LIST_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:300
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:325
@ ANIMFILTER_TMP_IGNORE_ONLYSEL
Definition: ED_anim_api.h:334
@ ANIMFILTER_FCURVESONLY
Definition: ED_anim_api.h:328
@ ANIMFILTER_SEL
Definition: ED_anim_api.h:308
@ ANIMFILTER_ACTGROUPED
Definition: ED_anim_api.h:305
#define FILTER_PART_OBJD(part)
Definition: ED_anim_api.h:366
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
NODE_GROUP
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
#define C
Definition: RandGen.cpp:25
#define MAX_MTEX
Definition: Stroke.h:31
struct bTheme * UI_GetTheme(void)
Definition: resources.c:1067
const bAnimChannelType * ANIM_channel_get_typeinfo(bAnimListElem *ale)
static size_t animdata_filter_ds_cachefile(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, CacheFile *cache_file, int filter_mode)
Definition: anim_filter.c:1966
bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
Definition: anim_filter.c:417
static bool nlaedit_get_context(bAnimContext *ac, SpaceNla *snla)
Definition: anim_filter.c:328
static bool fcurve_has_errors(const FCurve *fcu)
Definition: anim_filter.c:1212
static size_t animdata_filter_mask(Main *bmain, ListBase *anim_data, void *UNUSED(data), int filter_mode)
Definition: anim_filter.c:2027
static size_t animdata_filter_ds_nodetree_group(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
Definition: anim_filter.c:2073
static size_t animfilter_act_group(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, bActionGroup *agrp, int filter_mode, ID *owner_id)
Definition: anim_filter.c:1366
#define ANIMCHANNEL_SELOK(test_func)
Definition: anim_filter.c:583
static void animedit_get_yscale_factor(bAnimContext *ac)
Definition: anim_filter.c:98
static size_t animdata_filter_ds_scene(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
Definition: anim_filter.c:2906
static size_t animfilter_nla(bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
Definition: anim_filter.c:1506
static Key * actedit_get_shapekeys(bAnimContext *ac)
Definition: anim_filter.c:119
static bool skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
Definition: anim_filter.c:1031
static size_t animfilter_fcurves(ListBase *anim_data, bDopeSheet *ads, FCurve *first, eAnim_ChannelType fcurve_type, int filter_mode, void *owner, ID *owner_id, ID *fcurve_owner_id)
Definition: anim_filter.c:1321
static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
Definition: anim_filter.c:2786
static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, const eObjectMode object_mode, int filter_mode)
Definition: anim_filter.c:3075
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk)
Definition: anim_filter.c:512
static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
Definition: anim_filter.c:1922
static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
Definition: anim_filter.c:2143
static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, void *UNUSED(data), int filter_mode)
Definition: anim_filter.c:1846
static size_t animdata_filter_ds_movieclip(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, MovieClip *clip, int filter_mode)
Definition: anim_filter.c:3026
static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
Definition: anim_filter.c:3203
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:379
static Base ** animdata_filter_ds_sorted_bases(bDopeSheet *ads, ViewLayer *view_layer, int filter_mode, size_t *r_usable_bases)
Definition: anim_filter.c:3176
#define ANIMCHANNEL_ACTIVEOK(ale)
Definition: anim_filter.c:578
static size_t animdata_filter_ds_material(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Material *ma, int filter_mode)
Definition: anim_filter.c:2303
static size_t animdata_filter_remove_invalid(ListBase *anim_data)
Definition: anim_filter.c:3387
static size_t animdata_filter_gpencil_layers_data(ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
Definition: anim_filter.c:1752
static size_t animdata_filter_ds_obdata(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
Definition: anim_filter.c:2507
static bool name_matches_dopesheet_filter(bDopeSheet *ads, char *name)
Definition: anim_filter.c:1146
static bool skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, eAnim_ChannelType channel_type, void *owner, ID *owner_id)
Definition: anim_filter.c:1177
bool ANIM_animdata_context_getdata(bAnimContext *ac)
Definition: anim_filter.c:349
static void animfilter_modifier_idpoin_cb(void *afm_ptr, Object *ob, ID **idpoin, int UNUSED(cb_flag))
Definition: anim_filter.c:2377
#define ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, fcurve_owner_id, ale_statement)
Definition: anim_filter.c:556
static FCurve * animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, eAnim_ChannelType channel_type, int filter_mode, void *owner, ID *owner_id)
Definition: anim_filter.c:1249
static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAnimListElem *channel, int filter_mode)
Definition: anim_filter.c:3344
static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode)
Definition: anim_filter.c:1652
#define ANIMCHANNEL_NEW_CHANNEL(channel_data, channel_type, owner_id, fcurve_owner_id)
Definition: anim_filter.c:572
static size_t animdata_filter_ds_keyanim(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, Key *key, int filter_mode)
Definition: anim_filter.c:2695
static short animdata_filter_dopesheet_summary(bAnimContext *ac, ListBase *anim_data, int filter_mode, size_t *items)
Definition: anim_filter.c:3297
static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
Definition: anim_filter.c:3056
static size_t animdata_filter_gpencil_data(ListBase *anim_data, bDopeSheet *ads, bGPdata *gpd, int filter_mode)
Definition: anim_filter.c:1796
static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
Definition: anim_filter.c:3167
static size_t animdata_filter_ds_modifiers(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
Definition: anim_filter.c:2425
static size_t animdata_filter_ds_particles(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
Definition: anim_filter.c:2457
static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
Definition: anim_filter.c:2729
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3447
static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
Definition: anim_filter.c:2002
#define END_ANIMFILTER_SUBCHANNELS
Definition: anim_filter.c:461
static size_t animdata_filter_ds_world(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, World *wo, int filter_mode)
Definition: anim_filter.c:2866
static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
Definition: anim_filter.c:2962
static size_t animdata_filter_ds_texture(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Tex *tex, ID *owner_id, int filter_mode)
Definition: anim_filter.c:2204
static size_t animdata_filter_ds_textures(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
Definition: anim_filter.c:2257
static size_t animdata_filter_remove_duplis(ListBase *anim_data)
Definition: anim_filter.c:3408
static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
Definition: anim_filter.c:2111
static size_t animdata_filter_ds_materials(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
Definition: anim_filter.c:2342
#define BEGIN_ANIMFILTER_SUBCHANNELS(expanded_check)
Definition: anim_filter.c:443
static bool graphedit_get_context(bAnimContext *ac, SpaceGraph *sipo)
Definition: anim_filter.c:275
static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
Definition: anim_filter.c:146
static bAnimListElem * make_new_animlistelem(void *data, short datatype, ID *owner_id, ID *fcurve_owner_id)
Definition: anim_filter.c:604
static size_t animfilter_nla_controls(ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
Definition: anim_filter.c:1598
static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Key *key, int filter_mode)
Definition: anim_filter.c:1694
static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, ID *owner_id)
Definition: anim_filter.c:1456
#define ANIMCHANNEL_SELEDITOK(test_func)
Definition: anim_filter.c:596
struct tAnimFilterModifiersContext tAnimFilterModifiersContext
ListBase * ED_context_get_markers(const bContext *C)
Definition: anim_markers.c:88
#define SELECT
OperationNode * node
Scene scene
FreestyleLineStyle linestyle
Simulation simulation
bNodeTree * ntree
#define GS(x)
Definition: iris.c:225
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
static ulong * next
#define G(x, y, z)
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
Editing * SEQ_editing_get(const Scene *scene)
Definition: sequencer.c:241
Sequence * SEQ_select_active_get(Scene *scene)
Definition: strip_select.c:18
short regiontype
bAction * action
ListBase drivers
ListBase nla_tracks
short flag
struct Object * object
struct AnimData * adt
struct AnimData * adt
ListBase variables
struct AnimData * adt
struct DriverVar * next
ListBase * seqbasep
struct FCurve * next
bActionGroup * grp
char * rna_path
ChannelDriver * driver
short flag
struct FreestyleLineStyle * linestyle
struct FreestyleLineSet * next
struct AnimData * adt
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
void * next
Definition: DNA_ID.h:369
char name[66]
Definition: DNA_ID.h:378
short flag
Definition: DNA_key_types.h:42
char name[64]
Definition: DNA_key_types.h:52
struct KeyBlock * next
Definition: DNA_key_types.h:25
struct AnimData * adt
Definition: DNA_key_types.h:65
char type
Definition: DNA_key_types.h:94
ListBase block
Definition: DNA_key_types.h:84
struct AnimData * adt
struct AnimData * adt
struct bNodeTree * nodetree
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase masks
Definition: BKE_main.h:200
ListBase movieclips
Definition: BKE_main.h:199
ListBase gpencils
Definition: BKE_main.h:198
ListBase cachefiles
Definition: BKE_main.h:202
struct MaskLayer * next
struct AnimData * adt
int masklay_act
struct AnimData * adt
struct AnimData * adt
struct AnimData * adt
struct NlaStrip * next
ListBase fcurves
char name[64]
ListBase strips
struct NlaTrack * next
char name[64]
struct NlaTrack * prev
ListBase particlesystem
struct bPose * pose
ListBase modifiers
struct PartDeflect * pd
short visibility_flag
struct AnimData * adt
void * data
struct AnimData * adt
struct MTex * mtex[18]
ParticleSettings * part
struct ParticleSystem * next
struct AnimData * adt
struct bNodeTree * nodetree
struct MovieClip * clip
short flag
struct bGPdata * gpd
ListBase view_layers
struct AnimData * adt
struct World * world
struct Mask * mask
struct AnimData * adt
bAction * action
bDopeSheet ads
struct bDopeSheet * ads
struct bDopeSheet * ads
struct AnimData * adt
struct AnimData * adt
struct bNodeTree * nodetree
float keyframe_scale_fac
struct FreestyleConfig freestyle_config
struct ViewLayer * next
struct Base * basact
ListBase object_bases
struct AnimData * adt
struct AnimData * adt
struct bActionGroup * next
ListBase curves
ListBase groups
void(* name)(bAnimListElem *ale, char *name)
Definition: ED_anim_api.h:596
ListBase * markers
Definition: ED_anim_api.h:92
struct ARegion * region
Definition: ED_anim_api.h:76
struct Scene * scene
Definition: ED_anim_api.h:84
short spacetype
Definition: ED_anim_api.h:67
struct bDopeSheet * ads
Definition: ED_anim_api.h:79
short datatype
Definition: ED_anim_api.h:62
void * data
Definition: ED_anim_api.h:60
struct ScrArea * area
Definition: ED_anim_api.h:72
struct Object * obact
Definition: ED_anim_api.h:90
float yscale_fac
Definition: ED_anim_api.h:98
short regiontype
Definition: ED_anim_api.h:69
struct ViewLayer * view_layer
Definition: ED_anim_api.h:86
struct Main * bmain
Definition: ED_anim_api.h:82
struct SpaceLink * sl
Definition: ED_anim_api.h:74
struct Depsgraph * depsgraph
Definition: ED_anim_api.h:88
struct ID * fcurve_owner_id
Definition: ED_anim_api.h:175
struct bAnimListElem * next
Definition: ED_anim_api.h:127
void * key_data
Definition: ED_anim_api.h:146
struct AnimData * adt
Definition: ED_anim_api.h:162
struct ID * id
Definition: ED_anim_api.h:160
struct AnimData * adt
unsigned int layer
char searchstr[64]
struct Collection * filter_grp
char info[128]
ListBase frames
struct bGPDlayer * prev
ListBase layers
struct AnimData * adt
ListBase nodes
struct AnimData * adt
struct Bone * bone
ThemeSpace space_action
Sequence * SEQ_get_sequence_by_name(ListBase *seqbase, const char *name, bool recursive)
Definition: utils.c:422