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