Blender  V2.93
anim_deps.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.
17  * All rights reserved.
18  */
19 
24 #include <string.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_anim_types.h"
29 #include "DNA_armature_types.h"
30 #include "DNA_gpencil_types.h"
31 #include "DNA_mask_types.h"
32 #include "DNA_node_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_sequence_types.h"
36 
37 #include "BLI_blenlib.h"
38 #include "BLI_utildefines.h"
39 
40 #include "BKE_action.h"
41 #include "BKE_anim_data.h"
42 #include "BKE_context.h"
43 #include "BKE_fcurve.h"
44 #include "BKE_gpencil.h"
45 #include "BKE_main.h"
46 #include "BKE_node.h"
47 
48 #include "DEG_depsgraph.h"
49 
50 #include "RNA_access.h"
51 
52 #include "SEQ_sequencer.h"
53 #include "SEQ_utils.h"
54 
55 #include "ED_anim_api.h"
56 
57 /* **************************** depsgraph tagging ******************************** */
58 
59 /* tags the given anim list element for refreshes (if applicable)
60  * due to Animation Editor editing
61  */
63 {
64  ID *id;
65  FCurve *fcu;
66  AnimData *adt;
67 
68  id = ale->id;
69  if (!id) {
70  return;
71  }
72 
73  /* tag AnimData for refresh so that other views will update in realtime with these changes */
74  adt = BKE_animdata_from_id(id);
75  if (adt) {
77  if (adt->action != NULL) {
79  }
80  }
81 
82  /* Tag copy on the main object if updating anything directly inside AnimData */
83  if (ELEM(ale->type,
89  return;
90  }
91 
92  /* update data */
93  fcu = (ale->datatype == ALE_FCURVE) ? ale->key_data : NULL;
94 
95  if (fcu && fcu->rna_path) {
96  /* if we have an fcurve, call the update for the property we
97  * are editing, this is then expected to do the proper redraws
98  * and depsgraph updates */
99  PointerRNA id_ptr, ptr;
100  PropertyRNA *prop;
101 
102  RNA_id_pointer_create(id, &id_ptr);
103 
104  if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
105  RNA_property_update_main(bmain, scene, &ptr, prop);
106  }
107  }
108  else {
109  /* in other case we do standard depsgraph update, ideally
110  * we'd be calling property update functions here too ... */
113  ID_RECALC_ANIMATION); /* XXX or do we want something more restrictive? */
114  }
115 }
116 
117 /* tags the given ID block for refreshes (if applicable) due to
118  * Animation Editor editing */
119 void ANIM_id_update(Main *bmain, ID *id)
120 {
121  if (id) {
123  bmain,
124  id,
126  ID_RECALC_ANIMATION); /* XXX or do we want something more restrictive? */
127  }
128 }
129 
130 /* **************************** animation data <-> data syncing ******************************** */
131 /* This code here is used to synchronize the
132  * - selection (to find selected data easier)
133  * - ... (insert other relevant items here later)
134  * status in relevant Blender data with the status stored in animation channels.
135  *
136  * This should be called in the refresh() callbacks for various editors in
137  * response to appropriate notifiers.
138  */
139 
140 /* perform syncing updates for Action Groups */
141 static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGroup **active_agrp)
142 {
143  bActionGroup *agrp = (bActionGroup *)ale->data;
144  ID *owner_id = ale->id;
145 
146  /* major priority is selection status
147  * so we need both a group and an owner
148  */
149  if (ELEM(NULL, agrp, owner_id)) {
150  return;
151  }
152 
153  /* for standard Objects, check if group is the name of some bone */
154  if (GS(owner_id->name) == ID_OB) {
155  Object *ob = (Object *)owner_id;
156 
157  /* check if there are bones, and whether the name matches any
158  * NOTE: this feature will only really work if groups by default contain the F-Curves
159  * for a single bone.
160  */
161  if (ob->pose) {
162  bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name);
163  bArmature *arm = ob->data;
164 
165  if (pchan) {
166  bActionGroup *bgrp;
167 
168  /* if one matches, sync the selection status */
169  if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
170  agrp->flag |= AGRP_SELECTED;
171  }
172  else {
173  agrp->flag &= ~AGRP_SELECTED;
174  }
175 
176  /* also sync active group status */
177  if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) {
178  /* if no previous F-Curve has active flag, then we're the first and only one to get it */
179  if (*active_agrp == NULL) {
180  agrp->flag |= AGRP_ACTIVE;
181  *active_agrp = agrp;
182  }
183  else {
184  /* someone else has already taken it - set as not active */
185  agrp->flag &= ~AGRP_ACTIVE;
186  }
187  }
188  else {
189  /* this can't possibly be active now */
190  agrp->flag &= ~AGRP_ACTIVE;
191  }
192 
193  /* sync group colors */
194  bgrp = (bActionGroup *)BLI_findlink(&ob->pose->agroups, (pchan->agrp_index - 1));
195  if (bgrp) {
196  agrp->customCol = bgrp->customCol;
197  action_group_colors_sync(agrp, bgrp);
198  }
199  }
200  }
201  }
202 }
203 
205 {
206  ID *owner_id = ale->id;
207  BLI_assert(GS(owner_id->name) == ID_SCE);
208  Scene *scene = (Scene *)owner_id;
209  FCurve *fcu = (FCurve *)ale->data;
210 
211  /* only affect if F-Curve involves sequence_editor.sequences */
212  if (!strstr(fcu->rna_path, "sequences_all")) {
213  return;
214  }
215 
216  Editing *ed = SEQ_editing_get(scene, false);
217 
218  /* get strip name, and check if this strip is selected */
219  char *seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all[");
220  if (seq_name == NULL) {
221  return;
222  }
223 
224  Sequence *seq = SEQ_get_sequence_by_name(ed->seqbasep, seq_name, false);
225  MEM_freeN(seq_name);
226 
227  if (seq == NULL) {
228  return;
229  }
230 
231  /* update selection status */
232  if (seq->flag & SELECT) {
233  fcu->flag |= FCURVE_SELECTED;
234  }
235  else {
236  fcu->flag &= ~FCURVE_SELECTED;
237  }
238 }
239 
240 /* perform syncing updates for F-Curves */
242 {
243  FCurve *fcu = (FCurve *)ale->data;
244  ID *owner_id = ale->id;
245 
246  /* major priority is selection status, so refer to the checks done in anim_filter.c
247  * skip_fcurve_selected_data() for reference about what's going on here...
248  */
249  if (ELEM(NULL, fcu, fcu->rna_path, owner_id)) {
250  return;
251  }
252 
253  switch (GS(owner_id->name)) {
254  case ID_SCE:
256  break;
257  default:
258  break;
259  }
260 }
261 
262 /* perform syncing updates for GPencil Layers */
264 {
265  bGPDlayer *gpl = (bGPDlayer *)ale->data;
266 
267  /* Make sure the selection flags agree with the "active" flag.
268  * The selection flags are used in the Dopesheet only, whereas
269  * the active flag is used everywhere else. Hence, we try to
270  * sync these here so that it all seems to be have as the user
271  * expects - T50184
272  *
273  * Assume that we only really do this when the active status changes.
274  * (NOTE: This may prove annoying if it means selection is always lost)
275  */
276  if (gpl->flag & GP_LAYER_ACTIVE) {
277  gpl->flag |= GP_LAYER_SELECT;
278  }
279  else {
280  gpl->flag &= ~GP_LAYER_SELECT;
281  }
282 }
283 
284 /* ---------------- */
285 
286 /* Main call to be exported to animation editors */
288 {
289  bAnimContext ac;
290  ListBase anim_data = {NULL, NULL};
291  bAnimListElem *ale;
292  int filter;
293 
294  bActionGroup *active_agrp = NULL;
295 
296  /* get animation context info for filtering the channels */
297  if (ANIM_animdata_get_context(C, &ac) == 0) {
298  return;
299  }
300 
301  /* filter data */
302 
303  /* NOTE: we want all channels, since we want to be able to set selection status on some of them
304  * even when collapsed... however,
305  * don't include duplicates so that selection statuses don't override each other.
306  */
308  ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
309 
310  /* flush settings as appropriate depending on the types of the channels */
311  for (ale = anim_data.first; ale; ale = ale->next) {
312  switch (ale->type) {
313  case ANIMTYPE_GROUP:
314  animchan_sync_group(&ac, ale, &active_agrp);
315  break;
316 
317  case ANIMTYPE_FCURVE:
319  break;
320 
321  case ANIMTYPE_GPLAYER:
323  break;
324  }
325  }
326 
327  ANIM_animdata_freelist(&anim_data);
328 }
329 
331 {
332  bAnimListElem *ale;
333 
334  for (ale = anim_data->first; ale; ale = ale->next) {
335  if (ale->type == ANIMTYPE_GPLAYER) {
336  bGPDlayer *gpl = ale->data;
337 
338  if (ale->update & ANIM_UPDATE_ORDER) {
339  ale->update &= ~ANIM_UPDATE_ORDER;
340  if (gpl) {
342  }
343  }
344 
345  if (ale->update & ANIM_UPDATE_DEPS) {
346  ale->update &= ~ANIM_UPDATE_DEPS;
347  ANIM_list_elem_update(ac->bmain, ac->scene, ale);
348  }
349  /* disable handles to avoid crash */
350  if (ale->update & ANIM_UPDATE_HANDLES) {
351  ale->update &= ~ANIM_UPDATE_HANDLES;
352  }
353  }
354  else if (ale->datatype == ALE_MASKLAY) {
355  MaskLayer *masklay = ale->data;
356 
357  if (ale->update & ANIM_UPDATE_ORDER) {
358  ale->update &= ~ANIM_UPDATE_ORDER;
359  if (masklay) {
360  /* While correct & we could enable it: 'posttrans_mask_clean' currently
361  * both sorts and removes doubles, so this is not necessary here. */
362  // BKE_mask_layer_shape_sort(masklay);
363  }
364  }
365 
366  if (ale->update & ANIM_UPDATE_DEPS) {
367  ale->update &= ~ANIM_UPDATE_DEPS;
368  ANIM_list_elem_update(ac->bmain, ac->scene, ale);
369  }
370  /* Disable handles to avoid assert. */
371  if (ale->update & ANIM_UPDATE_HANDLES) {
372  ale->update &= ~ANIM_UPDATE_HANDLES;
373  }
374  }
375  else if (ale->datatype == ALE_FCURVE) {
376  FCurve *fcu = ale->key_data;
377 
378  if (ale->update & ANIM_UPDATE_ORDER) {
379  ale->update &= ~ANIM_UPDATE_ORDER;
380  if (fcu) {
381  sort_time_fcurve(fcu);
382  }
383  }
384 
385  if (ale->update & ANIM_UPDATE_HANDLES) {
386  ale->update &= ~ANIM_UPDATE_HANDLES;
387  if (fcu) {
388  calchandles_fcurve(fcu);
389  }
390  }
391 
392  if (ale->update & ANIM_UPDATE_DEPS) {
393  ale->update &= ~ANIM_UPDATE_DEPS;
394  ANIM_list_elem_update(ac->bmain, ac->scene, ale);
395  }
396  }
397  else if (ELEM(ale->type,
402  if (ale->update & ANIM_UPDATE_DEPS) {
403  ale->update &= ~ANIM_UPDATE_DEPS;
404  ANIM_list_elem_update(ac->bmain, ac->scene, ale);
405  }
406  }
407  else if (ale->update) {
408 #if 0
409  if (G.debug & G_DEBUG) {
410  printf("%s: Unhandled animchannel updates (%d) for type=%d (%p)\n",
411  __func__,
412  ale->update,
413  ale->type,
414  ale->data);
415  }
416 #endif
417  /* Prevent crashes in cases where it can't be handled */
418  ale->update = 0;
419  }
420 
421  BLI_assert(ale->update == 0);
422  }
423 }
424 
426 {
427 #ifndef NDEBUG
428  bAnimListElem *ale, *ale_next;
429  for (ale = anim_data->first; ale; ale = ale_next) {
430  ale_next = ale->next;
431  BLI_assert(ale->update == 0);
432  MEM_freeN(ale);
433  }
434  BLI_listbase_clear(anim_data);
435 #else
436  BLI_freelistN(anim_data);
437 #endif
438 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void action_group_colors_sync(struct bActionGroup *grp, const struct bActionGroup *ref_grp)
struct AnimData * BKE_animdata_from_id(struct ID *id)
Definition: anim_data.c:96
void sort_time_fcurve(struct FCurve *fcu)
Definition: fcurve.c:1429
void calchandles_fcurve(struct FCurve *fcu)
Definition: fcurve.c:1391
@ G_DEBUG
Definition: BKE_global.h:133
void BKE_gpencil_layer_frames_sort(struct bGPDlayer *gpl, bool *r_has_duplicate_frames)
Definition: gpencil.c:1640
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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 ELEM(...)
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:614
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_OB
Definition: DNA_ID_enums.h:59
@ AGRP_ACTIVE
@ AGRP_SELECTED
@ FCURVE_SELECTED
@ BONE_SELECTED
@ GP_LAYER_ACTIVE
@ GP_LAYER_SELECT
Object is a sort of wrapper for general info.
@ ANIMTYPE_NLACURVE
Definition: ED_anim_api.h:210
@ ANIMTYPE_GROUP
Definition: ED_anim_api.h:206
@ ANIMTYPE_GPLAYER
Definition: ED_anim_api.h:241
@ ANIMTYPE_ANIMDATA
Definition: ED_anim_api.h:199
@ ANIMTYPE_NLAACTION
Definition: ED_anim_api.h:247
@ ANIMTYPE_FCURVE
Definition: ED_anim_api.h:207
@ ANIMTYPE_NLATRACK
Definition: ED_anim_api.h:246
@ ALE_FCURVE
Definition: ED_anim_api.h:258
@ ALE_MASKLAY
Definition: ED_anim_api.h:260
@ ANIM_UPDATE_DEPS
Definition: ED_anim_api.h:275
@ ANIM_UPDATE_HANDLES
Definition: ED_anim_api.h:277
@ ANIM_UPDATE_ORDER
Definition: ED_anim_api.h:276
@ ANIMFILTER_DATA_VISIBLE
Definition: ED_anim_api.h:295
@ ANIMFILTER_LIST_CHANNELS
Definition: ED_anim_api.h:303
@ ANIMFILTER_NODUPLIS
Definition: ED_anim_api.h:328
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
static void animchan_sync_fcurve_scene(bAnimListElem *ale)
Definition: anim_deps.c:204
static void animchan_sync_fcurve(bAnimListElem *ale)
Definition: anim_deps.c:241
void ANIM_animdata_freelist(ListBase *anim_data)
Definition: anim_deps.c:425
static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGroup **active_agrp)
Definition: anim_deps.c:141
void ANIM_sync_animchannels_to_data(const bContext *C)
Definition: anim_deps.c:287
void ANIM_id_update(Main *bmain, ID *id)
Definition: anim_deps.c:119
void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale)
Definition: anim_deps.c:62
static void animchan_sync_gplayer(bAnimListElem *ale)
Definition: anim_deps.c:263
void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
Definition: anim_deps.c:330
bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
Definition: anim_filter.c:405
size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, eAnimFilter_Flags filter_mode, void *data, eAnimCont_Types datatype)
Definition: anim_filter.c:3442
#define SELECT
Scene scene
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:122
void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2322
bool RNA_path_resolve_property(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_access.c:5434
Editing * SEQ_editing_get(Scene *scene, bool alloc)
Definition: sequencer.c:232
bAction * action
ListBase * seqbasep
char * rna_path
short flag
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
struct bPose * pose
void * data
struct Scene * scene
Definition: ED_anim_api.h:97
short datatype
Definition: ED_anim_api.h:75
void * data
Definition: ED_anim_api.h:73
struct Object * obact
Definition: ED_anim_api.h:103
struct Main * bmain
Definition: ED_anim_api.h:95
struct bAnimListElem * next
Definition: ED_anim_api.h:135
void * key_data
Definition: ED_anim_api.h:154
struct ID * id
Definition: ED_anim_api.h:168
struct Bone * bone
ListBase agroups
#define G(x, y, z)
Sequence * SEQ_get_sequence_by_name(ListBase *seqbase, const char *name, bool recursive)
Definition: utils.c:487
PointerRNA * ptr
Definition: wm_files.c:3157